diff --git a/CMakeLists.txt b/CMakeLists.txt
index c1791b21798210de722912c52510174a178b7b34..aad5f60d3150e83c2f87afeba9865c6a047c0010 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,8 @@
 project( calamares )
 cmake_minimum_required( VERSION 2.8.12 )
 set( CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules" )
+set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wl,--no-undefined" )
+#set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11" )
 
 cmake_policy( SET CMP0023 OLD )
 
diff --git a/src/calamares/CMakeLists.txt b/src/calamares/CMakeLists.txt
index 2dcb288752975766e448b71839fa0aa98a0dd5ae..d8da1be35429963987ca44909fb1b93f63c4975e 100644
--- a/src/calamares/CMakeLists.txt
+++ b/src/calamares/CMakeLists.txt
@@ -8,8 +8,11 @@ set( calamaresSources
     main.cpp
     CalamaresApplication.cpp
     CalamaresWindow.cpp
+    Module.cpp
+    ModuleLoader.cpp
     ViewManager.cpp
     Settings.cpp
+    YamlUtils.cpp
 
     viewpages/PagePlugin.cpp
     viewpages/AbstractPage.cpp
@@ -43,6 +46,7 @@ add_executable( calamares_bin ${final_src} )
 SET_TARGET_PROPERTIES(calamares_bin
     PROPERTIES
         AUTOMOC TRUE
+        ENABLE_EXPORTS TRUE
         RUNTIME_OUTPUT_NAME calamares
 )
 
diff --git a/src/calamares/Module.cpp b/src/calamares/Module.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..f4071c9eb29d41753b0c93813b1244448d788491
--- /dev/null
+++ b/src/calamares/Module.cpp
@@ -0,0 +1,120 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.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 "Module.h"
+
+#include "YamlUtils.h"
+
+#include "utils/Logger.h"
+
+#include <yaml-cpp/yaml.h>
+
+#include <QFile>
+#include <QString>
+
+
+// Example module.conf
+/*
+---
+type:      "core"     #core or view
+name:      "foo"      #the module name. must be unique and same as the parent directory
+interface: "qtplugin" #can be: qtplugin, python, process, ...
+requires:  []         #list of module names that must also be loaded. only applies to
+                      #binary plugins! these are actual link-time dependencies, not
+                      #conceptual dependencies for the setup procedure
+*/
+
+void
+operator>>( const YAML::Node& node, Calamares::Module& m )
+{
+    m.m_name = QString::fromStdString( node[ "name" ].as< std::string >() );
+
+    QString typeString = QString::fromStdString( node[ "type" ].as< std::string >() );
+    if ( typeString == "core" )
+    {
+        m.m_type = Calamares::Module::Core;
+    }
+    else if ( typeString == "view" )
+    {
+        m.m_type = Calamares::Module::View;
+        m.m_interface = Calamares::Module::QtPlugin;
+    }
+
+    if ( m.m_type != Calamares::Module::View )
+    {
+        QString interfaceString = QString::fromStdString( node[ "interface" ].as< std::string >() );
+        if ( interfaceString == "qtplugin" )
+        {
+            m.m_interface = Calamares::Module::QtPlugin;
+        }
+        else if ( interfaceString == "python" )
+        {
+            m.m_interface = Calamares::Module::Python;
+        }
+        else if ( interfaceString == "process" )
+        {
+            m.m_interface = Calamares::Module::Process;
+        }
+    }
+
+    if ( node[ "requires" ] && node[ "requires" ].IsSequence() )
+    {
+        node[ "requires" ] >> m.m_requiredModules;
+    }
+
+}
+
+
+Calamares::Module*
+Calamares::Module::loadFromFile( const QString& path )
+{
+    QFile metadataFile( path );
+    if ( metadataFile.exists() && metadataFile.open( QFile::ReadOnly | QFile::Text ) )
+    {
+        QByteArray ba = metadataFile.readAll();
+        cDebug() << Q_FUNC_INFO << "module metadata file: " << ba;
+
+        try
+        {
+            YAML::Node moduleDocument = YAML::Load( ba.constData() );
+            if ( !moduleDocument.IsMap() )
+            {
+                cDebug() << Q_FUNC_INFO << "bad module metadata format"
+                         << path;
+                return nullptr;
+            }
+
+            Module* m = new Module();
+            moduleDocument >> *m;
+            return m;
+        }
+        catch ( YAML::Exception& e )
+        {
+            cDebug() << "WARNING: YAML parser error " << e.what();
+            return nullptr;
+        }
+    }
+
+    return nullptr;
+}
+
+QString
+Calamares::Module::name()
+{
+    return m_name;
+}
diff --git a/src/calamares/Module.h b/src/calamares/Module.h
new file mode 100644
index 0000000000000000000000000000000000000000..c938a6cdab5d55e4ac17f00d571104073a8161e1
--- /dev/null
+++ b/src/calamares/Module.h
@@ -0,0 +1,72 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.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 CALAMARESMODULE_H
+#define CALAMARESMODULE_H
+
+#include "DllMacro.h"
+
+#include <QStringList>
+
+
+namespace YAML
+{
+class Node;
+}
+
+namespace Calamares
+{
+class Module;
+}
+
+void operator>>( const YAML::Node& node, Calamares::Module& m );
+
+namespace Calamares
+{
+
+class UIDLLEXPORT Module
+{
+public:
+    static Module* loadFromFile( const QString& path );
+
+    QString name();
+
+    enum Type
+    {
+        Core,
+        View
+    };
+
+    enum Interface
+    {
+        QtPlugin,
+        Python,
+        Process
+    };
+private:
+    QString m_name;
+    Type m_type;
+    Interface m_interface;
+    QStringList m_requiredModules;
+
+    friend void ::operator>>( const YAML::Node& node, Calamares::Module& m );
+};
+
+}
+
+#endif // CALAMARESMODULE_H
diff --git a/src/calamares/ModuleLoader.cpp b/src/calamares/ModuleLoader.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ee21e9a23295712ac7bc9a574860c7c748f12ea8
--- /dev/null
+++ b/src/calamares/ModuleLoader.cpp
@@ -0,0 +1,103 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.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 "ModuleLoader.h"
+
+#include "utils/Logger.h"
+
+#include <yaml-cpp/yaml.h>
+
+#include <QDir>
+
+#define MODULE_CONFIG_FILENAME "module.conf"
+
+namespace Calamares
+{
+
+ModuleLoader::ModuleLoader( const QStringList& paths, QObject* parent )
+    : QObject( parent )
+    , m_paths( paths )
+{
+}
+
+ModuleLoader::~ModuleLoader()
+{
+    foreach ( Module* m, m_availableModules )
+    {
+        delete m;
+    }
+}
+
+
+void
+ModuleLoader::exec()
+{
+    // We start from a list of paths in m_paths. Each of those is a directory that
+    // might (should) contain Calamares modules of any type/interface.
+    // For each modules search path (directory), it is expected that each module
+    // lives in its own subdirectory. This subdirectory must have the same name as
+    // the module name, and must contain a settings file named module.conf.
+    // If at any time the module loading procedure finds something unexpected, it
+    // silently skips to the next module or search path. --Teo 6/2014
+    foreach ( const QString& path, m_paths )
+    {
+        QDir currentDir( path );
+        if ( currentDir.exists() && currentDir.isReadable() )
+        {
+            QStringList subdirs = currentDir.entryList( QDir::AllDirs | QDir::NoDotAndDotDot );
+            foreach ( const QString& subdir, subdirs )
+            {
+                bool success = currentDir.cd( subdir );
+                if ( success && currentDir.isReadable() )
+                {
+                    QFileInfo metadataFileInfo( currentDir.absoluteFilePath( MODULE_CONFIG_FILENAME ) );
+                    if ( ! ( metadataFileInfo.exists() && metadataFileInfo.isReadable() ) )
+                    {
+                        cDebug() << Q_FUNC_INFO << "unreadable file: "
+                                 << metadataFileInfo.absoluteFilePath();
+                        continue;
+                    }
+
+                    Module* moduleInfo = Module::loadFromFile( metadataFileInfo.absoluteFilePath() );
+
+                    if ( moduleInfo &&
+                         ( moduleInfo->name() == currentDir.dirName() ) &&
+                         ( !m_availableModules.contains( moduleInfo->name() ) ) )
+                    {
+                        m_availableModules.insert( moduleInfo->name(), moduleInfo );
+                    }
+
+                    currentDir.cdUp();
+                }
+                else
+                {
+                    cDebug() << Q_FUNC_INFO << "cannot cd into module directory "
+                             << path << "/" << subdir;
+                }
+            }
+        }
+        else
+        {
+            cDebug() << Q_FUNC_INFO << "bad search path " << path;
+        }
+    }
+    // At this point m_availableModules is filled with whatever was found in the
+    // search paths.
+}
+
+}
diff --git a/src/calamares/ModuleLoader.h b/src/calamares/ModuleLoader.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5920b068f73a6682b083bc8ae49f18a449e23dd
--- /dev/null
+++ b/src/calamares/ModuleLoader.h
@@ -0,0 +1,54 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.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 MODULELOADER_H
+#define MODULELOADER_H
+
+#include "Module.h"
+
+#include <QMap>
+#include <QObject>
+#include <QStringList>
+
+namespace Calamares
+{
+
+class Module;
+
+class ModuleLoader : public QObject
+{
+    Q_OBJECT
+public:
+    explicit ModuleLoader( const QStringList& paths, QObject* parent = 0 );
+    virtual ~ModuleLoader();
+
+    void exec();
+
+signals:
+    void done();
+
+private:
+    QMap< QString, Module* > m_availableModules;
+
+    QStringList m_paths;
+
+};
+
+}
+
+#endif // MODULELOADER_H
diff --git a/src/calamares/Settings.cpp b/src/calamares/Settings.cpp
index ccef36f142e9bc895cc8197c66a143701a8109c9..0df7620df2a0f529dc1c51e85f8d510396170937 100644
--- a/src/calamares/Settings.cpp
+++ b/src/calamares/Settings.cpp
@@ -21,6 +21,7 @@
 #include "CalamaresApplication.h"
 #include "utils/CalamaresUtils.h"
 #include "utils/Logger.h"
+#include "YamlUtils.h"
 
 #include <QDir>
 #include <QFile>
@@ -28,16 +29,6 @@
 #include <yaml-cpp/yaml.h>
 
 
-void
-operator>>( const YAML::Node& node, QStringList& v )
-{
-    for ( int i = 0; i < node.size(); ++i )
-    {
-        v.append( QString::fromStdString( node[ i ].as< std::string >() ) );
-    }
-}
-
-
 namespace Calamares
 {
 
@@ -89,7 +80,7 @@ Settings::Settings( QObject* parent )
             config[ "modules-prepare" ] >> m_viewModulesPrepareList;
             config[ "modules-postinstall" ] >> m_viewModulesPostInstallList;
         }
-        catch( YAML::Exception& e )
+        catch ( YAML::Exception& e )
         {
             cDebug() << "WARNING: YAML parser error " << e.what();
         }
diff --git a/src/calamares/YamlUtils.cpp b/src/calamares/YamlUtils.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2bd89a082a41fa61fde822a6cd8f692a2b409c35
--- /dev/null
+++ b/src/calamares/YamlUtils.cpp
@@ -0,0 +1,30 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.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 "YamlUtils.h"
+
+#include <yaml-cpp/yaml.h>
+
+void
+operator>>( const YAML::Node& node, QStringList& v )
+{
+    for ( int i = 0; i < node.size(); ++i )
+    {
+        v.append( QString::fromStdString( node[ i ].as< std::string >() ) );
+    }
+}
+
diff --git a/src/calamares/YamlUtils.h b/src/calamares/YamlUtils.h
new file mode 100644
index 0000000000000000000000000000000000000000..173d76f76994a3e5ad12a4fb3a3dd0a9a11213be
--- /dev/null
+++ b/src/calamares/YamlUtils.h
@@ -0,0 +1,31 @@
+/* === This file is part of Calamares - <http://github.com/calamares> ===
+ *
+ *   Copyright 2014, Teo Mrnjavac <teo@kde.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 YAMLUTILS_H
+#define YAMLUTILS_H
+
+#include <QStringList>
+
+namespace YAML
+{
+class Node;
+}
+
+void operator>>( const YAML::Node& node, QStringList& v );
+
+#endif // YAMLUTILS_H
diff --git a/src/calamares/viewpages/AbstractPage.h b/src/calamares/viewpages/AbstractPage.h
index 6dd04af7cbf647c06b0c302323738034e2453246..d40932499e067bd634e4a9bf2e1334c356422e11 100644
--- a/src/calamares/viewpages/AbstractPage.h
+++ b/src/calamares/viewpages/AbstractPage.h
@@ -31,10 +31,8 @@ class UIDLLEXPORT AbstractPage : public QWidget
     Q_OBJECT
 public:
     explicit AbstractPage(QWidget *parent = 0);
+    virtual ~AbstractPage() {}
 
-signals:
-
-public slots:
 
 };
 
diff --git a/src/calamares/viewpages/PagePlugin.h b/src/calamares/viewpages/PagePlugin.h
index 58ba31cd81142b05a519fd338a5248a2d7560aba..35155512e61677baeb9a10ccc6a7ffee79950aaa 100644
--- a/src/calamares/viewpages/PagePlugin.h
+++ b/src/calamares/viewpages/PagePlugin.h
@@ -33,6 +33,7 @@ class UIDLLEXPORT PagePlugin : public QObject
     Q_OBJECT
 public:
     explicit PagePlugin( QObject *parent = 0 );
+    virtual ~PagePlugin() {}
 
 signals:
     void done();
diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt
index 1358089d29f37df16bf540f7018dd352a3d9246e..d996542299edc8e80ae00be092ba73610b8f48ab 100644
--- a/src/libcalamares/CMakeLists.txt
+++ b/src/libcalamares/CMakeLists.txt
@@ -17,8 +17,8 @@ set( libSources
     kdsingleapplicationguard/kdtoolsglobal.cpp
     kdsingleapplicationguard/kdlockedsharedmemorypointer.cpp
 
-    utils/Logger.cpp
     utils/CalamaresUtils.cpp
+    utils/Logger.cpp
 )
 
 include_directories(
diff --git a/src/modules/greeting/CMakeLists.txt b/src/modules/greeting/CMakeLists.txt
index c4eb762dade152c39e8bbd7c44d7d6f73c661e66..e03a3dc8d0ff1490695bcbf80de19cd9284aa04d 100644
--- a/src/modules/greeting/CMakeLists.txt
+++ b/src/modules/greeting/CMakeLists.txt
@@ -8,5 +8,6 @@ calamares_add_plugin( greeting
     UI
     LINK_LIBRARIES
         ${CALAMARES_LIBRARIES}
+        calamares_bin
     SHARED_LIB
 )
diff --git a/src/modules/greeting/GreetingPage.cpp b/src/modules/greeting/GreetingPage.cpp
index a215895c09f650da30d749816f4b2f7fa2d0d001..db455853568163fc2c99602d3e401033b4767445 100644
--- a/src/modules/greeting/GreetingPage.cpp
+++ b/src/modules/greeting/GreetingPage.cpp
@@ -20,6 +20,6 @@
 
 
 GreetingPage::GreetingPage( QWidget* parent )
-    : AbstractPage( parent )
+    : Calamares::AbstractPage( parent )
 {
 }
diff --git a/src/modules/greeting/GreetingPagePlugin.cpp b/src/modules/greeting/GreetingPagePlugin.cpp
index 2aa33f0189f7faf4085aaeef6fc3262dae82c92f..5028c84bf97d8ae2aceb11adf605165430ceface 100644
--- a/src/modules/greeting/GreetingPagePlugin.cpp
+++ b/src/modules/greeting/GreetingPagePlugin.cpp
@@ -19,6 +19,6 @@
 #include "GreetingPagePlugin.h"
 
 GreetingPagePlugin::GreetingPagePlugin( QObject *parent )
-    : PagePlugin( parent )
+    : Calamares::PagePlugin( parent )
 {
 }