diff --git a/BaseHandler.php b/BaseHandler.php
new file mode 100644
index 0000000000000000000000000000000000000000..2ade1b5d3c16657485f5718cba945bb723d1e1e1
--- /dev/null
+++ b/BaseHandler.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace LakeDrops\Component\Composer;
+
+use Composer\Composer;
+use Composer\IO\IOInterface;
+
+/**
+ * Class BaseHandler.
+ *
+ * @package LakeDrops\Component\Composer
+ */
+abstract class BaseHandler {
+
+  /**
+   * The composer object of this session.
+   *
+   * @var \Composer\Composer
+   */
+  protected $composer;
+
+  /**
+   * The input-output object of the composer session.
+   *
+   * @var \Composer\IO\IOInterface
+   */
+  protected $io;
+
+  /**
+   * The Drupal core package.
+   *
+   * @var \Composer\Package\PackageInterface
+   */
+  protected $drupalCorePackage;
+
+  /**
+   * Handler constructor.
+   *
+   * @param \Composer\Composer $composer
+   *   The composer object of this session.
+   * @param \Composer\IO\IOInterface $io
+   *   The input-output object of the composer session.
+   */
+  public function __construct(Composer $composer, IOInterface $io) {
+    $this->composer = $composer;
+    $this->io = $io;
+  }
+
+  /**
+   * Look up the Drupal core package object.
+   *
+   * @return \Composer\Package\PackageInterface
+   *   The Drupal core package.
+   */
+  protected function getDrupalCorePackage() {
+    if (!isset($this->drupalCorePackage)) {
+      $this->drupalCorePackage = $this->getPackage('drupal/core');
+    }
+    return $this->drupalCorePackage;
+  }
+
+  /**
+   * Retrieve a package from the current composer process.
+   *
+   * @param string $name
+   *   Name of the package to get from the current composer installation.
+   *
+   * @return \Composer\Package\PackageInterface
+   *   The package.
+   */
+  protected function getPackage($name) {
+    return $this->composer->getRepositoryManager()->getLocalRepository()->findPackage($name, '*');
+  }
+
+  /**
+   * Wrapper for git command in the root directory.
+   *
+   * @param string $command
+   *   Git command name, arguments and/or options.
+   */
+  protected function git($command) {
+    passthru(escapeshellcmd('git -c "user.email=composer@lakedrops.com" ' . $command));
+  }
+
+}
diff --git a/BaseHandlerInterface.php b/BaseHandlerInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..135a49926a002a336f70079480d87562a5b8fd85
--- /dev/null
+++ b/BaseHandlerInterface.php
@@ -0,0 +1,12 @@
+<?php
+
+namespace LakeDrops\Component\Composer;
+
+/**
+ * Interface for BaseHandler.
+ *
+ * @package LakeDrops\Component\Composer
+ */
+interface BaseHandlerInterface {
+
+}
diff --git a/BasePlugin.php b/BasePlugin.php
new file mode 100644
index 0000000000000000000000000000000000000000..115a25815da9a95e984613270fc698e51611e616
--- /dev/null
+++ b/BasePlugin.php
@@ -0,0 +1,30 @@
+<?php
+
+namespace LakeDrops\Component\Composer;
+
+use Composer\Composer;
+use Composer\EventDispatcher\EventSubscriberInterface;
+use Composer\IO\IOInterface;
+use Composer\Plugin\PluginInterface;
+
+/**
+ * Composer plugin for handling docker4drupal setup.
+ */
+abstract class BasePlugin implements BasePluginInterface, PluginInterface, EventSubscriberInterface {
+
+  /**
+   * The handler object to do the real work then.
+   *
+   * @var \LakeDrops\Component\Composer\BaseHandlerInterface
+   */
+  protected $handler;
+
+  /**
+   * {@inheritdoc}
+   */
+  public function activate(Composer $composer, IOInterface $io) {
+    $class = $this->getHandlerClass();
+    $this->handler = new $class($composer, $io);
+  }
+
+}
diff --git a/BasePluginInterface.php b/BasePluginInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..903eb902a341b6f233d4862846e7fbd69a10c7a2
--- /dev/null
+++ b/BasePluginInterface.php
@@ -0,0 +1,17 @@
+<?php
+
+namespace LakeDrops\Component\Composer;
+
+/**
+ * Interface for BasePlugin.
+ *
+ * @package LakeDrops\Component\Composer
+ */
+interface BasePluginInterface {
+
+  /**
+   * @return \LakeDrops\Component\Composer\BaseHandlerInterface
+   */
+  public function getHandlerClass();
+
+}
diff --git a/Utils.php b/Utils.php
index 4d998347d891f0097eef73ebd4d0ce15d2b25c84..c6f8417aef45072b6f6cbebfd329df3e590a5899 100644
--- a/Utils.php
+++ b/Utils.php
@@ -78,12 +78,17 @@ final class Utils {
     $jsonFile = new JsonFile($this->composerJsonPath);
     if (file_exists($this->composerJsonPath)) {
       $content = $jsonFile->read();
-      if (md5(json_encode($content)) == md5(json_encode($this->content))) {
+      if (md5(json_encode($content)) === md5(json_encode($this->content))) {
         // Nothing has changed.
         return $this;
       }
     }
-    $jsonFile->write($this->content);
+    try {
+      $jsonFile->write($this->content);
+    }
+    catch (\Exception $ex) {
+      // Let's ignore this, if composer.json is read-only there is a general problem.
+    }
     return $this;
   }
 
diff --git a/composer.json b/composer.json
index 59d3a5d4688d2016aa5c3ba2e683d685605d2476..5ca3192cc960affa577c3bdb57b0a5a174398f3e 100644
--- a/composer.json
+++ b/composer.json
@@ -24,7 +24,8 @@
         "source": "https://gitlab.lakedrops.com/composer/library/composer-json-utils/tree/master"
     },
     "require": {
-        "php": ">=5.6"
+        "php": ">=5.6",
+        "ext-json": "*"
     },
     "require-dev": {
         "composer/composer": "^1.5.0",