diff --git a/nodejs_config/config/nodejs_config.settings.yml b/nodejs_config/config/nodejs_config.settings.yml
new file mode 100644
index 0000000..f26cb83
--- /dev/null
+++ b/nodejs_config/config/nodejs_config.settings.yml
@@ -0,0 +1,16 @@
+nodejs_config_js_suggestion: ''
+nodejs_config_host: 'localhost'
+nodejs_config_port: 8080
+nodejs_server_scheme: 'http'
+nodejs_config_key: '/path/to/key/file'
+nodejs_config_cert: '/path/to/cert/file'
+nodejs_config_resource: '/socket.io'
+nodejs_config_publishUrl: 'publish'
+nodejs_service_key: ''
+nodejs_config_write_channels: false
+nodejs_config_write_clients: false
+nodejs_config_backend_host: 'localhost'
+nodejs_config_backend_port: 80
+nodejs_config_backend_messagePath: '/nodejs/message'
+nodejs_config_debug: false
+nodejs_config_extensions: ''
diff --git a/nodejs_config/lib/Drupal/nodejs_config/Form/NodejsConfigSettingsForm.php b/nodejs_config/lib/Drupal/nodejs_config/Form/NodejsConfigSettingsForm.php
new file mode 100644
index 0000000..0a75b17
--- /dev/null
+++ b/nodejs_config/lib/Drupal/nodejs_config/Form/NodejsConfigSettingsForm.php
@@ -0,0 +1,209 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\nodejs_config\Form\NodejsConfigSettingsForm.
+ */
+
+namespace Drupal\nodejs_config\Form;
+
+use Drupal\Core\Config\ConfigFactory;
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Component\Utility\String;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Node.js server configuration form.
+ */
+class NodejsConfigSettingsForm extends ConfigFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'nodejs_config_settings_form';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+    $config = $this->configFactory->get('nodejs_config.settings');
+    $suggestion = $config->get('nodejs_config_js_suggestion')?: '';
+    $file_path = drupal_get_path('module', 'nodejs') . '/nodejs.config.js';
+    $config_path_message = t('<ol><li>Configure your server settings in the SETTINGS form below.</li><li>Click the <b>Save Configuration</b> button.</li><li>Copy the suggested configuration lines to <b>!file</b>, you need to do it manually.</li></ol>', array('!file' => $file_path));
+
+    $form['config_suggestion'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Configuration builder'),
+      '#description' => $config_path_message,
+    );
+    $form['config_suggestion']['nodejs_config_js'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Suggested configuration:'),
+      '#default_value' => $suggestion,
+    );
+    $form['config'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Settings'),
+    );
+    $form['config']['nodejs_config_host'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Host'),
+      '#required' => TRUE,
+      '#description' => t('Specify the host name or IP address that the node.js server should listen on.
+                           Leave blank to listen for any host name. Otherwise, the server will only respond
+                           to names that match the IP address given (or resolved from the given name).'),
+      '#default_value' => $config->get('nodejs_config_host')?: 'localhost',
+    );
+    $form['config']['nodejs_config_port'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Port'),
+      '#required' => TRUE,
+      '#description' => t('Specify the TCP port that the node.js server should listen on.'),
+      '#default_value' => $config->get('nodejs_config_port')?: 8080,
+    );
+
+    $scheme = $config->get('nodejs_server_scheme')?: 'http';
+    $form['config']['nodejs_config_key'] = array(
+      '#type' => $scheme == 'https' ? 'textfield' : 'hidden',
+      '#title' => t('Key'),
+      '#required' => TRUE,
+      '#description' => t('File system path to a key used for https communication with the server and clients.'),
+      '#default_value' => $config->get('nodejs_config_key')?: '/path/to/key/file',
+    );
+    $form['config']['nodejs_config_cert'] = array(
+      '#type' => $scheme == 'https' ? 'textfield' : 'hidden',
+      '#title' => t('Cert'),
+      '#required' => TRUE,
+      '#description' => t('File system path to a certificate used for https communication with the server and clients.'),
+      '#default_value' => $config->get('nodejs_config_cert')?: '/path/to/cert/file',
+    );
+    $form['config']['nodejs_config_resource'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Resource'),
+      '#required' => TRUE,
+      '#description' => t('http path that the node.js server should respond to.
+                           This value needs to match the Drupal node.js configuration.'),
+      '#default_value' => $config->get('nodejs_config_resource')?: '/socket.io',
+    );
+    $form['config']['nodejs_config_publishUrl'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Publish URL'),
+      '#required' => TRUE,
+      '#description' => t('http path on which the node.js server should accept messages from the Drupal site.'),
+      '#default_value' => $config->get('nodejs_config_publishUrl')?: 'publish',
+    );
+    $form['config']['nodejs_service_key'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Service Key'),
+      '#description' => t('An arbitrary string used as a secret between the node.js server and the Drupal site.'),
+      '#default_value' => $config->get('nodejs_service_key')?: '',
+    );
+    $form['config']['nodejs_config_write_channels'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Client write to channels'),
+      '#description' => t('Global flag that allows all channels to be written to by client sockets without
+                           going via the backend. Defaults to false.'),
+      '#default_value' => $config->get('nodejs_config_write_channels')?: FALSE,
+    );
+    $form['config']['nodejs_config_write_clients'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Client write to clients'),
+      '#description' => t('Global flag that allows all clients to be written to by client sockets
+                           without going via the backend. Defaults to false.'),
+      '#default_value' => $config->get('nodejs_config_write_clients')?: FALSE,
+    );
+    $form['config']['backend'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Backend'),
+    );
+    $form['config']['backend']['nodejs_config_backend_host'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Host'),
+      '#required' => TRUE,
+      '#description' => t('Host name of the Drupal site.'),
+      '#default_value' => $config->get('nodejs_config_backend_host')?: 'localhost',
+    );
+    $form['config']['backend']['nodejs_config_backend_port'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Port'),
+      '#required' => TRUE,
+      '#description' => t('TCP port of the server running the Drupal site. Usually 80.'),
+      '#default_value' => $config->get('nodejs_config_backend_port')?: 80,
+    );
+    $form['config']['backend']['nodejs_config_backend_messagePath'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Auth Path'),
+      '#description' => t('http path on which the Drupal node.js module listens for authentication check
+                           requests. Must end with /.'),
+      '#default_value' => $config->get('nodejs_config_backend_messagePath')?: '/nodejs/message',
+    );
+    $form['config']['backend']['nodejs_config_debug'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Debug'),
+      '#description' => t('Show debug information from the node.js process.'),
+      '#default_value' => $config->get('nodejs_config_debug')?: FALSE,
+    );
+    $form['ext'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Extensions'),
+      '#description' => t('An array of names of node.js modules that should be loaded as extensions to the
+                           node.js server.'),
+    );
+    $form['ext']['nodejs_config_extensions'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Extension file paths'),
+      '#description' => t('A list of node.js extension files paths, one per line.'),
+      '#default_value' => $config->get('nodejs_config_extensions')?: '',
+    );
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    $values = $form_state['values'];
+    $ext = $values['nodejs_config_extensions'];
+    if ($ext == !NULL) {
+      $ext = explode("\n", str_replace("\r", '', $ext));
+    }
+    $array = array(
+      'scheme' => $this->configFactory->get('nodejs_server_scheme')?: 'http',
+      'host' => String::checkPlain($values['nodejs_config_host']),
+      'port' => (int) $values['nodejs_config_port'],
+      'key' => String::checkPlain($values['nodejs_config_key']),
+      'cert' => String::checkPlain($values['nodejs_config_cert']),
+      'resource' => String::checkPlain($values['nodejs_config_resource']),
+      'publishUrl' => String::checkPlain($values['nodejs_config_publishUrl']),
+      'serviceKey' => String::checkPlain($values['nodejs_service_key']),
+      'backend' => array(
+        'port' => (int) $values['nodejs_config_backend_port'],
+        'host' => String::checkPlain($values['nodejs_config_backend_host']),
+        'messagePath' => String::checkPlain($values['nodejs_config_backend_messagePath']),
+      ),
+      'clientsCanWriteToChannels' => (bool) $values['nodejs_config_write_channels'],
+      'clientsCanWriteToClients' => (bool) $values['nodejs_config_write_clients'],
+      'extensions' => $ext,
+      'debug' => (bool) $values['nodejs_config_debug'],
+      'transports' => array(
+        'websocket', 'flashsocket', 'htmlfile', 'xhr-polling', 'jsonp-polling'
+      ),
+      'jsMinification' => true,
+      'jsEtag' => true,
+      'logLevel' => 1
+    );
+    $output = 'backendSettings = ' . drupal_json_encode($array);
+    $output = str_replace(array('= {', ',', '}}', ':{', '\/'), array("= {\n  ", ",\n  ", "\n  }\n}", ":{\n  ",  '/'), $output);
+    $output = "/**\n* This configuration file was built using the 'Node.js server configuration builder'.\n* For a more fully commented example see the file nodejs.config.js.example in the root of this module\n*/\n" . $output . ';';
+
+    $this->configFactory->get('nodejs_config.settings')
+      ->set('nodejs_config_js_suggestion', $output)
+      ->save();
+
+    parent::submitForm($form, $form_state);
+  }
+
+}
diff --git a/nodejs_config/nodejs_config.info b/nodejs_config/nodejs_config.info
deleted file mode 100644
index cd26ece..0000000
--- a/nodejs_config/nodejs_config.info
+++ /dev/null
@@ -1,6 +0,0 @@
-name = Nodejs Config
-description = Helps to configure the nodejs module.
-package = Nodejs
-version = VERSION
-core = 7.x
-dependencies[] = nodejs
diff --git a/nodejs_config/nodejs_config.info.yml b/nodejs_config/nodejs_config.info.yml
new file mode 100644
index 0000000..8413389
--- /dev/null
+++ b/nodejs_config/nodejs_config.info.yml
@@ -0,0 +1,8 @@
+name: Nodejs Config
+type: module
+description: 'Helps to configure the nodejs module.'
+package: Nodejs
+version: VERSION
+core: 8.x
+dependencies:
+  - nodejs
diff --git a/nodejs_config/nodejs_config.module b/nodejs_config/nodejs_config.module
index 76a5290..8fc245d 100644
--- a/nodejs_config/nodejs_config.module
+++ b/nodejs_config/nodejs_config.module
@@ -8,196 +8,7 @@ function nodejs_config_menu() {
     'admin/config/nodejs/js' => array(
       'title' => 'Node.js server configuration builder',
       'description' => 'A utility that outputs configuration suggestions. Copy & paste the output from this utility to nodejs.config.js',
-      'page callback' => 'drupal_get_form',
-      'page arguments' => array('nodejs_config_form'),
-      'access arguments' => array('administer site configuration'),
+      'route_name' => 'nodejs_config.settings',
     ),
   );
 }
-
-/**
- * Node.js server configuration form.
- * 
- * @param mixed $form 
- * @param mixed $form_state 
- * @return array
- */
-function nodejs_config_form($form, &$form_state) {
-	$suggestion = variable_get('nodejs_config_js_suggestion', '');
-	$file_path = drupal_get_path('module', 'nodejs') . '/nodejs.config.js';	
-	$config_path_message = t('<ol><li>Configure your server settings in the SETTINGS form below.</li><li>Click the <b>Save Configuration</b> button</li><li>Copy the suggested configuration lines to <b>!file</b>, you need to do it manually.</li></ol>', array('!file' => $file_path));
-	
-	$form['config_suggestion'] = array(
-    '#type' => 'fieldset',
-    '#title' => 'Configuration builder',
-    '#description' => $config_path_message,
-  );
-  $form['config_suggestion']['nodejs_config_js'] = array(
-    '#type' => 'textarea',
-    '#title' => 'Suggested configuration:',
-    '#default_value' => $suggestion,
-  );
-  $form['config'] = array(
-    '#type' => 'fieldset',
-    '#title' => 'Settings',
-  );
-  $form['config']['nodejs_config_host'] = array(
-    '#type' => 'textfield',
-    '#title' => 'Host',
-    '#required' => TRUE,
-    '#description' => 'Specify the host name or IP address that the node.js server should listen on. 
-                       Leave blank to listen for any host name. Otherwise, the server will only respond 
-                       to names that match the IP address given (or resolved from the given name).',
-    '#default_value' => variable_get('nodejs_config_host', 'localhost'),
-  );
-  $form['config']['nodejs_config_port'] = array(
-    '#type' => 'textfield',
-    '#title' => 'Port',
-    '#required' => TRUE,
-    '#description' => 'Specify the TCP port that the node.js server should listen on.',
-    '#default_value' => variable_get('nodejs_config_port', '8080'),
-  );
-
-  $scheme = variable_get('nodejs_server_scheme', 'http');
-  $form['config']['nodejs_config_key'] = array(
-    '#type' => $scheme == 'https' ? 'textfield' : 'hidden',
-    '#title' => 'Key',
-    '#required' => TRUE,
-    '#description' => 'File system path to a key used for https communication with the server and clients.',
-    '#default_value' => variable_get('nodejs_config_key', '/path/to/key/file'),
-  );  
-  $form['config']['nodejs_config_cert'] = array(
-    '#type' => $scheme == 'https' ? 'textfield' : 'hidden',
-    '#title' => 'Cert',
-    '#required' => TRUE,
-    '#description' => 'File system path to a certificate used for https communication with the server and clients.',
-    '#default_value' => variable_get('nodejs_config_cert', '/path/to/cert/file'),
-  );
-  $form['config']['nodejs_config_resource'] = array(
-    '#type' => 'textfield',
-    '#title' => 'Resource',
-    '#required' => TRUE,
-    '#description' => 'http path that the node.js server should respond to. 
-                       This value needs to match the Drupal node.js configuration.',
-    '#default_value' => variable_get('nodejs_config_resource', '/socket.io'),
-  );
-  $form['config']['nodejs_config_publishUrl'] = array(
-    '#type' => 'textfield',
-    '#title' => 'Publish URL',
-    '#required' => TRUE,
-    '#description' => 'http path on which the node.js server should accept messages from the Drupal site.',
-    '#default_value' => variable_get('nodejs_config_publishUrl', 'publish'),
-  );
-  $form['config']['nodejs_service_key'] = array(
-    '#type' => 'textfield',
-    '#title' => 'Service Key',
-    '#description' => 'An arbitrary string used as a secret between the node.js server and the Drupal site.',
-    '#default_value' => variable_get('nodejs_service_key', ''),
-  );
-  $form['config']['nodejs_config_write_channels'] = array(
-    '#type' => 'checkbox',
-    '#title' => 'Client write to channels',
-    '#description' => 'Global flag that allows all channels to be written to by client sockets without 
-                       going via the backend. defaults to false',
-    '#default_value' => variable_get('nodejs_config_write_channels', FALSE),
-  );
-  $form['config']['nodejs_config_write_clients'] = array(
-    '#type' => 'checkbox',
-    '#title' => 'Client write to clients',
-    '#description' => 'Global flag that allows all clients to be written to by client sockets 
-                       without going via the backend. defaults to false',
-    '#default_value' => variable_get('nodejs_config_write_clients', FALSE),
-  );
-  $form['config']['backend'] = array(
-    '#type' => 'fieldset',
-    '#title' => 'Backend',
-  );
-  $form['config']['backend']['nodejs_config_backend_host'] = array(
-    '#type' => 'textfield',
-    '#title' => 'Host',
-    '#required' => TRUE,
-    '#description' => 'Host name of the Drupal site.',
-    '#default_value' => variable_get('nodejs_config_backend_host', 'localhost'),
-  );
-  $form['config']['backend']['nodejs_config_backend_port'] = array(
-    '#type' => 'textfield',
-    '#title' => 'Port',
-    '#required' => TRUE,
-    '#description' => 'TCP port of the server running the Drupal site. Usually 80.',
-    '#default_value' => variable_get('nodejs_config_backend_port', '80'),
-  );
-  $form['config']['backend']['nodejs_config_backend_messagePath'] = array(
-    '#type' => 'textfield',
-    '#title' => 'Auth Path',
-    '#description' => 'http path on which the Drupal node.js module listens for authentication check 
-                       requests. Must end with /.',
-    '#default_value' => variable_get('nodejs_config_backend_messagePath', '/nodejs/message'),
-  );
-  $form['config']['backend']['nodejs_config_debug'] = array(
-    '#type' => 'checkbox',
-    '#title' => 'Debug',
-    '#description' => 'Show debug information from the node.js process.',
-    '#default_value' => variable_get('nodejs_config_debug', FALSE),
-  );
-  $form['ext'] = array(
-    '#type' => 'fieldset',
-    '#title' => 'Extensions',
-    '#description' => 'An array of names of node.js modules that should be loaded as extensions to the 
-                       node.js server.',
-  );
-  $form['ext']['nodejs_config_extensions'] = array(
-    '#type' => 'textarea',
-    '#title' => 'Extension file paths',
-    '#description' => 'A list of node.js extension files paths, one per line',
-    '#default_value' => variable_get('nodejs_config_extensions', ''),
-  );
-
-  $form['#submit'][] = 'nodejs_config_form_submit';
-  return system_settings_form($form);
-}
-
-/**
- * Node.js server configuration form submit handler.
- * 
- * @param mixed $form 
- * @param mixed $form_state 
- */
-function nodejs_config_form_submit($form, &$form_state) {
-  $values = $form_state['values'];
-  $ext = $values['nodejs_config_extensions'];
-  if ($ext == !NULL) {
-  	$ext = explode("\n", str_replace("\r", '', $ext));
-  }
-  $array = array(
-    'scheme' => variable_get('nodejs_server_scheme', 'http'),
-    'host' => check_plain($values['nodejs_config_host']),
-    'port' => (int) $values['nodejs_config_port'],
-    'key' => check_plain($values['nodejs_config_key']),
-    'cert' => check_plain($values['nodejs_config_cert']),
-    'resource' => check_plain($values['nodejs_config_resource']),
-    'publishUrl' => check_plain($values['nodejs_config_publishUrl']),
-    'serviceKey' => check_plain($values['nodejs_service_key']),
-    'backend' => array(
-      'port' => (int) $values['nodejs_config_backend_port'],
-      'host' => check_plain($values['nodejs_config_backend_host']),
-      'messagePath' => check_plain($values['nodejs_config_backend_messagePath']),
-    ),
-    'clientsCanWriteToChannels' => (bool) $values['nodejs_config_write_channels'],
-    'clientsCanWriteToClients' => (bool) $values['nodejs_config_write_clients'],
-    'extensions' => $ext,
-    'debug' => (bool) $values['nodejs_config_debug'],
-    'transports' => array(
-    	'websocket', 'flashsocket', 'htmlfile', 'xhr-polling', 'jsonp-polling'
-    ),
-	  'jsMinification' => true,
-	  'jsEtag' => true,
-	  'logLevel' => 1
-  );
-  $output = 'backendSettings = ' . drupal_json_encode($array);
-  $output = str_replace(array('= {', ',', '}}', ':{', '\/'), array("= {\n  ", ",\n  ", "\n  }\n}", ":{\n  ",  '/'), $output);
-  $output = $output . ';';
-	$output = "/**\n* This configuration file was built using the 'Node.js server configuration builder'.\n* For a more fully commented example see the file nodejs.config.js.example in the root of this module\n*/\n" . $output;
-
-  variable_set('nodejs_config_js_suggestion', $output);
-}
-
diff --git a/nodejs_config/nodejs_config.routing.yml b/nodejs_config/nodejs_config.routing.yml
new file mode 100644
index 0000000..5653543
--- /dev/null
+++ b/nodejs_config/nodejs_config.routing.yml
@@ -0,0 +1,7 @@
+nodejs_config.settings:
+  path: '/admin/config/nodejs/js'
+  defaults:
+    _form: '\Drupal\nodejs_config\Form\NodejsConfigSettingsForm'
+    _title: 'Node.js server configuration builder'
+  requirements:
+    _permission: 'administer site configuration'
