diff --git a/config/install/tweetbutton.settings.yml b/config/install/tweetbutton.settings.yml
new file mode 100644
index 0000000..bad91df
--- /dev/null
+++ b/config/install/tweetbutton.settings.yml
@@ -0,0 +1,9 @@
+tweetbutton_tweet_text: ''
+tweetbutton_size: 'medium'
+tweetbutton_hashtags: ''
+tweetbutton_language: 'en'
+tweetbutton_shorten_service: ''
+tweetbutton_account: ''
+tweetbutton_rel_account_name: ''
+tweetbutton_rel_account_description: ''
+tweetbutton_follow_screen_name: ''
diff --git a/lib/Drupal/tweetbutton/Form/TweetbuttonSettingsForm.php b/lib/Drupal/tweetbutton/Form/TweetbuttonSettingsForm.php
new file mode 100644
index 0000000..e24ecee
--- /dev/null
+++ b/lib/Drupal/tweetbutton/Form/TweetbuttonSettingsForm.php
@@ -0,0 +1,189 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tweetbutton\Form\TweetbuttonSettingsForm.
+ */
+
+namespace Drupal\tweetbutton\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+use Drupal\Core\Extension\ModuleHandlerInterface;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Provides a configuration form for tweetbutton.
+ */
+class TweetbuttonSettingsForm extends ConfigFormBase {
+
+  /**
+   * The module handler.
+   *
+   * @var \Drupal\Core\Extension\ModuleHandlerInterface
+   */
+  protected $moduleHandler;
+
+  /**
+   * Constructs a TweetbuttonSettingsForm object.
+   *
+   * @param \Drupal\Core\Extension\ModuleHandlerInterface
+   *   The module handler instance to use.
+   */
+  public function __construct(ModuleHandlerInterface $module_handler) {
+    $this->moduleHandler = $module_handler;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('module_handler')
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'tweetbutton_settings';
+  }
+
+  /**
+  * {@inheritdoc}
+  */
+  public function buildForm(array $form, array &$form_state) {
+    $config = $this->config('tweetbutton.settings');
+
+    $form['button'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Tweet button settings'),
+    );
+    $form['button']['tweetbutton_tweet_text'] = array(
+      '#type'          => 'textfield',
+      '#title'         => t('Tweet Text'),
+      '#default_value' => $config->get('tweetbutton_tweet_text'),
+      '#description'  => t('Tweet text to use as a default text, if no values are passed, leave this to blank to use page title as tweet text.')
+    );
+    $form['button']['tokens'] = array(
+      '#token_types' => array('node'),
+      '#theme' => 'token_tree',
+    );
+    $form['button']['tweetbutton_size'] = array(
+      '#title' => t('Tweetbutton size'),
+      '#type' => 'select',
+      '#options' => array(
+        'medium' => t('Medium'),
+        'large' => t('Large'),
+      ),
+      '#default_value' => $config->get('tweetbutton_size'),
+    );
+    $form['button']['tweetbutton_hashtags'] = array(
+      '#title' => t('Hashtags'),
+      '#type' => 'textfield',
+      '#default_value' => $config->get('tweetbutton_hashtags'),
+      '#description' => t('Comma separated hashtags to be used in every tweet'),
+    );
+    $form['button']['tweetbutton_language'] = array(
+      '#title' => t('Language'),
+      '#description' => t('This is the language that the button will render in on your website. People will see the Tweet dialog in their selected language for Twitter.com.'),
+      '#type' => 'select',
+      '#options' => array(
+        'en'   => t('English'),
+        'fr'   => t('French'),
+        'de'   => t('German'),
+        'es'   => t('Spanish'),
+        'ja'   => t('Japanese'),
+        'auto' => t('Automatic'),
+      ),
+      '#default_value' => $config->get('tweetbutton_language'),
+    );
+
+    if ($this->moduleHandler->moduleExists('shorten')) {
+      $services = array();
+      $services[0] = t('Use t.co twitter default url shortener');
+      $all_services = module_invoke_all('shorten_service');
+      foreach (array_keys($all_services) as $value) {
+        $services[$value] = $value;
+      }
+
+      $form['button']['tweetbutton_shorten_service'] = array(
+        '#title' => t('Shorten service to use to add custom url'),
+        '#type' => 'select',
+        '#options' => $services,
+        '#default_value' => $config->get('tweetbutton_shorten_service'),
+      );
+    }
+
+    $form['button']['follow'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Recommend people to follow'),
+    );
+    $form['button']['follow']['tweetbutton_account'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Twitter account to follow'),
+      '#description' => t('This user will be @mentioned in the suggested. Will be used as default if tweetbutton fields author twitter account is not set'),
+      '#default_value' => $config->get('tweetbutton_account'),
+      '#id' => 'tweetbutton-account',
+    );
+    $form['button']['follow']['tweetbutton_rel_account_name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Related Account'),
+      '#default_value' => $config->get('tweetbutton_rel_account_name'),
+      '#description' => t('This should be site default twitter account'),
+    );
+    $form['button']['follow']['tweetbutton_rel_account_description'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Related Account Description'),
+      '#default_value' => $config->get('tweetbutton_rel_account_description'),
+    );
+
+    // Follow button settings.
+    $form['follow_button'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Follow button settings'),
+    );
+    $form['follow_button']['tweetbutton_follow_screen_name'] = array(
+      '#type'           => 'textfield',
+      '#title'          => t('Screen name to follow'),
+      '#default_value'  => $config->get('tweetbutton_follow_screen_name'),
+      '#required'       => TRUE,
+    );
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+  * {@inheritdoc}
+  */
+  public function validateForm(array &$form, array &$form_state) {
+    return parent::validateForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    $values = $form_state['values'];
+
+    $this->config('tweetbutton.settings')
+      ->set('tweetbutton_tweet_text', $values['tweetbutton_tweet_text'])
+      ->set('tweetbutton_size', $values['tweetbutton_size'])
+      ->set('tweetbutton_hashtags', $values['tweetbutton_hashtags'])
+      ->set('tweetbutton_language', $values['tweetbutton_language'])
+      ->set('tweetbutton_account', $values['tweetbutton_account'])
+      ->set('tweetbutton_rel_account_name', $values['tweetbutton_rel_account_name'])
+      ->set('tweetbutton_rel_account_description', $values['tweetbutton_rel_account_description'])
+      ->set('tweetbutton_follow_screen_name', $values['tweetbutton_follow_screen_name']);
+
+    if ($this->moduleHandler->moduleExists('shorten')) {
+      $this->configFactory->get('tweetbutton.settings')
+        ->set('tweetbutton_shorten_service', $values['tweetbutton_shorten_service']);
+    }
+
+    $this->config('tweetbutton.settings')
+      ->save();
+    parent::submitForm($form, $form_state);
+  }
+
+}
diff --git a/lib/Drupal/tweetbutton/Plugin/Block/TweetbuttonFollowBlock.php b/lib/Drupal/tweetbutton/Plugin/Block/TweetbuttonFollowBlock.php
new file mode 100644
index 0000000..e7e2700
--- /dev/null
+++ b/lib/Drupal/tweetbutton/Plugin/Block/TweetbuttonFollowBlock.php
@@ -0,0 +1,167 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tweetbutton\Plugin\Block\TweetbuttonFollowBlock.
+ */
+
+namespace Drupal\tweetbutton\Plugin\Block;
+
+use Drupal\Core\Session\AccountInterface;
+use Drupal\block\Annotation\Block;
+use Drupal\block\BlockBase;
+use Drupal\Component\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Provides a 'Tweetbutton Follow' block.
+ *
+ * @Block(
+ *   id = "tweetbutton_follow_block",
+ *   admin_label = @Translation("Tweetbutton Follow"),
+ *   module = "tweetbutton"
+ *)
+ */
+class TweetbuttonFollowBlock extends BlockBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(AccountInterface $account) {
+    return $account->hasPermission('access tweetbutton');
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::defaultConfiguration().
+   */
+  public function defaultConfiguration() {
+    $config = \Drupal::config('tweetbutton.settings');
+    $default = array(
+      'label_display'    => FALSE,
+      'show_count'       => FALSE,
+      'lang'             => 'en',
+      'width'            => '',
+      'align'            => 'none',
+      'show_screen_name' => TRUE,
+      'size'             => 'medium',
+      'dnt'              => FALSE,
+    );
+
+    if (!empty($config->get('tweetbutton_follow_screen_name'))) {
+      $default['screen_name'] = $config->get('tweetbutton_follow_screen_name');
+    }
+
+    return $default;
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockForm().
+   */
+  public function blockForm($form, &$form_state) {
+    $form['follow'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Button settings'),
+      '#collapsible' => FALSE,
+    );
+    $form['follow']['show_count'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Followers count display'),
+      '#default_value' => $this->configuration['show_count'],
+    );
+    $form['follow']['lang'] = array(
+      '#type' => 'select',
+      '#title' => t('Language'),
+      '#options' => array(
+        'en'   => t('English'),
+        'fr'   => t('French'),
+        'de'   => t('German'),
+        'es'   => t('Spanish'),
+        'ja'   => t('Japanese'),
+        'auto' => t('Automatic'),
+      ),
+      '#description' => t('This is the language that the button will render in on your website. People will see the Tweet dialog in their selected language for Twitter.com.'),
+      '#default_value' => $this->configuration['lang'],
+    );
+    $form['follow']['width'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Width'),
+      '#description' => t('Enter the width of the block in pixels.'),
+      '#default_value' => $this->configuration['width'],
+    );
+    $form['follow']['align'] = array(
+      '#type' => 'select',
+      '#title' => t('Alignment'),
+      '#options' => array(
+        'none'   => t('None'),
+        'left'   => t('Left'),
+        'right'   => t('Right'),
+      ),
+      '#default_value' => $this->configuration['align'],
+    );
+    $form['follow']['show_screen_name'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Show Screen Name'),
+      '#default_value' => $this->configuration['show_screen_name'],
+    );
+    $form['follow']['screen_name'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Screen Name'),
+      '#default_value' => $this->configuration['screen_name'],
+      '#description' => t('If you leave the field blank, it will use the global setting of screen name.'),
+    );
+    $form['follow']['size'] = array(
+      '#type' => 'select',
+      '#title' => t('Button Size'),
+      '#options' => array(
+        'medium' => t('Medium'),
+        'large' => t('Large'),
+      ),
+      '#default_value' => $this->configuration['size'],
+    );
+    $form['follow']['dnt'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Opt-out of tailoring Twitter'),
+      '#default_value' => $this->configuration['dnt'],
+    );
+
+    return $form;
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockSubmit().
+   */
+  public function blockSubmit($form, &$form_state) {
+    $settings = $form_state['values']['follow'];
+
+    $this->configuration = array(
+      'show_count'       => $settings['show_count'],
+      'lang'             => $settings['lang'],
+      'width'            => $settings['width'],
+      'align'            => $settings['align'],
+      'show_screen_name' => $settings['show_screen_name'],
+      'screen_name'      => $settings['screen_name'],
+      'size'             => $settings['size'],
+      'dnt'              => $settings['dnt'],
+    );
+  }
+
+  /**
+   * Implements \Drupal\block\BlockBase::blockBuild().
+   */
+  public function build() {
+    return array(
+      '#theme' => 'tweetbutton_follow_display',
+      '#options' => array(
+        'show_count'       => $this->configuration['show_count'],
+        'lang'             => $this->configuration['lang'],
+        'width'            => $this->configuration['width'],
+        'align'            => $this->configuration['align'],
+        'show_screen_name' => $this->configuration['show_screen_name'],
+        'screen_name'      => $this->configuration['screen_name'],
+        'size'             => $this->configuration['size'],
+        'dnt'              => $this->configuration['dnt'],
+      ),
+    );
+  }
+
+}
diff --git a/lib/Drupal/tweetbutton/Plugin/Block/TweetbuttonTweetBlock.php b/lib/Drupal/tweetbutton/Plugin/Block/TweetbuttonTweetBlock.php
new file mode 100644
index 0000000..b78fa4c
--- /dev/null
+++ b/lib/Drupal/tweetbutton/Plugin/Block/TweetbuttonTweetBlock.php
@@ -0,0 +1,123 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tweetbutton\Plugin\Block\TweetbuttonTweetBlock.
+ */
+
+namespace Drupal\tweetbutton\Plugin\Block;
+
+use Drupal\Core\Session\AccountInterface;
+use Drupal\block\Annotation\Block;
+use Drupal\block\BlockBase;
+use Drupal\Component\Annotation\Plugin;
+use Drupal\Core\Annotation\Translation;
+
+/**
+ * Provides a 'Tweetbutton Tweet' block.
+ *
+ * @Block(
+ *   id = "tweetbutton_tweet_block",
+ *   admin_label = @Translation("Tweetbutton Tweet"),
+ *   module = "tweetbutton"
+ *)
+ */
+class TweetbuttonTweetBlock extends BlockBase {
+
+
+  /**
+   * {@inheritdoc}
+   */
+  public function access(AccountInterface $account) {
+    return $account->hasPermission('access tweetbutton');
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::defaultConfiguration().
+   */
+  public function defaultConfiguration() {
+    $config = \Drupal::config('tweetbutton.settings');
+    $default = array(
+      'label_display' => FALSE,
+      'text'          => '',
+      'count'         => 'horizontal',
+      'lang'          => 'en',
+      'size'          => 'medium',
+      'dnt'           => FALSE,
+    );
+
+    return $default;
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockForm().
+   */
+  public function blockForm($form, &$form_state) {
+    $form['tweet'] = array(
+      '#type' => 'fieldset',
+      '#title' => t('Button settings'),
+      '#collapsible' => FALSE,
+    );
+    $form['tweet']['text'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Tweet text'),
+      '#default_value' => $this->configuration['text'],
+    );
+    $form['tweet']['count'] = array(
+      '#type' => 'select',
+      '#title' => t('Count box position'),
+      '#options' => array(
+        'none'       => t('None'),
+        'horizontal' => t('Horizontal'),
+        'vertical'   => t('Vertical'),
+      ),
+      '#default_value' => $this->configuration['count'],
+    );
+    $form['tweet']['size'] = array(
+      '#type' => 'select',
+      '#title' => t('Button Size'),
+      '#options' => array(
+        'medium' => t('Medium'),
+        'large' => t('Large'),
+      ),
+      '#default_value' => $this->configuration['size'],
+    );
+    $form['tweet']['dnt'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Opt-out of tailoring Twitter'),
+      '#default_value' => $this->configuration['dnt'],
+    );
+
+    return $form;
+  }
+
+  /**
+   * Overrides \Drupal\block\BlockBase::blockSubmit().
+   */
+  public function blockSubmit($form, &$form_state) {
+    $settings = $form_state['values']['tweet'];
+
+    $this->configuration = array(
+      'text' => $settings['text'],
+      'count' => $settings['count'],
+      'size'  => $settings['size'],
+      'dnt'   => $settings['dnt'],
+    );
+  }
+
+  /**
+   * Implements \Drupal\block\BlockBase::blockBuild().
+   */
+  public function build() {
+    return array(
+      '#theme' => 'tweetbutton_tweet_display',
+      '#options' => array(
+        'text' => $this->configuration['text'],
+        'count' => $this->configuration['count'],
+        'size'  => $this->configuration['size'],
+        'dnt'   => $this->configuration['dnt'],
+      ),
+    );
+  }
+
+}
diff --git a/lib/Drupal/tweetbutton/Plugin/Field/FieldFormatter/TweetbuttonHorizontalFormatter.php b/lib/Drupal/tweetbutton/Plugin/Field/FieldFormatter/TweetbuttonHorizontalFormatter.php
new file mode 100644
index 0000000..1aa9ee9
--- /dev/null
+++ b/lib/Drupal/tweetbutton/Plugin/Field/FieldFormatter/TweetbuttonHorizontalFormatter.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tweetbutton\Plugin\field\formatter\TweetbuttonHorizontalFormatter.
+ */
+
+namespace Drupal\tweetbutton\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FormatterBase;
+use Drupal\Core\Field\FieldItemListInterface;
+
+/**
+ * Plugin implementation of the 'telephone_link' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "tweetbutton_formatter_horizontal",
+ *   label = @Translation("Tweetbutton style horizontal"),
+ *   field_types = {
+ *     "tweetbutton"
+ *   }
+ * )
+ */
+class TweetbuttonHorizontalFormatter extends FormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return array() + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state) {
+    $elements = array();
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+    $settings = $this->getSettings();
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items) {
+    $element = array();
+    return $element;
+  }
+}
diff --git a/lib/Drupal/tweetbutton/Plugin/Field/FieldFormatter/TweetbuttonNoneFormatter.php b/lib/Drupal/tweetbutton/Plugin/Field/FieldFormatter/TweetbuttonNoneFormatter.php
new file mode 100644
index 0000000..4d8c4d9
--- /dev/null
+++ b/lib/Drupal/tweetbutton/Plugin/Field/FieldFormatter/TweetbuttonNoneFormatter.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tweetbutton\Plugin\field\formatter\TweetbuttonNoneFormatter.
+ */
+
+namespace Drupal\tweetbutton\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FormatterBase;
+use Drupal\Core\Field\FieldItemListInterface;
+
+/**
+ * Plugin implementation of the 'telephone_link' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "tweetbutton_formatter_none",
+ *   label = @Translation("Tweetbutton style none"),
+ *   field_types = {
+ *     "tweetbutton"
+ *   }
+ * )
+ */
+class TweetbuttonNoneFormatter extends FormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return array() + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state) {
+    $elements = array();
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+    $settings = $this->getSettings();
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items) {
+    $element = array();
+    return $element;
+  }
+}
diff --git a/lib/Drupal/tweetbutton/Plugin/Field/FieldFormatter/TweetbuttonVerticalFormatter.php b/lib/Drupal/tweetbutton/Plugin/Field/FieldFormatter/TweetbuttonVerticalFormatter.php
new file mode 100644
index 0000000..5bc0cc8
--- /dev/null
+++ b/lib/Drupal/tweetbutton/Plugin/Field/FieldFormatter/TweetbuttonVerticalFormatter.php
@@ -0,0 +1,57 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tweetbutton\Plugin\field\formatter\TweetbuttonVerticalFormatter.
+ */
+
+namespace Drupal\tweetbutton\Plugin\Field\FieldFormatter;
+
+use Drupal\Core\Field\FormatterBase;
+use Drupal\Core\Field\FieldItemListInterface;
+
+/**
+ * Plugin implementation of the 'telephone_link' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "tweetbutton_formatter_vertical",
+ *   label = @Translation("Tweetbutton style vertical"),
+ *   field_types = {
+ *     "tweetbutton"
+ *   }
+ * )
+ */
+class TweetbuttonVerticalFormatter extends FormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return array() + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state) {
+    $elements = array();
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+    $settings = $this->getSettings();
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items) {
+    $element = array();
+    return $element;
+  }
+}
diff --git a/lib/Drupal/tweetbutton/Plugin/Field/FieldType/TweetbuttonItem.php b/lib/Drupal/tweetbutton/Plugin/Field/FieldType/TweetbuttonItem.php
new file mode 100644
index 0000000..78f9aac
--- /dev/null
+++ b/lib/Drupal/tweetbutton/Plugin/Field/FieldType/TweetbuttonItem.php
@@ -0,0 +1,90 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tweetbutton\Plugin\Field\FieldType\TweetbuttonItem.
+ */
+
+namespace Drupal\tweetbutton\Plugin\Field\FieldType;
+
+use Drupal\Core\Field\FieldStorageDefinitionInterface;
+use Drupal\Core\Field\FieldItemBase;
+use Drupal\Core\TypedData\DataDefinition;
+
+/**
+ * Plugin implementation of the 'tweetbutton' field type.
+ *
+ * @FieldType(
+ *   id = "tweetbutton",
+ *   label = @Translation("Tweetbutton"),
+ *   description = @Translation("Creates a tweetbutton field."),
+ *   default_widget = "tweetbutton",
+ *   default_formatter = "tweetbutton_formatter_horizontal"
+ * )
+ */
+class TweetbuttonItem extends FieldItemBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldStorageDefinitionInterface $field_definition) {
+    return array(
+      'columns' => array(
+        'text' => array(
+          'type' => 'varchar',
+          'length' => 128,
+          'not null' => FALSE,
+        ),
+        'account' => array(
+          'type' => 'varchar',
+          'length' => 32,
+          'not null' => FALSE,
+        ),
+      ),
+      'indexes' => array(
+        'text' => array('text'),
+        'account' => array('account'),
+      ),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state, $has_data) {
+    $element = array();
+    $config = \Drupal::config('tweetbutton.settings');
+    $settings = $this->getFieldDefinition()->getField()->getSettings();
+
+    $element['tweet_text'] = array(
+      '#type' => 'textfield',
+      '#title' =>  t('Tweet text'),
+      '#default_value' => isset($settings['tweet_text']) ? $settings['tweet_text'] : $config->get('tweetbutton_tweet_text'),
+    );
+    $element['author_twitter'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Author twitter account'),
+      '#default_value' => isset($settings['author_twitter']) ? $settings['author_twitter'] : $config->get('tweetbutton_account'),
+      '#description' => t('This user will be @mentioned in the suggested'),
+    );
+
+    return $element;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isEmpty() {
+    return FALSE;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConstraints() {
+    $constraint_manager = \Drupal::typedDataManager()->getValidationConstraintManager();
+    $constraints = parent::getConstraints();
+    return $constraints;
+  }
+
+}
diff --git a/lib/Drupal/tweetbutton/Plugin/Field/FieldWidget/TweetbuttonWidget.php b/lib/Drupal/tweetbutton/Plugin/Field/FieldWidget/TweetbuttonWidget.php
new file mode 100644
index 0000000..3a4a38a
--- /dev/null
+++ b/lib/Drupal/tweetbutton/Plugin/Field/FieldWidget/TweetbuttonWidget.php
@@ -0,0 +1,77 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\tweetbutton\Plugin\Field\FieldWidget\TweetbuttonWidget.
+ */
+
+namespace Drupal\tweetbutton\Plugin\Field\FieldWidget;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+
+/**
+ * Plugin implementation of the 'tweetbutton' widget.
+ *
+ * @FieldWidget(
+ *   id = "tweetbutton",
+ *   label = @Translation("Tweetbutton widget"),
+ *   field_types = {
+ *     "tweetbutton"
+ *   }
+ * )
+ */
+class TweetbuttonWidget extends WidgetBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function defaultSettings() {
+    return array(
+      'display_label' => '',
+    ) + parent::defaultSettings();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state) {
+    $element['display_label'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Use field label instead of the "On value" as label'),
+      '#default_value' => $this->getSetting('display_label'),
+      '#weight' => -1,
+    );
+    return $element;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $placeholder = $this->getSetting('placeholder');
+    if (!empty($placeholder)) {
+      $summary[] = t('Placeholder: @placeholder', array('@placeholder' => $placeholder));
+    }
+    else {
+      $summary[] = t('No placeholder');
+    }
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) {
+    $element['value'] = $element + array(
+      '#type' => 'tel',
+      '#default_value' => isset($items[$delta]->value) ? $items[$delta]->value : NULL,
+      '#placeholder' => $this->getSetting('placeholder'),
+    );
+    return $element;
+  }
+
+}
diff --git a/tweetbutton.admin.inc b/tweetbutton.admin.inc
deleted file mode 100644
index 1aa0d63..0000000
--- a/tweetbutton.admin.inc
+++ /dev/null
@@ -1,142 +0,0 @@
-<?php
-
-
-
-function tweetbutton_admin_settings() {
-	$form = array();
-  
-  $form['button'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Default settings for tweetbutton'),
-  );
-  
-  $form['button']['tweetbutton_button'] = array(
-    '#type' => 'select',
-    '#options' => array(
-      'vertical' => t('Vertical Count'),
-      'horizontal' => t('Horizontal Count'),
-      'none'   => t('No count'),
-    ),
-    '#default_value' => variable_get('tweetbutton_button', 'vertical'),
-    '#id' => 'tweetbutton-button',
-  );
-  
-  
-  $form['button']['tweetbutton_tweet_text'] = array(
-    '#type'          => 'textfield',
-    '#title'         => t('Tweet Text'),
-    '#default_value' => variable_get('tweetbutton_tweet_text'),
-    '#description'  => t('Tweet text to use as a default text, if no values are passed, leave this to blank to use page title as tweet text.')
-  );
-
-  $form['button']['tokens'] = array(
-    '#token_types' => array('node'),
-    '#theme' => 'token_tree',
-  );  
-
-  $form['button']['tweetbutton_size'] = array(
-    '#title' => t('Tweetbutton size'),
-    '#type' => 'select',
-    '#options' => array(
-      'medium' => t('Medium'),
-      'large' => t('Large'),
-    ),
-    '#default_value' => variable_get('tweetbutton_size'),
-  );
-  
-  $form['button']['tweetbutton_hashtags'] = array(
-    '#title' => t('Hashtags'),
-    '#type' => 'textfield',
-    '#default_value' => variable_get('tweetbutton_hashtags'),
-    '#description' => t('Comma separated hashtags to be used in every tweet'),
-  );
-  
-  $form['button']['tweetbutton_language'] = array(
-    '#title' => t('Language'),
-    '#description' => t('This is the language that the button will render in on your website. People will see the Tweet dialog in their selected language for Twitter.com.'),
-    '#type' => 'select',
-    '#options' => array(
-      'en'   => t('English'),
-      'fr'   => t('French'),
-      'de'   => t('German'),
-      'es'   => t('Spanish'),
-      'ja'   => t('Japanese'),
-      'auto' => t('Automatic'),
-    ),
-    '#default_value' => variable_get('tweetbutton_language'),
-  );
-  
-  if (module_exists('shorten')) {
-
-    $services = array();
-    $services[0] = t('Use t.co twitter default url shortener');
-    $all_services = module_invoke_all('shorten_service');
-    foreach (array_keys($all_services) as $value) {
-      $services[$value] = $value;
-    }
-    
-    $form['button']['tweetbutton_shorten_service'] = array(
-      '#title' => t('Shorten service to use to add custom url'),
-      '#type' => 'select',
-      '#options' => $services,
-      '#default_value' => variable_get('tweetbutton_shorten_service', 0),
-    );
-  }
-  
-  $form['button']['follow'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Recommend people to follow'),
-  );
-  
-  $form['button']['follow']['tweetbutton_account'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Twitter account to follow'),
-    '#description' => t('This user will be @mentioned in the suggested. Will be used as default if tweetbutton fields author twitter account is not set'),
-    '#default_value' => variable_get('tweetbutton_account'),
-    '#id' => 'tweetbutton-account',
-  );
-  
-  $form['button']['follow']['tweetbutton_rel_account_name'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Related Account'),
-    '#default_value' => variable_get('tweetbutton_rel_account_name'),
-    '#description' => t('This should be site default twitter account'),
-  );
-  
-  $form['button']['follow']['tweetbutton_rel_account_description'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Related Account Description'),
-    '#default_value' => variable_get('tweetbutton_rel_account_description'),
-  );
-
-  
-  
-  $form['follow_button'] = array(
-    '#type' => 'fieldset',
-    '#title' => t('Follow button settings'),
-  );
-  
-  $form['follow_button']['tweetbutton_follow_show_count'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Show follow count'),
-    '#default_value' => variable_get('tweetbutton_follow_show_count', TRUE),
-  );
-  
-  $form['follow_button']['tweetbutton_follow_screen_name'] = array(
-    '#type'           => 'textfield',
-    '#title'          => t('Screen name to follow'),
-    '#default_value'  => variable_get('tweetbutton_follow_screen_name'),
-  );
-  
-  $form['follow_button']['tweetbutton_follow_size'] = array(
-    '#title' => t('Tweetbutton size'),
-    '#type' => 'select',
-    '#options' => array(
-      'medium' => t('Medium'),
-      'large' => t('Large'),
-    ),
-    '#default_value' => variable_get('tweetbutton_follow_size'),
-  );
-  
-  return system_settings_form($form);
-}
\ No newline at end of file
diff --git a/tweetbutton.info b/tweetbutton.info
deleted file mode 100644
index 491a4b4..0000000
--- a/tweetbutton.info
+++ /dev/null
@@ -1,5 +0,0 @@
-name = Tweetbutton
-description = Add tweet button to  your website without having to leave the page
-core = 7.x
-dependencies[] = token
-configure = admin/config/services/tweetbutton
\ No newline at end of file
diff --git a/tweetbutton.info.yml b/tweetbutton.info.yml
new file mode 100644
index 0000000..4500a47
--- /dev/null
+++ b/tweetbutton.info.yml
@@ -0,0 +1,6 @@
+name: Tweetbutton
+type: module
+description: 'Add tweet button to your website without having to leave the page.'
+version: VERSION
+core: 8.x
+configure: tweetbutton.settings
diff --git a/tweetbutton.install b/tweetbutton.install
deleted file mode 100644
index b8dec17..0000000
--- a/tweetbutton.install
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-
-/**
- * Implements hook_field_schema()
- */
-function tweetbutton_field_schema($field) {
-  switch ($field['type']) {
-    case 'tweetbutton':
-      $columns = array(
-        'text' => array(
-          'type' => 'varchar',
-          'length' => 128,
-          'not null' => FALSE,
-        ),
-        'account' => array(
-          'type' => 'varchar',
-          'length' => 32,  
-          'not null' => FALSE,
-        ),
-      );
-      break;
-  }
-  return array(
-    'columns' => $columns,
-    'indexes' => array(
-      'account' => array('account'),
-      'text' => array('text'),
-    ),
-  );
-}
-
-/**
- * Implementation of hook_uninstall()
- */
-function tweetbutton_uninstall() {
-	variable_del('tweetbutton_button');
-  variable_del('tweetbutton_tweet_text');
-  variable_del('tweetbutton_tweet_url');
-  variable_del('tweetbutton_language');
-  variable_del('tweetbutton_account');
-  variable_del('tweetbutton_rel_account_name');
-  variable_del('tweetbutton_rel_account_description');
-  variable_del('tweetbutton_node_weight');
-  variable_del('tweetbutton_node_types');
-  variable_del('tweetbutton_node_location');  
-  variable_del('tweetbutton_shorten_service');
-  variable_del('tweetbutton_follow_show_count');
-  variable_del('tweetbutton_follow_screen_name');
-  variable_del('tweetbutton_follow_size');
-}
\ No newline at end of file
diff --git a/tweetbutton.module b/tweetbutton.module
index 400cf0b..dbcd7f9 100644
--- a/tweetbutton.module
+++ b/tweetbutton.module
@@ -1,6 +1,13 @@
 <?php
 
 /**
+ * @file
+ * Adds block with tweet and follow buttons.
+ */
+
+use Drupal\Core\Language\Language;
+
+/**
  * Implements hook_help().
  */
 function tweetbutton_help($path, $arg) {
@@ -16,463 +23,268 @@ function tweetbutton_help($path, $arg) {
 }
 
 /**
- * Implementation of hook_field_info() 
- */
-function tweetbutton_field_info() {
-  return array(
-    'tweetbutton' => array(
-      'label' => 'Tweetbutton',
-      'description' => 'Creates a tweetbutton field',
-      'instance_settings' => array( 'tweet_text' => '', 'author_twitter' => ''),
-      'default_widget' => 'tweetbutton',
-      'default_formatter' => 'tweetbutton_formatter_button_horizontal',
-    ),
-  );
-}
-
-/**
- * Implementation of hook_field_is_empty() 
- */
-function tweetbutton_field_is_empty($item, $field) {
-  return FALSE;
-}
-
-/**
- * Implementation of hook_field_instance_settings_form 
- */
-function tweetbutton_field_instance_settings_form($field, $instance) {
-  $settings = $instance['settings'];
-
-  $form = array();
-  
-  $form['tweet_text'] = array(
-    '#type' => 'textfield',
-    '#title' =>  t('Tweet text'),
-    '#default_value' => isset($settings['tweet_text'])? $settings['tweet_text']: variable_get('tweetbutton_tweet_text'),
-  );
-
-
-  $form['author_twitter'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Author twitter account'),
-    '#default_value' => isset($settings['author_twitter'])? $settings['author_twitter']: variable_get('tweetbutton_account'),
-    '#description' => t('This user will be @mentioned in the suggested'),
-  );
-  
-  if ($instance['entity_type'] == 'taxonomy_term') {
-    $token_type = 'term';
-  }
-  else {
-    $token_type = $instance['entity_type'];
-  }
-
-  $form['tokens'] = array(
-    '#token_types' => array($token_type),
-    '#theme' => 'token_tree',
-  );
-  
-  return $form;
-}
-
-/**
- * Implementation of hook_field_widget_info() 
- */
-function tweetbutton_field_widget_info() {
-  return array(
-    'tweetbutton' => array(
-      'label' => t('Tweetbutton'),
-      'field types' => array('tweetbutton'),
-      'behaviors' => array(
-        'multiple values' => FIELD_BEHAVIOR_DEFAULT,
-        'default value' => FIELD_BEHAVIOR_DEFAULT
-      ),
-    ),
-  );
-}
-
-/**
- * Implementation of hook_field_widget_form() 
- */
-function tweetbutton_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
-  $default_author = isset($instance['settings']['author_twitter'])? $instance['settings']['author_twitter']: '';
-  $default_text = isset($instance['settings']['tweet_text'])? $instance['settings']['tweet_text']: '';
-
-  $element['account'] = array(
-    '#type' => 'textfield',
-    '#default_value' => !empty($items[$delta]['account'])? $items[$delta]['account']: $default_author,
-    '#title' => t('Author twitter account'),
-    '#description' => t('Leave blank to use global twitter account.'),
-    '#maxlength' => 128,
-    '#access' => user_access('use tweetbutton field'),
-  );
-  
-  $element['text'] = array(
-    '#type' => 'textfield',
-    '#default_value' => !empty($items[$delta]['text'])? $items[$delta]['text']: $default_text,
-    '#title' => t('Tweet text'),
-    '#description' => t('Leave blank to use content title as tweet text'),
-    '#maxlength' => 32,
-    '#access' => user_access('use tweetbutton field'),
-  );
-  
-  return $element;
-}
-
-/**
- * Implementation of hook_field_presave() 
- */
-function tweetbutton_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
-  if ($field['type'] == 'tweetbutton') {
-    foreach ($items as $delta => $item) {
-      $data = array($entity_type => $entity);
-      $option = array('clear' => TRUE);
-      $items[$delta]['text'] = !empty($items[$delta]['text'])? token_replace($items[$delta]['text'], $data, $option): $entity->title;
-      $items[$delta]['account'] = !empty($items[$delta]['account'])? token_replace($items[$delta]['account'], $data, $option): '';
-    }
-  }
-}
-
-
-/**
- * Implementation of hook_field_formatter_info()
+ * Implements hook_theme()
  */
-function tweetbutton_field_formatter_info() {
+function tweetbutton_theme() {
   return array(
-    'tweetbutton_formatter_button_vertical' => array(
-      'label' => t('Tweetbutton style vertical'),
-      'field types' => array('tweetbutton'),
-      'settings' =>  array(
-        'size' => 'medium',
+    'tweetbutton_tweet_display' => array(
+      'variables' => array(
+        'options' => array(),
       ),
     ),
-    'tweetbutton_formatter_button_horizontal' => array(
-      'label' => t('Tweetbutton style horizontal'),
-      'field types' => array('tweetbutton'),
-      'settings' =>  array(
-        'size' => 'medium',
+    'tweetbutton_follow_display' => array(
+      'variables' => array(
+        'options' => array(),
       ),
     ),
-    'tweetbutton_formatter_button_none' => array(
-      'label' => t('Tweetbutton style none'),
-      'field types' => array('tweetbutton'),
-      'settings' =>  array(
-        'size' => 'medium',
+    'tweetbutton_hashtag_display' => array(
+      'variables' => array(
+        'options' => array(),
+        'hashtag' => '',
       ),
     ),
   );
 }
 
 /**
- * Implements hook_field_formatter_settings_form().
- */
-function tweetbutton_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
-  $display = $instance['display'][$view_mode];
-  $settings = $display['settings'];
-  
-  $element['size'] = array(
-    '#type' => 'select',
-    '#title' => t('Tweetbutton size'),
-    '#options' => array('medium' => t('Medium'), 'large' => t('Large')),
-    '#default_value' => $settings['size']
-  );
-
-  return $element;
-}
-
-/**
- * Implements hook_field_formatter_settings_summary().
- */
-function tweetbutton_field_formatter_settings_summary($field, $instance, $view_mode) {
-  $display = $instance['display'][$view_mode];
-  $settings = $display['settings'];
-  $options = array('medium' => t('Medium'), 'large' => t('Large'));
-  $title = $options[$settings['size']];
-  return t('Size: !title', array('!title' => $title));
-}
-
-/**
- * Implements hook_field_formatter_view().
+ * Implementation of hook_permission()
  */
-function tweetbutton_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, &$items, $display) {
-  $settings = $display['settings'];
-
-  $delta = 0;
-  switch ($display['type']) {
-    case 'tweetbutton_formatter_button_vertical':
-      $button_type = 'vertical';
-      break;
-    case 'tweetbutton_formatter_button_horizontal':
-      $button_type = 'horizontal';
-      break;
-    case 'tweetbutton_formatter_button_none':
-      $button_type = 'none';
-      break;
-  }
-
-  if (empty($items)) {
-    $items[$delta] = array(
-      'text' => '',
-      'account' => ''
-    );  
-  }
-
-  $uri = entity_uri($entity_type, $entity);
-  $element[$delta] = array(
-    '#theme' => 'tweetbutton_tweet_display',
-    '#options' => array(
-      'size'            => $settings['size'],
-      'type'            => $button_type,
-      'account'         => $items[$delta]['account'],
-      'tweet_text'      => $items[$delta]['text'],
-      'url'             => url($uri['path'], array('absolute' => TRUE)),
+function tweetbutton_permission() {
+  return array(
+    'administer tweetbutton' => array(
+      'title' => t('Administer Tweet Button'),
+    ),
+    'access tweetbutton' => array(
+      'title' => t('Access Tweet Button'),
+    ),
+    'use tweetbutton field' => array(
+      'title' => t('Use tweetbutton field to alter tweet text')
     ),
-    '#entity' => $entity,
-    '#entity_type' => $entity_type,
-     
   );
-  return $element;
 }
 
 /**
  * Implementation of hook_menu()
- */ 
+ */
 function tweetbutton_menu() {
-	$items = array();
+  $items = array();
 
   $items['admin/config/services/tweetbutton'] = array(
-    'title'            => 'Tweet Button',
-    'description'      => 'Configure the look and behavior of the Tweet Button appears on the site.',
-    'page callback'    => 'drupal_get_form',
-    'page arguments'   => array('tweetbutton_admin_settings'),
-    'access arguments' => array('administer tweetbutton'),
-    'file'             => 'tweetbutton.admin.inc',
-    'type'             => MENU_NORMAL_ITEM,
+    'title'       => 'Tweet Button',
+    'description' => 'Configure the look and behavior of the Tweet Button appears on the site.',
+    'route_name'  => 'tweetbutton.settings',
   );
 
   return $items;
 }
 
 /**
- * Implementation of hook_theme()
+ * Helper function to build the required tweet attributes.
+ *
+ * @param array $options
+ *   Context specific options.
+ *
+ * @return
+ *   List of attributes to be rendered for tweet button.
  */
-function tweetbutton_theme() {
-	return array(
-    'tweetbutton_tweet_display' => array(
-      'variables' => array('entity' => NULL, 'entity_type' => NULL, 'options' => array()),
-    ),
-    'tweetbutton_follow_display' => array(
-      'variables' => array('options' => array(), 'screen_name' => ''),
-    ),
-    'tweetbutton_hashtag_display' => array(
-      'variables' => array('options' => array(), 'hashtag' => ''),
-    ),
+function tweetbutton_tweet_get_attributes($options = array()) {
+  $config = \Drupal::config('tweetbutton.settings');
+
+  $default_option = array(
+    'account'         => $config->get('tweetbutton_account'),
+    'text'            => $config->get('tweetbutton_tweet_text'),
+    'rel_account'     => $config->get('tweetbutton_rel_account_name'),
+    'rel_description' => $config->get('tweetbutton_rel_account_description'),
+    'language'        => $config->get('tweetbutton_language'),
+    'hashtags'        => $config->get('tweetbutton_hashtags'),
   );
-}
 
+  // @TODO: Integration with module shorten.
+  $default_option['url'] = '';
+  $default_option['count_url'] = '';
 
-/**
- * Implementation of hook_cron() 
- */
-function tweetbutton_cron() {
-  // @TODO: Fetch count of each page where tweetbutton is on and add it to column 'count' in field
-  // Will be useful in sorting page based on no of tweets and add views support
-  if (!variable_get('tweetbutton_get_count', FALSE)) {
-    return;
-  }
-  
-  
-}
+  $options += $default_option;
 
-/**
- * Implementation of hook_permission()
- */
-function tweetbutton_permission() {
-  return array(
-    'administer tweetbutton' => array(
-      'title' => t('Administer Tweet Button'),
-    ),
-    'access tweetbutton' => array(
-      'title' => t('Access Tweet Button'),
-    ),
-    'use tweetbutton field' => array(
-      'title' => t('Use tweetbutton field to alter tweet text')
-    ),
+  $attributes =  array(
+    'data-url'      => $options['url'],
+    'data-via'      => $options['account'],
+    'data-text'     => $options['text'],
+    'data-related'  => $options['rel_account'] . ':' . $options['rel_description'],
+    'data-count'    => $options['count'],
+    'data-lang'     => $options['language'],
+    'data-counturl' => $options['count_url'],
+    'data-hashtags' => $options['hashtags'],
+    'data-size'     => $options['size'],
+    'data-dnt'      => $options['dnt'] ? 'true' : 'false',
+    'class'         => 'twitter-share-button',
   );
+
+  return $attributes;
 }
 
 /**
- * Implementation of hook_block_info()
+ * Helper function to build attributes of follow button.
+ *
+ * @param array $options
+ *   Context specific options.
+ *
+ * @return
+ *   List of attributes to be rendered for follow button.
  */
-function tweetbutton_block_info() {
-  $blocks['tweetbutton_tweet'] = array(
-    'info' => t('Tweetbutton tweet'),
-  );  
-  $blocks['tweetbutton_follow'] = array(
-    'info' => t('Tweetbutton follow'),
+function tweetbutton_follow_get_attributes($options) {
+  $language = \Drupal::languageManager()->getCurrentLanguage();
+
+  $attributes = array(
+    'data-show-count'       => $options['show_count'] ? 'true': 'false',
+    'data-lang'             => $options['lang'] == 'auto' ? $language->id : $options['lang'],
+    'data-width'            => $options['width'] . 'px',
+    'data-show-screen-name' => $options['show_screen_name'] ? 'true' : 'false',
+    'data-size'             => $options['size'],
+    'data-dnt'              => $options['dnt'] ? 'true' : 'false',
+    'class'                 => 'twitter-follow-button',
   );
-  return $blocks;
-}
 
-/**
- * Implementation of hook_block_configure 
- */
-function tweetbutton_block_view($delta = '') {
-  if ($delta == 'tweetbutton_tweet') {
-    $block['subject'] = t('Tweetbutton tweet');
-    $block['content'] = theme('tweetbutton_tweet_display');
-    return $block; 
-  }
-  elseif ($delta == 'tweetbutton_follow') {
-    $block['subject'] = t('Tweetbutton follow');
-    $block['content'] = theme('tweetbutton_follow_display');
-    return $block;
+  if ($options['align'] !== 'none') {
+    $attributes['data-align'] = $options['align'];
   }
+
+  return $attributes;
 }
 
 /**
- * Helper function to build the required tweet attributes
- * @param $options
- *   Context specific options
- * @return 
- *   List of attributes to be rendered for twitter tweetbutton
+ * Helper function to build attributes of hashtag.
+ *
+ * @param array $options
+ *   Context specific options.
+ *
+ * @return
+ *   List of attributes to be rendered for hashtag.
  */
-function tweetbutton_tweet_get_attributes($options = array()) {
-  global $language;
-  
-  $default_option = array(
-    'type'        => variable_get('tweetbutton_button', 'vertical'),
-    'tweet_text'  => variable_get('tweetbutton_tweet_text'),
-    'language'    => variable_get('tweetbutton_language'),
-    'account'     => variable_get('tweetbutton_account'),
-    'rel_account' => variable_get('tweetbutton_rel_account_name'),
-    'rel_desc'    => variable_get('tweetbutton_rel_account_description'),
-    'size'        => variable_get('tweetbutton_size', 'medium')
-  );
-  
-  if (empty($options['url'])) {
-    $options['url'] = url($_GET['q'], array('absolute' => TRUE));  
-  }
-  
-  if (empty($options['count_url'])) {
-    $options['count_url'] = $options['url'];
-  }
-  
-  if (module_exists('shorten') && ($service = variable_get('tweetbutton_shorten_service'))) {
-    $url = shorten_url($options['url'], $service);
-    // if www => http://  replacement if enabled
-    if (variable_get('shorten_www', TRUE)) {
-      if (strpos($url, 'www.') === 0) {
-        $url = drupal_substr($url, 4);
-        $url = 'http://' . $url;
-      }
-    }
-    $options['url'] = $url;
-  }
-  
-  
-  $options += $default_option;
-  
-  $attributes =  array(
-    'data-size'    => $options['size'],
-    'data-count'   => $options['type'],
-    'data-via'     => $options['account'],
-    'data-related' => $options['rel_account'] . ':' . $options['rel_desc'],
-    'data-text'    => $options['tweet_text'],
-    'data-counturl'=> $options['count_url'],
-    'data-url'     => $options['url'],
-    'data-lang'    => $options['language'] == 'auto' ? $language->language : $options['language'],
-    'class'        => 'twitter-share-button',
+function tweetbutton_hashtag_get_attributes($options) {
+  $language = \Drupal::languageManager()->getCurrentLanguage();
+  $default_options = array(
+    'rel_account'     => variable_get('tweetbutton_account'),
   );
 
-  return $attributes;
-}
+  $options += $default_options;
 
+  $attributes = array(
+    'data-related' => $options['rel_account'],
+    'data-lang' => $options['language'] == 'auto'? $language->id: $options['language'],
+    'class' => 'twitter-hashtag-button',
+  );
+}
 
+/**
+ * Returns HTML for a tweet button.
+ *
+ * @param array $variables
+ *   An associative array with options of tweet button.
+ */
 function theme_tweetbutton_tweet_display($variables) {
   $script_url = url('http://platform.twitter.com/widgets.js', array('external' => TRUE, 'https' => TRUE));
-  drupal_add_js($script_url, array('type' => 'external', 'scope' => 'footer'));
+
   $options = $variables['options'];
   $attributes = tweetbutton_tweet_get_attributes($options);
- 
+
   $tweetbutton_label = isset($options['tweetbutton_label'])? $options['tweetbutton_label']: t('Tweet');
   $tweet_link = l($tweetbutton_label, 'http://twitter.com/share', array('attributes' => $attributes, 'external' => TRUE, 'https' => TRUE));
-  $link = '<div class="tweetbutton-tweet tweetbutton">' . $tweet_link . '</div>';
-
-  return $link;
-}
-
 
-function tweetbutton_follow_get_attributes($options) {
-  global $language;
-  $default_options = array(
-    'show_count'       => variable_get('tweetbutton_follow_show_count', TRUE),
-    'show_screen_name' => variable_get('tweetbutton_follow_screen_name'),
-    'size'             => variable_get('tweetbutton_follow_size'),
-    'language'         => variable_get('tweetbutton_language'),
-  );
-  
-  $options += $default_options;
-  
-  $attributes = array(
-    'data-show-count'       => $options['show_count']? 'true': 'false',
-    'data-show-screen-name' => $options['show_screen_name'],
-    'data-size'             => $options['size'],
-    'data-lang'             => $options['language'] == 'auto' ? $language->language : $options['language'],
-    'class'                 => 'twitter-follow-button',
+  $link = array(
+    '#markup' => $tweet_link,
+    '#prefix' => '<div class="tweetbutton-tweet tweetbutton">',
+    '#suffix' => '</div>',
+    '#attached' => array(
+      'js' => array(
+        $script_url => array(
+          'type' => 'external',
+          'scope' => 'footer',
+        ),
+      ),
+    ),
   );
-  return $attributes;
+
+  return drupal_render($link);
 }
 
+/**
+ * Returns HTML for a follow button.
+ *
+ * @param array $variables
+ *   An associative array with options of follow button.
+ */
 function theme_tweetbutton_follow_display($variables) {
   $script_url = url('http://platform.twitter.com/widgets.js', array('external' => TRUE, 'https' => TRUE));
-  drupal_add_js($script_url, array('type' => 'external', 'scope' => 'footer'));
-  
+
   $options = $variables['options'];
-  $screen_name = $variables['screen_name'];
-  if (empty($screen_name)) {
-    $screen_name = variable_get('tweetbutton_follow_screen_name');
-  }
-  $follow_user_text = isset($options['tweetbutton_label'])? $options['tweetbutton_label']: t('Follow !screen_name', array('!screen_name' => $screen_name));
- 
+
+  $screen_name = !empty($options['screen_name']) ? $options['screen_name'] : \Drupal::config('tweetbutton.settings')->get('tweetbutton_follow_screen_name');
+
+  $follow_text = t('Follow !screen_name', array('!screen_name' => $screen_name));
   $twitter_account_link = 'http://twitter.com/' . $screen_name;
-  
+
   $attributes = tweetbutton_follow_get_attributes($options);
-  
-  $follow_link = l($follow_user_text, $twitter_account_link,array('attributes' => $attributes, 'external' => TRUE, 'https' => TRUE));
-  $link = '<div class="tweetbutton-follow tweetbutton">' . $follow_link . '</div>';
-  return $link;
-}
 
-function tweetbutton_hashtag_get_attributes($options) {
-  global $language;
-  $default_options = array(
-    'rel_account'     => variable_get('tweetbutton_account'),
-  );
-  
-  $options += $default_options;
-  
-  $attributes = array(
-    'data-related' => $options['rel_account'],
-    'data-lang' => $options['language'] == 'auto'? $language->language: $options['language'],
-    'class' => 'twitter-hashtag-button',
+  $follow_link = l($follow_text, $twitter_account_link, array('attributes' => $attributes, 'external' => TRUE, 'https' => TRUE));
+
+  $link = array(
+    '#markup' => $follow_link,
+    '#prefix' => '<div class="tweetbutton-follow tweetbutton">',
+    '#suffix' => '</div>',
+    '#attached' => array(
+      'js' => array(
+        $script_url => array(
+          'type' => 'external',
+          'scope' => 'footer',
+        ),
+      ),
+    ),
   );
+
+  return drupal_render($link);
 }
 
+/**
+ * Returns HTML for a hashtag.
+ *
+ * @param array $variables
+ *   An associative array with options of hashtag.
+ */
 function theme_tweetbutton_hashtag_display($variables) {
   $script_url = url('http://platform.twitter.com/widgets.js', array('external' => TRUE));
-  drupal_add_js($script_url, array('type' => 'external', 'scope' => 'footer'));
-  
+
   $options = $variables['options'];
   $attributes = tweetbutton_hashtag_get_attributes($options);
+
   $query = array();
   if (!empty($options['tweet_text'])) {
     $query['tweet_text'] = $options['tweet_text'];
   }
-  
+
   if (!empty($variables['hashtag'])) {
     $query['button_hashtag'] = $variables['hashtag'];
   }
-  
-  $hash_link = l($hash_text, 'http://twitter.com/intent/tweet', array('query' => $query, 'attributes' => $attributes, 'external' => TRUE, 'https' => TRUE));
-  return '<div class="tweetbutton-hashtag tweetbutton">' . $hash_link . '</div>';
-}
\ No newline at end of file
+
+  $hash_link = l($hash_text, 'http://twitter.com/intent/tweet', array(
+    'query'      => $query,
+    'attributes' => $attributes,
+    'external'   => TRUE,
+    'https'      => TRUE,
+  ));
+
+  $hash_link = array(
+    '#markup' => $hash_link,
+    '#prefix' => '<div class="tweetbutton-hashtag tweetbutton">',
+    '#suffix' => '</div>',
+    '#attached' => array(
+      'js' => array(
+        $script_url => array(
+          'type' => 'external',
+          'scope' => 'footer',
+        ),
+      ),
+    ),
+  );
+
+  return drupal_render($hash_link);
+}
diff --git a/tweetbutton.routing.yml b/tweetbutton.routing.yml
new file mode 100644
index 0000000..d6cf396
--- /dev/null
+++ b/tweetbutton.routing.yml
@@ -0,0 +1,7 @@
+tweetbutton.settings:
+  path: '/admin/config/services/tweetbutton'
+  defaults:
+    _form: '\Drupal\tweetbutton\Form\TweetbuttonSettingsForm'
+    _title: 'Tweet Button'
+  requirements:
+    _permission: 'administer tweetbutton'
