diff --git a/src/modules/netinstall/CMakeLists.txt b/src/modules/netinstall/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..363c1dab300755722c90777a9241fa283b3833f1
--- /dev/null
+++ b/src/modules/netinstall/CMakeLists.txt
@@ -0,0 +1,18 @@
+include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui )
+
+calamares_add_plugin( netinstall
+    TYPE viewmodule
+    EXPORT_MACRO PLUGINDLLEXPORT_PRO
+    SOURCES
+        NetInstallViewStep.cpp
+        NetInstallPage.cpp
+        widgets/groupselectionwidget.cpp
+    UI
+        page_netinst.ui
+        widgets/groupselectionwidget.ui
+    RESOURCES
+        netinstall.qrc
+    LINK_LIBRARIES
+        calamaresui
+    SHARED_LIB
+)
diff --git a/src/modules/netinstall/NetInstallPage.cpp b/src/modules/netinstall/NetInstallPage.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0e3a18c95facfd60bbec09bc9f2100467fbea9ca
--- /dev/null
+++ b/src/modules/netinstall/NetInstallPage.cpp
@@ -0,0 +1,170 @@
+/*
+ *   Copyright 2016, Luca Giambonini <almack@chakraos.org>
+ *   Copyright 2016, Lisa Vitolo     <shainer@chakraos.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "NetInstallPage.h"
+
+#include "widgets/groupselectionwidget.h"
+#include "ui_page_netinst.h"
+#include "GlobalStorage.h"
+#include "JobQueue.h"
+#include "utils/Logger.h"
+#include "utils/YamlUtils.h"
+
+#include <QFile>
+#include <QMap>
+#include <QTextStream>
+
+#include <QNetworkAccessManager>
+#include <QNetworkRequest>
+#include <QNetworkReply>
+
+#include <QtDebug>
+#include <QtGlobal>
+#include <QWidget>
+#include <QSignalMapper>
+
+#include <yaml-cpp/yaml.h>
+
+using CalamaresUtils::yamlToVariant;
+
+NetInstallPage::NetInstallPage( QWidget* parent )
+    : QWidget( parent )
+    , ui( new Ui::Page_NetInst )
+    , m_networkManager( this )
+{
+    ui->setupUi( this );
+}
+
+bool
+NetInstallPage::isReady()
+{
+    // nothing to wait for, the data are immediately ready
+    // if the user does not select any group nothing is installed
+    return true;
+}
+
+void NetInstallPage::readGroups( const QByteArray& yamlData )
+{
+    YAML::Node groups = YAML::Load( yamlData.constData() );
+    Q_ASSERT( groups.IsSequence() );
+
+    for ( YAML::const_iterator it = groups.begin(); it != groups.end(); ++it )
+    {
+        const YAML::Node groupDefinition = *it;
+
+        QString name( tr( yamlToVariant(groupDefinition["name"]).toByteArray() ) );
+        QString description( tr( yamlToVariant(groupDefinition["description"]).toByteArray() ) );
+        QStringList packages;
+
+        for ( YAML::const_iterator it = groupDefinition["packages"].begin();
+                it != groupDefinition["packages"].end(); ++it )
+            packages.append( yamlToVariant(*it).toString() );
+
+        m_groups[name].name = name;
+        m_groups[name].description = description;
+        m_groups[name].packages = packages;
+
+        if ( groupDefinition["selected"] )
+            m_groups[name].selected = yamlToVariant( groupDefinition["selected"] ).toBool();
+
+        if ( groupDefinition["hidden"] )
+            m_groups[name].hidden = yamlToVariant( groupDefinition["hidden"] ).toBool();
+
+        m_groupOrder.append( name );
+    }
+}
+
+void
+NetInstallPage::dataIsHere( QNetworkReply* reply )
+{
+    if ( reply->error() != QNetworkReply::NoError )
+    {
+        cDebug() << reply->errorString();
+        ui->netinst_status->setText( tr( "Network Installation. (Disabled: Unable to fetch package lists, check your network connection)" ) );
+        return;
+    }
+
+    readGroups( reply->readAll() );
+
+    QSignalMapper* mapper = new QSignalMapper( this );
+    foreach ( const QString& groupKey, m_groupOrder )
+    {
+        Group group = m_groups[groupKey];
+        if ( group.hidden )
+        {
+            // Do not present on view.
+            continue;
+        }
+
+        GroupSelectionWidget* groupWidget = new GroupSelectionWidget( group.name, group.description, group.packages, this );
+        m_groupWidgets.insert( groupKey, groupWidget );
+        ui->groupswidget->layout()->addWidget( groupWidget );
+
+        mapper->setMapping( groupWidget, groupKey );
+        connect( groupWidget, &GroupSelectionWidget::toggled, mapper,
+                 static_cast<void(QSignalMapper::*)()>(&QSignalMapper::map) );
+    }
+
+    reply->deleteLater();
+    emit checkReady( isReady() );
+}
+
+QStringList NetInstallPage::selectedPackages() const
+{
+    QStringList selectedPackages;
+
+    // Add all the packages for groups that are toggled in the view.
+    for ( auto it = m_groupWidgets.constBegin(); it != m_groupWidgets.constEnd(); it++ )
+    {
+        if ( it.value()->isToggled() )
+            selectedPackages += m_groups[it.key()].packages;
+    }
+
+    // Add all the packages for groups that are hidden but selected.
+    for ( const Group& group : m_groups.values() )
+    {
+        if ( group.hidden && group.selected )
+            selectedPackages += group.packages;
+    }
+
+    return selectedPackages;
+}
+
+void NetInstallPage::loadGroupList()
+{
+    QString confUrl(
+        Calamares::JobQueue::instance()->globalStorage()->value(
+            "groupsUrl" ).toString() );
+
+    QNetworkRequest request;
+    request.setUrl( QUrl( confUrl ) );
+    // Follows all redirects except unsafe ones (https to http).
+    request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
+    // Not everybody likes the default User Agent used by this class (looking at you,
+    // sourceforge.net), so let's set a more descriptive one.
+    request.setRawHeader( "User-Agent", "Mozilla/5.0 (compatible; Calamares)" );
+
+    connect(&m_networkManager, &QNetworkAccessManager::finished,
+            this, &NetInstallPage::dataIsHere);
+    m_networkManager.get(request);
+}
+
+void NetInstallPage::onActivate()
+{
+    ui->groupswidget->setFocus();
+}
diff --git a/src/modules/netinstall/NetInstallPage.h b/src/modules/netinstall/NetInstallPage.h
new file mode 100644
index 0000000000000000000000000000000000000000..5145fdb23ca6a7515cc0d5887f98961c82678fb4
--- /dev/null
+++ b/src/modules/netinstall/NetInstallPage.h
@@ -0,0 +1,101 @@
+/*
+ *   Copyright 2016, Luca Giambonini <almack@chakraos.org>
+ *   Copyright 2016, Lisa Vitolo     <shainer@chakraos.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETINSTALLPAGE_H
+#define NETINSTALLPAGE_H
+
+#include "Typedefs.h"
+#include <QWidget>
+#include <QAbstractButton>
+#include <QNetworkAccessManager>
+
+// required forward declarations
+class QByteArray;
+class QNetworkReply;
+class GroupSelectionWidget;
+
+namespace Ui
+{
+class Page_NetInst;
+}
+
+class NetInstallPage : public QWidget
+{
+    Q_OBJECT
+
+    // Internal representation of a package group.
+    struct Group
+    {
+        Group()
+            : Group( "","",false, false ) { }
+        Group( QString name, QString description, bool selected, bool hidden )
+            : name( name ), description( description ), selected( selected ), hidden( hidden ) { }
+        Group( QString name, QString description )
+            : Group( name, description, false, false ) { }
+
+        QString name;
+        QString description;
+        QStringList packages;
+
+        // See README.md for a description of these two fields.
+        bool selected = false;
+        bool hidden = false;
+    };
+
+public:
+    NetInstallPage( QWidget* parent = nullptr );
+
+    void onActivate();
+
+    bool isReady();
+
+    // Retrieves the groups, with name, description and packages, from
+    // the remote URL configured in the settings. Assumes the URL is already
+    // in the global storage. This should be called before displaying the page.
+    void loadGroupList();
+
+    // Returns the list of packages belonging to groups that are
+    // selected in the view in this given moment. No data is cached here, so
+    // this function does not have constant time.
+    QStringList selectedPackages() const;
+
+public slots:
+    void dataIsHere( QNetworkReply* );
+
+signals:
+    void checkReady( bool );
+
+private:
+    // Takes the YAML data representing the groups and reads them into the
+    // m_groups and m_groupOrder internal structures. See the README.md
+    // of this module to know the format expected of the YAML files.
+    void readGroups( const QByteArray& yamlData );
+
+    Ui::Page_NetInst* ui;
+
+    // Handles connection with the remote URL storing the configuration.
+    QNetworkAccessManager m_networkManager;
+
+    QHash<QString, Group> m_groups;
+    // For each group name, store the selection widget to retrieve UI
+    // properties.
+    QHash<QString, GroupSelectionWidget*> m_groupWidgets;
+    QList<QString> m_groupOrder;
+};
+
+#endif // NETINSTALLPAGE_H
diff --git a/src/modules/netinstall/NetInstallViewStep.cpp b/src/modules/netinstall/NetInstallViewStep.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..333debd9b85eb446ed8b4f3d2cc7d07a8304dd17
--- /dev/null
+++ b/src/modules/netinstall/NetInstallViewStep.cpp
@@ -0,0 +1,151 @@
+/*
+ *   Copyright 2016, Luca Giambonini <almack@chakraos.org>
+ *   Copyright 2016, Lisa Vitolo <shainer@chakraos.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "NetInstallViewStep.h"
+
+#include "JobQueue.h"
+#include "GlobalStorage.h"
+#include "utils/Logger.h"
+
+#include "NetInstallPage.h"
+
+CALAMARES_PLUGIN_FACTORY_DEFINITION( NetInstallViewStepFactory, registerPlugin<NetInstallViewStep>(); )
+
+NetInstallViewStep::NetInstallViewStep( QObject* parent )
+    : Calamares::ViewStep( parent )
+    , m_widget( new NetInstallPage() )
+    , m_nextEnabled( true )
+{
+    emit nextStatusChanged( true );
+    connect( m_widget, &NetInstallPage::checkReady,
+             this, &NetInstallViewStep::nextStatusChanged );
+}
+
+
+NetInstallViewStep::~NetInstallViewStep()
+{
+    if ( m_widget && m_widget->parent() == nullptr )
+        m_widget->deleteLater();
+}
+
+
+QString
+NetInstallViewStep::prettyName() const
+{
+    return tr( "Package selection" );
+}
+
+
+QString
+NetInstallViewStep::prettyStatus() const
+{
+    return m_prettyStatus;
+}
+
+
+QWidget*
+NetInstallViewStep::widget()
+{
+    return m_widget;
+}
+
+
+void
+NetInstallViewStep::next()
+{
+    emit done();
+}
+
+
+void
+NetInstallViewStep::back()
+{}
+
+
+bool
+NetInstallViewStep::isNextEnabled() const
+{
+    return m_nextEnabled;
+}
+
+
+bool
+NetInstallViewStep::isBackEnabled() const
+{
+    return true;
+}
+
+
+bool
+NetInstallViewStep::isAtBeginning() const
+{
+    return true;
+}
+
+
+bool
+NetInstallViewStep::isAtEnd() const
+{
+    return true;
+}
+
+
+QList< Calamares::job_ptr >
+NetInstallViewStep::jobs() const
+{
+    return m_jobs;
+}
+
+
+void
+NetInstallViewStep::onActivate()
+{
+    m_widget->onActivate();
+}
+
+
+void
+NetInstallViewStep::onLeave()
+{
+    cDebug() << "Leaving netinstall, adding packages to be installed"
+             << "to global storage";
+
+    if ( !m_widget->selectedPackages().empty() )
+    {
+        QMap<QString, QVariant> packagesWithOperation;
+        // Gets all packages selected in the page; includes groups that are
+        // selected by default but not displayed.
+        packagesWithOperation.insert( "install", m_widget->selectedPackages() );
+
+        Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
+        gs->insert( "packageOperations", QVariant( packagesWithOperation ) );
+    }
+}
+
+
+void
+NetInstallViewStep::setConfigurationMap( const QVariantMap& configurationMap )
+{
+    if ( configurationMap.contains( "groupsUrl" ) &&
+            configurationMap.value( "groupsUrl" ).type() == QVariant::String )
+    {
+        Calamares::JobQueue::instance()->globalStorage()->insert(
+            "groupsUrl", configurationMap.value( "groupsUrl" ).toString() );
+        m_widget->loadGroupList();
+    }
+}
diff --git a/src/modules/netinstall/NetInstallViewStep.h b/src/modules/netinstall/NetInstallViewStep.h
new file mode 100644
index 0000000000000000000000000000000000000000..de4d411d81f39b1a9f967b9b5afe0567b124d760
--- /dev/null
+++ b/src/modules/netinstall/NetInstallViewStep.h
@@ -0,0 +1,72 @@
+/*
+ *   Copyright 2016, Luca Giambonini <almack@chakraos.org>
+ *   Copyright 2016, Lisa Vitolo     <shainer@chakraos.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef NETINSTALLVIEWSTEP_H
+#define NETINSTALLVIEWSTEP_H
+
+#include <utils/PluginFactory.h>
+#include <viewpages/ViewStep.h>
+
+#include <PluginDllMacro.h>
+
+#include <QVariant>
+
+class NetInstallPage;
+
+class PLUGINDLLEXPORT NetInstallViewStep : public Calamares::ViewStep
+{
+    Q_OBJECT
+
+public:
+    explicit NetInstallViewStep( QObject* parent = nullptr );
+    virtual ~NetInstallViewStep();
+
+    QString prettyName() const override;
+    QString prettyStatus() const override;
+
+    QWidget* widget() override;
+
+    void next() override;
+    void back() override;
+
+    bool isNextEnabled() const override;
+    bool isBackEnabled() const override;
+
+    bool isAtBeginning() const override;
+    bool isAtEnd() const override;
+
+    QList< Calamares::job_ptr > jobs() const override;
+
+    void onActivate() override;
+
+    // Leaving the page; store all selected packages for later installation.
+    void onLeave() override;
+
+    void setConfigurationMap( const QVariantMap& configurationMap ) override;
+
+private:
+    NetInstallPage* m_widget;
+    bool m_nextEnabled;
+    QString m_prettyStatus;
+
+    QList< Calamares::job_ptr > m_jobs;
+};
+
+CALAMARES_PLUGIN_FACTORY_DECLARATION( NetInstallViewStepFactory )
+
+#endif // NETINSTALLVIEWSTEP_H
diff --git a/src/modules/netinstall/README.md b/src/modules/netinstall/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..790691e1b9b13a720c33e05fdba4914ded4ad14c
--- /dev/null
+++ b/src/modules/netinstall/README.md
@@ -0,0 +1,66 @@
+# Netinstall module
+
+The netinstall module allows distribution maintainers to ship minimal ISOs with only a basic set of preinstall packages.
+At installation time, the user is presented with the choice to install groups of packages from a predefined list.
+
+Calamares will then invoke the correct backend to install the packages.
+
+## Configuration of the packages
+Every distribution can choose which groups to display and which packages should be in the groups.
+
+The *netinstall.conf* file should have this format:
+
+    ----
+    groupsUrl: <URL to YAML file>
+
+The URL must point to a YAML file. Here is a short example of how the YAML file should look.
+
+      - name: "Group name"
+      description: "Description of the group"
+      packages:
+        - lsb-release
+        - avahi
+        - grub
+      - name: "Second group name"
+      ...
+
+
+The file is composed of a list of entry, each describing one group. The keys *name*, *description* and *packages* are required.
+
+Two more keys are supported, *hidden* (if true, do not show the group on the page) and *selected* (if true, display the group as selected). Both default to false if not present.
+If both keys are set to true for the same group, you are basically creating a "default" group of packages which will always be installed in the user's system.
+
+## Configuration of the module
+Here is the set of instructions to have the module work in your Calamares. As of July 2016, this has been successfully 
+tested using the live installation of Chakra Fermi.
+
+First, if the module is used, we need to require a working Internet connection, otherwise the module will be
+unable to fetch the package groups and to perform the installation. Requirements for the Calamares instance
+are configured in the **welcome.conf** file (configuration for the **welcome** module). Make sure *internet*
+is listed below *required*.
+
+In the *settings.conf* file, decide where the **netinstall** page should be displayed. I put it just after the
+**welcome** page, but any position between that and just before **partition** should make no difference.
+
+If not present, add the **packages** job in the **exec** list. This is the job that calls the package manager
+to install packages. Make sure it is configured to use the correct package manager for your distribution; this
+is configured in src/modules/packages/packages.conf.
+
+The exec list should be:
+
+  - unpackfs
+  - networkcfg
+  - packages
+
+**unpackfs** creates the chroot where the installation is performed, and unpacks the root image with the filesystem
+structure; **networkcfg** set ups a working network in the chroot; and finally **packages** can install packages
+in the chroot.
+
+## Common issues
+If launching the package manager command returns you negative exit statuses and nothing is actually invoked, this
+is likely an error in the setup of the chroot; check that the parameter **rootMountPoint** is set to the correct
+value in the Calamares configuration.
+
+If the command is run, but exits with error, check that the network is working in the chroot. Make sure /etc/resolv.conf
+exists and that it's not empty.
+
diff --git a/src/modules/netinstall/images/arrow-down.png b/src/modules/netinstall/images/arrow-down.png
new file mode 100644
index 0000000000000000000000000000000000000000..f1b8569daac05298e3d82f117d76b7a4633926b4
Binary files /dev/null and b/src/modules/netinstall/images/arrow-down.png differ
diff --git a/src/modules/netinstall/images/arrow-up.png b/src/modules/netinstall/images/arrow-up.png
new file mode 100644
index 0000000000000000000000000000000000000000..18679693d14833d8a9ef74aa5b63285d4e0475a3
Binary files /dev/null and b/src/modules/netinstall/images/arrow-up.png differ
diff --git a/src/modules/netinstall/module.desc b/src/modules/netinstall/module.desc
new file mode 100644
index 0000000000000000000000000000000000000000..f39082eba8b5eb3ab9b15e2ad823e5409522b0fd
--- /dev/null
+++ b/src/modules/netinstall/module.desc
@@ -0,0 +1,7 @@
+# Module metadata file for netinstall module
+# Syntax is YAML 1.2
+---
+type:      "view"
+name:      "netinstall"
+interface: "qtplugin"
+load:      "libcalamares_viewmodule_netinstall.so"
diff --git a/src/modules/netinstall/netinstall.conf b/src/modules/netinstall/netinstall.conf
new file mode 100644
index 0000000000000000000000000000000000000000..b87aef43ef538cc07c5fad71de7ed80141e5d4c6
--- /dev/null
+++ b/src/modules/netinstall/netinstall.conf
@@ -0,0 +1,2 @@
+---
+groupsUrl: http://chakraos.org/netinstall.php
diff --git a/src/modules/netinstall/netinstall.qrc b/src/modules/netinstall/netinstall.qrc
new file mode 100644
index 0000000000000000000000000000000000000000..ab49ebf4f0e5c8d37d1d7edbf302a40f28aed6f2
--- /dev/null
+++ b/src/modules/netinstall/netinstall.qrc
@@ -0,0 +1,6 @@
+<RCC>
+    <qresource prefix="/">
+        <file>images/arrow-up.png</file>
+        <file>images/arrow-down.png</file>
+    </qresource>
+</RCC>
diff --git a/src/modules/netinstall/netinstall.yaml b/src/modules/netinstall/netinstall.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e3718831256e1c7ca9fd593e63b2579a2d777ba8
--- /dev/null
+++ b/src/modules/netinstall/netinstall.yaml
@@ -0,0 +1,246 @@
+- name: "Default"
+  description: "Default group"
+  hidden: true
+  selected: true
+  packages:
+    - base
+    - chakra-live-skel
+    - cdemu-client
+    - lsb-release
+    - avahi
+    - grub
+    # disk utils
+    - dosfstools
+    - e2fsprogs
+    - fuse
+    - gptfdisk
+    - jfsutils
+    - ntfs-3g
+    - reiserfsprogs
+    - xfsprogs
+    # power
+    - acpi_call
+    - pmtools
+    # network
+    - dnsutils
+    - iputils
+    - netcfg
+    - xinetd
+    # firmwares
+    - alsa-firmware
+    - linux-firmware
+    # sound
+    - alsa-lib
+    - alsa-utils
+    - gstreamer
+    - gst-plugins-good
+    - gst-plugins-bad
+    - libao
+    - libcanberra-gstreamer
+    - libcanberra-pulse
+    - pulseaudio
+    - pulseaudio-alsa
+    # tools
+    - bash-completion
+    - hwinfo
+    - lsof
+    - man-db
+    - mlocate
+    - nano
+    - openssh
+    - sudo
+    - vim
+    - zsh # :D
+    # archivers
+    - p7zip
+    - unarj
+    - unrar
+    - unzip
+    - zip
+    # xorg base
+    - xorg
+    - xorg-apps
+    - xorg-fonts-alias
+    - xorg-fonts-encodings
+    - xorg-fonts-misc
+    - xorg-res-utils
+    - xorg-server
+    - xorg-server-utils
+    - xorg-xauth
+    - xorg-xinit
+    - xorg-xkb-utils
+    # xorg video drivers
+    - xf86-video-apm
+    - xf86-video-ark
+    - xf86-video-ati
+    - xf86-video-chips
+    - xf86-video-cirrus
+    - xf86-video-glint
+    - xf86-video-i128
+    - xf86-video-i740
+    - xf86-video-intel
+    - xf86-video-mach64
+    - xf86-video-mga
+    - xf86-video-neomagic
+    - xf86-video-nouveau
+    - xf86-video-nv
+    - xf86-video-openchrome
+    - xf86-video-r128
+    - xf86-video-rendition
+    - xf86-video-s3
+    - xf86-video-s3virge
+    - xf86-video-savage
+    - xf86-video-siliconmotion
+    - xf86-video-sisusb
+    - xf86-video-tdfx
+    - xf86-video-trident
+    - xf86-video-tseng
+    - xf86-video-v4l
+    - xf86-video-vesa
+    - xf86-video-voodoo
+    - mesa-libgl
+    # xorg input drivers
+    - xf86-input-synaptics
+    - xf86-input-wacom
+    - xf86-input-evdev
+    - xf86-input-keyboard
+    - xf86-input-mouse
+    # fonts
+    - terminus-font
+    - ttf-dejavu
+    - ttf-liberation
+    - wqy-microhei
+    - xorg-fonts-100dpi
+    - xorg-fonts-75dpi
+    - xorg-fonts-cyrillic
+    # additional stuff that needs xorg
+    - hicolor-icon-theme
+    # kde
+    - chakra-common
+    - qt
+    - kde-baseapps
+    - kde-baseapps-dolphin
+    - kde-baseapps-konsole
+    - kde-runtime
+    - kde-workspace
+    - kdelibs
+    - kdepimlibs
+    - kdemultimedia-kmix
+    - oxygen-icons
+    - phonon-backend-gstreamer
+    # chakra theme (including kapudan options)
+    - chakra-wallpapers-dharma
+    - chakra-wallpapers-curie
+    - chakra-wallpapers-descartes
+    - grub2-themes-sirius
+    - kapudan-kde-themes-caledonia
+    - kde-kdm-themes-sirius
+    - kde-ksplash-themes-sirius
+    - kde-plasma-themes-caledonia
+    - python2-imaging
+    - python2-v4l2capture
+    - python2-xlib
+    - caledonia-colors
+    - yakuake-themes-ronak
+    # kde (everything else)
+    - kdeadmin-kcron
+    - kdeadmin-kuser
+    - kdeplasma-addons-applets-icontasks
+    - kdesdk-kate
+    - kdeutils-ark
+    - kdeutils-kgpg
+    - kdeutils-sweeper
+    # kde network
+    - kdeplasma-applets-plasma-nm
+    - networkmanager-dispatcher-ntpd
+    - kcm-ufw
+    # applications
+    - rekonq
+    - yakuake
+    # enable systemd-units
+    - chakra-init-live
+    # overlay pkgs
+    - partitionmanager
+    - octopi-notifier
+    - kapudan
+- name: "Wireless"
+  description: "Tools for wireless connections"
+  packages:
+    - crda
+    - ndiswrapper
+    - usb-modeswitch
+    - wireless-regdb
+    - wireless_tools
+    - wpa_supplicant
+- name: "CCR"
+  description: "Tools for the Chakra Community Repository"
+  packages:
+    - ccr
+    - base-devel
+- name: "Graphics"
+  description: "Applications to work with graphics"
+  packages:
+    - kdegraphics-gwenview
+    - kdegraphics-kamera
+    - kdegraphics-kcolorchooser
+    - kdegraphics-kgamma
+    - kdegraphics-kolourpaint
+    - kdegraphics-kruler
+    - kdegraphics-ksaneplugin
+    - kdegraphics-ksnapshot
+    - kdegraphics-libkdcraw
+    - kdegraphics-libkexiv2
+    - kdegraphics-libkipi
+    - kdegraphics-libksane
+    - kdegraphics-mobipocket
+    - kdegraphics-okular
+    - kdegraphics-strigi-analyzer
+    - kdegraphics-svgpart
+    - kdegraphics-thumbnailers
+    - imagemagick
+- name: "Burning"
+  description: "Set of packages for disc burning"
+  packages:
+    - dvd+rw-tools
+    - vcdimager
+    - transcode
+    - emovix
+    - k3b
+    - libdvdcss
+- name: "Printing"
+  description: "Print much?"
+  packages:
+    - cups
+    - gutenprint
+    - cups-pdf
+    - kdeadmin-print-manager
+    - hplip
+    - epsoneplijs
+    - epson-inkjet-printer-escpr
+    - python2-gobject2
+    - samba
+- name: "Multimedia"
+  description: "Music and video players"
+  packages:
+    - kdemultimedia-dragonplayer
+    - kdenlive
+    - amarok
+- name: "Miscellaneous"
+  description: "Useful tools and apps"
+  packages:
+    - imagewriter
+    - tomoyo-tools
+    - python2-gobject  ## needed for systemd-analyze
+    - clamav
+    - kdenetwork-kget  ## maybe move to a network group?
+    - kdeplasma-addons-applets-lancelot
+    - kdeplasma-applets-homerun
+    - kdeplasma-applets-appmenu-qml
+    - kdeplasma-addons-runners-characters
+    - kdeplasma-addons-runners-converter
+    - kdeplasma-addons-runners-datetime
+    - kdeplasma-addons-runners-dictionary ##4.10 option
+    - kdeplasma-addons-runners-spellchecker
+    - appmenu-qt  ## needed for menubar options in 4.10
+    - kscreen
+
diff --git a/src/modules/netinstall/page_netinst.ui b/src/modules/netinstall/page_netinst.ui
new file mode 100644
index 0000000000000000000000000000000000000000..3b7a260ec7ec4fffbd69bef418e6a23c893113c0
--- /dev/null
+++ b/src/modules/netinstall/page_netinst.ui
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Page_NetInst</class>
+ <widget class="QWidget" name="Page_NetInst">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>997</width>
+    <height>474</height>
+   </rect>
+  </property>
+  <property name="windowTitle">
+   <string/>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout_2">
+   <item>
+    <widget class="QScrollArea" name="scrollArea">
+     <property name="maximumSize">
+      <size>
+       <width>16777215</width>
+       <height>16777215</height>
+      </size>
+     </property>
+     <property name="widgetResizable">
+      <bool>true</bool>
+     </property>
+     <widget class="QWidget" name="groupswidget">
+      <property name="geometry">
+       <rect>
+        <x>0</x>
+        <y>0</y>
+        <width>981</width>
+        <height>434</height>
+       </rect>
+      </property>
+      <layout class="QVBoxLayout" name="verticalLayout_3"/>
+     </widget>
+    </widget>
+   </item>
+   <item>
+    <widget class="QLabel" name="netinst_status">
+     <property name="text">
+      <string/>
+     </property>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
diff --git a/src/modules/netinstall/widgets/groupselectionwidget.cpp b/src/modules/netinstall/widgets/groupselectionwidget.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..b477c0453acf5f4afe1bc2f562e7e7f93a4faff2
--- /dev/null
+++ b/src/modules/netinstall/widgets/groupselectionwidget.cpp
@@ -0,0 +1,66 @@
+/*
+ *   Copyright 2016, Luca Giambonini <almack@chakraos.org>
+ *   Copyright 2016, Lisa Vitolo     <shainer@chakraos.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "groupselectionwidget.h"
+
+#include <QtDebug>
+
+GroupSelectionWidget::GroupSelectionWidget( QString name, QString description, QStringList packages, QWidget* parent ) :
+    QWidget( parent ),
+    m_isToggled( false )
+{
+    ui.setupUi( this );
+
+    connect( ui.group, &QCheckBox::toggled, this, &GroupSelectionWidget::toggleGroup );
+
+    ui.group->setText( name );
+    ui.description->setText( description );
+    const int columns = 4;
+    const int rows = ( packages.size() - 1 ) / columns + 1;
+    ui.packageview->setRowCount( rows );
+    ui.packageview->setColumnCount( columns );
+
+    ui.packageview->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch );
+
+    int r = 0, c = 0;
+    for ( int i = 0; i < packages.size(); ++i )
+    {
+        ui.packageview->setItem( r++,c, new QTableWidgetItem( packages.at( i ) ) );
+        if ( r == ui.packageview->rowCount() )
+        {
+            ++c;
+            r = 0;
+        }
+    }
+
+    int rowsShown = 6;
+    rowsShown = rows < rowsShown ? rows : 6;
+    ui.packageview->setFixedHeight( rowsShown * ui.packageview->rowHeight( 0 ) );
+    ui.packageview->hide();
+}
+
+void GroupSelectionWidget::toggleGroup( bool isToggled )
+{
+    m_isToggled = isToggled;
+    emit toggled( isToggled );
+}
+
+bool GroupSelectionWidget::isToggled() const
+{
+    return m_isToggled;
+}
diff --git a/src/modules/netinstall/widgets/groupselectionwidget.h b/src/modules/netinstall/widgets/groupselectionwidget.h
new file mode 100644
index 0000000000000000000000000000000000000000..a003f48336a8982b70dceda1e815e022c4f6eaf9
--- /dev/null
+++ b/src/modules/netinstall/widgets/groupselectionwidget.h
@@ -0,0 +1,50 @@
+/*
+ *   Copyright 2016, Luca Giambonini <almack@chakraos.org>
+ *   Copyright 2016, Lisa Vitolo     <shainer@chakraos.org>
+ *
+ *   Calamares is free software: you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, either version 3 of the License, or
+ *   (at your option) any later version.
+ *
+ *   Calamares is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ *   GNU General Public License for more details.
+ *
+ *   You should have received a copy of the GNU General Public License
+ *   along with Calamares. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GROUPSELECTIONWIDGET_H
+#define GROUPSELECTIONWIDGET_H
+
+#include "ui_groupselectionwidget.h"
+
+#include <QSignalMapper>
+#include <QWidget>
+
+// Represents a widget to display and select a group.
+class GroupSelectionWidget : public QWidget
+{
+    Q_OBJECT
+public:
+    explicit GroupSelectionWidget( QString name, QString description, QStringList packages, QWidget* parent = nullptr );
+
+    // Current status of the group: is it selected in the view?
+    bool isToggled() const;
+
+signals:
+    void toggled( bool );
+
+public slots:
+    void toggleGroup( bool isToggled );
+
+private:
+    Ui::GroupSelectionWidget ui;
+    static QSignalMapper* m_mapper;
+
+    bool m_isToggled;
+};
+
+#endif // GROUPSELECTIONWIDGET_H
diff --git a/src/modules/netinstall/widgets/groupselectionwidget.ui b/src/modules/netinstall/widgets/groupselectionwidget.ui
new file mode 100644
index 0000000000000000000000000000000000000000..1e05839d3e644c57a14b7e63a2de9ea950c1093d
--- /dev/null
+++ b/src/modules/netinstall/widgets/groupselectionwidget.ui
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>GroupSelectionWidget</class>
+ <widget class="QWidget" name="GroupSelectionWidget">
+  <property name="geometry">
+   <rect>
+    <x>0</x>
+    <y>0</y>
+    <width>805</width>
+    <height>62</height>
+   </rect>
+  </property>
+  <property name="sizePolicy">
+   <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+    <horstretch>0</horstretch>
+    <verstretch>0</verstretch>
+   </sizepolicy>
+  </property>
+  <property name="windowTitle">
+   <string>Frame</string>
+  </property>
+  <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QWidget" name="widget" native="true">
+     <layout class="QHBoxLayout" name="horizontalLayout">
+      <item>
+       <widget class="QCheckBox" name="group">
+        <property name="text">
+         <string>group</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QLabel" name="description">
+        <property name="text">
+         <string>description</string>
+        </property>
+       </widget>
+      </item>
+      <item>
+       <widget class="QPushButton" name="pushButton">
+        <property name="sizePolicy">
+         <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+          <horstretch>0</horstretch>
+          <verstretch>0</verstretch>
+         </sizepolicy>
+        </property>
+        <property name="text">
+         <string/>
+        </property>
+        <property name="icon">
+         <iconset resource="../netinstall.qrc">
+          <normaloff>:/images/arrow-up.png</normaloff>
+          <normalon>:/images/arrow-down.png</normalon>:/images/arrow-up.png</iconset>
+        </property>
+        <property name="checkable">
+         <bool>true</bool>
+        </property>
+        <property name="checked">
+         <bool>true</bool>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
+   <item>
+    <widget class="QTableWidget" name="packageview">
+     <property name="enabled">
+      <bool>true</bool>
+     </property>
+     <property name="sizePolicy">
+      <sizepolicy hsizetype="Expanding" vsizetype="Maximum">
+       <horstretch>0</horstretch>
+       <verstretch>0</verstretch>
+      </sizepolicy>
+     </property>
+     <property name="minimumSize">
+      <size>
+       <width>0</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="maximumSize">
+      <size>
+       <width>16777215</width>
+       <height>0</height>
+      </size>
+     </property>
+     <property name="editTriggers">
+      <set>QAbstractItemView::NoEditTriggers</set>
+     </property>
+     <property name="tabKeyNavigation">
+      <bool>false</bool>
+     </property>
+     <property name="showDropIndicator" stdset="0">
+      <bool>false</bool>
+     </property>
+     <property name="dragDropOverwriteMode">
+      <bool>false</bool>
+     </property>
+     <property name="selectionMode">
+      <enum>QAbstractItemView::NoSelection</enum>
+     </property>
+     <attribute name="horizontalHeaderVisible">
+      <bool>false</bool>
+     </attribute>
+     <attribute name="verticalHeaderVisible">
+      <bool>false</bool>
+     </attribute>
+    </widget>
+   </item>
+  </layout>
+ </widget>
+ <resources>
+  <include location="../netinstall.qrc"/>
+ </resources>
+ <connections>
+  <connection>
+   <sender>pushButton</sender>
+   <signal>toggled(bool)</signal>
+   <receiver>packageview</receiver>
+   <slot>setHidden(bool)</slot>
+   <hints>
+    <hint type="sourcelabel">
+     <x>772</x>
+     <y>25</y>
+    </hint>
+    <hint type="destinationlabel">
+     <x>653</x>
+     <y>61</y>
+    </hint>
+   </hints>
+  </connection>
+ </connections>
+ <slots>
+  <signal>toggled(bool)</signal>
+ </slots>
+</ui>