diff --git a/README.txt b/README.txt
deleted file mode 100644
index bd505ee..0000000
--- a/README.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-SUMMARY - YouTube Field
-========================
-The YouTube field module provides a simple field that allows you to add a
-YouTube video to a content type, user, or any entity.
-
-Display types include:
-
- * YouTube videos of various sizes and options.
- * YouTube thumbnails with image styles.
-
-
-REQUIREMENTS
--------------
-All dependencies of this module are enabled by default in Drupal 7.x.
-
-
-INSTALLATION
--------------
-Install this module as usual. Please see
-http://drupal.org/documentation/install/modules-themes/modules-7
-
-
-USAGE
--------
-To use this module create a new field of type 'YouTube video'. This field will
-accept YouTube URLs of the following formats:
-
- * http://youtube.com/watch?v=[video_id]
- * http://youtu.be/[video_id]
-
-It will not be a problem if users submit values with http:// or https:// and
-additional parameters after the URL will be ignored.
-
-
-CONFIGURATION
---------------
-Global module settings can be found at admin/config/media/youtube.
-
-The video output of a YouTube field can be manipulated in three ways:
- * global parameters found on the configuration page mentioned above
- * field-specific parameters found in that particular field's display settings
- * Views settings for the specific field
-
-The thumbnail of the YouTube image can also be used and can link to either the
-content, the video on YouTube, or nothing at all.
-
-To configure the field settings:
-
- 1. click 'manage display' on the listing of entity types
- 2. click the configuration gear to the right of the YouTube field
-
-
-SUPPORT
---------
-Please use the issue queue to report bugs or request support:
-http://drupal.org/project/issues/youtube
diff --git a/config/youtube.settings.yml b/config/youtube.settings.yml
new file mode 100644
index 0000000..8239888
--- /dev/null
+++ b/config/youtube.settings.yml
@@ -0,0 +1,9 @@
+youtube_suggest: true
+youtube_modestbranding: false
+youtube_theme: false
+youtube_color: false
+youtube_enablejsapi: false
+youtube_playerid: ""
+youtube_wmode: true
+youtube_privacy: false
+youtube_thumb_dir: "youtube"
\ No newline at end of file
diff --git a/lib/Drupal/youtube/Form/YoutubeSettingsForm.php b/lib/Drupal/youtube/Form/YoutubeSettingsForm.php
new file mode 100644
index 0000000..463ceba
--- /dev/null
+++ b/lib/Drupal/youtube/Form/YoutubeSettingsForm.php
@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\youtube\Form\YoutubeSettingsForm.
+ */
+
+namespace Drupal\youtube\Form;
+
+use Drupal\Core\Form\ConfigFormBase;
+
+/**
+ * Configure Youtube settings for this site.
+ */
+class YoutubeSettingsForm extends ConfigFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormID() {
+    return 'youtube_settings';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, array &$form_state) {
+    $config = $this->configFactory->get('youtube.settings');
+    $form['text'] = array(
+      '#type' => 'markup',
+      '#markup' => '<p>' . t('The following settings will be used as default values 
+        on all YouTube video fields.  Many of these settings can be overridden
+        on a per-field basis.') . '</p>',
+    );
+    $form['youtube_global'] = array(
+      '#type' => 'fieldset',
+      '#title' => 'Video Parameters',
+    );
+    $form['youtube_global']['youtube_suggest'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Show suggested videos when the video finishes'),
+      '#default_value' => $config->get('youtube_suggest'),
+    );
+    $form['youtube_global']['youtube_modestbranding'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Do not show YouTube logo on video player (modestbranding).'),
+      '#default_value' => $config->get('youtube_modestbranding'),
+    );
+    $form['youtube_global']['youtube_theme'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Use a light colored control bar for video player controls (theme).'),
+      '#default_value' => $config->get('youtube_theme'),
+    );
+    $form['youtube_global']['youtube_color'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Use a white colored video progress bar (color).'),
+      '#default_value' => $config->get('youtube_color'),
+      '#description' => 'Note: the modestbranding parameter will be ignored when this is in use.',
+    );
+    $form['youtube_global']['youtube_enablejsapi'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Enable use of the JavaScript API (enablejsapi, origin).'),
+      '#default_value' => $config->get('youtube_enablejsapi'),
+      '#description' => 'For more information on the Javascript API and how to use it, see the <a href="https://developers.google.com/youtube/js_api_reference">JavaScript API documentation</a>.',
+    );
+    $form['youtube_global']['youtube_playerid'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Javascript API Player ID'),
+      '#default_value' => $config->get('youtube_playerid'),
+      '#states' => array(
+        'visible' => array(
+          ':input[name="youtube_enablejsapi"]' => array('checked' => TRUE),
+        ),
+      ),
+    );
+    $form['youtube_global']['youtube_wmode'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Fix overlay problem on IE8 and lower'),
+      '#default_value' => $config->get('youtube_wmode'),
+      '#description' => t('Checking this will fix the issue of a YouTube video showing above a modal window (including Drupal\'s Overlay). This is needed if you have Overlay users in IE or have modal windows throughout your site.'),
+    );
+    $form['youtube_privacy'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Enable privacy-enhanced mode'),
+      '#default_value' => $config->get('youtube_privacy'),
+      '#description' => t('Checking this box will prevent YouTube from setting cookies in your site visitors browser.'),
+    );
+    $form['youtube_thumb_dir'] = array(
+      '#type' => 'textfield',
+      '#title' => t('YouTube thumbnail directory'),
+      '#field_prefix' => settings()->get('file_public_path', conf_path() . '/files') . '/',
+      '#field_suffix' => '/thumbnail.png',
+      '#description' => t('Location, within the files directory, where you would like the YouTube thumbnails stored.'),
+      '#default_value' => $config->get('youtube_thumb_dir'),
+    );
+
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, array &$form_state) {
+    $config = $this->configFactory->get('youtube.settings');
+    $config->set('youtube_suggest', $form_state['values']['youtube_suggest']);
+    $config->set('youtube_modestbranding', $form_state['values']['youtube_modestbranding']);
+    $config->set('youtube_theme', $form_state['values']['youtube_theme']);
+    $config->set('youtube_color', $form_state['values']['youtube_color']);
+    $config->set('youtube_enablejsapi', $form_state['values']['youtube_enablejsapi']);
+    $config->set('youtube_playerid', $form_state['values']['youtube_playerid']);
+    $config->set('youtube_privacy', $form_state['values']['youtube_privacy']);
+    $config->set('youtube_wmode', $form_state['values']['youtube_wmode']);
+    $config->set('youtube_thumb_dir', $form_state['values']['youtube_thumb_dir']);
+    $config->save();
+    parent::submitForm($form, $form_state);
+  }
+
+}
diff --git a/lib/Drupal/youtube/Plugin/field/FieldFormatter/YouTubeFormatter.php b/lib/Drupal/youtube/Plugin/field/FieldFormatter/YouTubeFormatter.php
new file mode 100644
index 0000000..1f2e44c
--- /dev/null
+++ b/lib/Drupal/youtube/Plugin/field/FieldFormatter/YouTubeFormatter.php
@@ -0,0 +1,154 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\youtube\Plugin\field\FieldFormatter\YouTubeFormatter.
+ */
+
+namespace Drupal\youtube\Plugin\field\FieldFormatter;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FormatterBase;
+
+/**
+ * Plugin implementation of the 'youtube' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "youtube",
+ *   label = @Translation("YouTube video"),
+ *   field_types = {
+ *     "youtube"
+ *   },
+ *   settings = {
+ *     "youtube_size" = "450x315",
+ *     "youtube_width" = "",
+ *     "youtube_height" = "",
+ *     "youtube_autoplay" = "",
+ *     "youtube_showinfo" = "",
+ *     "youtube_controls" = "",
+ *     "youtube_autohide" = "",
+ *     "youtube_iv_load_policy" = ""
+ *   }
+ * )
+ */
+class YouTubeFormatter extends FormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state) {
+    $elements = parent::settingsForm($form, $form_state);
+
+    $elements['youtube_size'] = array(
+      '#type' => 'select',
+      '#title' => t('YouTube video size'),
+      '#options' => youtube_size_options(),
+      '#default_value' => $this->getSetting('youtube_size'),
+    );
+    $elements['youtube_width'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Width'),
+      '#size' => 10,
+      '#default_value' => $this->getSetting('youtube_width'),
+      '#states' => array(
+        'visible' => array(
+          ':input[name*="youtube_size"]' => array('value' => 'custom'),
+        ),
+      ),
+    );
+    $elements['youtube_height'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Height'),
+      '#size' => 10,
+      '#default_value' => $this->getSetting('youtube_height'),
+      '#states' => array(
+        'visible' => array(
+          ':input[name*="youtube_size"]' => array('value' => 'custom'),
+        ),
+      ),
+    );
+    $elements['youtube_autoplay'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Play video automatically when loaded (autoplay).'),
+      '#default_value' => $this->getSetting('youtube_autoplay'),
+    );
+
+    $elements['youtube_showinfo'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Hide video title and uploader info (showinfo).'),
+      '#default_value' => $this->getSetting('youtube_showinfo'),
+    );
+    $elements['youtube_controls'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Always hide video controls (controls).'),
+      '#default_value' => $this->getSetting('youtube_controls'),
+    );
+    $elements['youtube_autohide'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Hide video controls after play begins (autohide).'),
+      '#default_value' => $this->getSetting('youtube_autohide'),
+    );
+    $elements['youtube_iv_load_policy'] = array(
+      '#type' => 'checkbox',
+      '#title' => t('Hide video annotations by default (iv_load_policy).'),
+      '#default_value' => $this->getSetting('youtube_iv_load_policy'),
+    );
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+    $cp = "";
+    $youtube_size = $this->getSetting('youtube_size');
+
+    $parameters = array(
+      $this->getSetting('youtube_autoplay'),
+      $this->getSetting('youtube_showinfo'),
+      $this->getSetting('youtube_controls'),
+      $this->getSetting('youtube_autohide'),
+      $this->getSetting('youtube_iv_load_policy'),
+    );
+
+    foreach ($parameters as $parameter) {
+    if ($parameter) {
+        $cp = t(', custom parameters');
+        break;
+      }
+    }
+    $summary[] = t('YouTube video: @youtube_size@cp',array('@youtube_size' => $youtube_size,'@cp' => $cp));
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareView(array $entities_items) {
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items) {
+    $element = array();
+    $settings = $this->getSettings();
+
+    foreach ($items as $delta => $item) {
+      $element[$delta] = array(
+        '#theme' => 'youtube_video',
+        '#video_id' => $item->video_id,
+        '#size' => $settings['youtube_size'],
+        '#width' => $settings['youtube_width'],
+        '#height' => $settings['youtube_height'],
+        '#autoplay' => $settings['youtube_autoplay'],
+        '#showinfo' => $settings['youtube_showinfo'],
+        '#controls' => $settings['youtube_controls'],
+        '#autohide' => $settings['youtube_autohide'],
+        '#iv_load_policy' => $settings['youtube_iv_load_policy'],
+      );
+    }
+    return $element;
+  }
+}
\ No newline at end of file
diff --git a/lib/Drupal/youtube/Plugin/field/FieldFormatter/YouTubeThumbFormatter.php b/lib/Drupal/youtube/Plugin/field/FieldFormatter/YouTubeThumbFormatter.php
new file mode 100644
index 0000000..5a192d6
--- /dev/null
+++ b/lib/Drupal/youtube/Plugin/field/FieldFormatter/YouTubeThumbFormatter.php
@@ -0,0 +1,115 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\youtube\Plugin\field\FieldFormatter\YouTubeThumbFormatter.
+ */
+
+namespace Drupal\youtube\Plugin\field\FieldFormatter;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\FieldItemInterface;
+use Drupal\Core\Field\FormatterBase;
+
+
+/**
+ * Plugin implementation of the 'youtube_thumb' formatter.
+ *
+ * @FieldFormatter(
+ *   id = "youtube_thumb",
+ *   label = @Translation("YouTube thumbnail"),
+ *   field_types = {
+ *     "youtube"
+ *   },
+ *   settings = {
+ *     "image_style" = "thumbnail",
+ *     "image_link" = ""
+ *   }
+ * )
+ */
+class YouTubeThumbFormatter extends FormatterBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state) {
+    $elements = parent::settingsForm($form, $form_state);
+
+    $elements['image_style'] = array(
+      '#type' => 'select',
+      '#title' => t('Image style'),
+      '#options' => image_style_options(FALSE),
+      '#default_value' => $this->getSetting('image_style'),
+      '#empty_option' => t('None (original image)'),
+    );
+    $link_types = array(
+      'content' => t('Content'),
+      'youtube' => t('YouTube'),
+    );
+    $elements['image_link'] = array(
+      '#title' => t('Link image to'),
+      '#type' => 'select',
+      '#default_value' => $this->getSetting('image_link'),
+      '#empty_option' => t('Nothing'),
+      '#options' => $link_types,
+    );
+
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+    $image_link = $this->getSetting('image_link');
+    $image_link = !empty($image_link) ? t(" linked to @image_link",array('@image_link' => $image_link)) : "";
+    $summary[] = t('Image style: @image_style@image_link',array('@image_style' => $this->getSetting('image_style'),'@image_link' => $image_link));
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function prepareView(array $entities_items) {}
+
+  /**
+   * {@inheritdoc}
+   */
+  public function viewElements(FieldItemListInterface $items) {
+    $element = array();
+    $entity = $items->getEntity();
+    $image_link = $this->getSetting('image_link');
+
+    // Check if the formatter involves a link.
+    if (!empty($image_link)) {
+      if ($image_link == 'content') {
+        $uri = $entity->uri();
+        $uri['options']['html'] = TRUE;
+      }
+      elseif ($image_link == 'youtube') {
+        $link_youtube = TRUE;
+      }
+    }
+
+    foreach ($items as $delta => $item) {
+      // If the thumbnail is linked to its youtube page, take the original url.
+      if (isset($link_youtube) && $link_youtube) {
+        $uri = array(
+          'path' => $item->input,
+          'options' => array('html' => TRUE),
+        );
+      }
+
+      $element[$delta] = array(
+        '#theme' => 'youtube_thumbnail',
+        '#video_id' => $item->video_id,
+        '#image_style' => $this->getSetting('image_style'),
+        '#image_link' => isset($uri) ? $uri : '',
+      );
+    }
+
+    return $element;
+  }
+}
\ No newline at end of file
diff --git a/lib/Drupal/youtube/Plugin/field/FieldType/YouTubeItem.php b/lib/Drupal/youtube/Plugin/field/FieldType/YouTubeItem.php
new file mode 100644
index 0000000..a72f418
--- /dev/null
+++ b/lib/Drupal/youtube/Plugin/field/FieldType/YouTubeItem.php
@@ -0,0 +1,80 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\youtube\Plugin\field\FieldType\YouTubeItem.
+ */
+
+namespace Drupal\youtube\Plugin\field\FieldType;
+
+use Drupal\Core\Field\ConfigFieldItemBase;
+use Drupal\field\FieldInterface;
+
+/**
+ * Plugin implementation of the 'youtube' field type.
+ *
+ * @FieldType(
+ *   id = "youtube",
+ *   label = @Translation("YouTube video"),
+ *   description = @Translation("This field stores a YouTube video in the database."),
+ *   default_widget = "youtube_default",
+ *   default_formatter = "youtube"
+ * )
+ */
+class YouTubeItem extends ConfigFieldItemBase {
+
+  /**
+   * Definitions of the contained properties.
+   *
+   * @var array
+   */
+  static $propertyDefinitions;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function schema(FieldInterface $field) {
+    return array(
+      'columns' => array(
+        'input' => array(
+          'description' => 'The video url.',
+          'type' => 'varchar',
+          'length' => 1024,
+          'not null' => FALSE,
+        ),
+        'video_id' => array(
+          'description' => 'The video id.',
+          'type' => 'varchar',
+          'length' => 15,
+          'not null' => FALSE,
+        ),
+      ),
+    );
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPropertyDefinitions() {
+    if (!isset(static::$propertyDefinitions)) {
+      static::$propertyDefinitions['input'] = array(
+        'type' => 'string',
+        'label' => t('video url'),
+      );
+      static::$propertyDefinitions['video_id'] = array(
+        'type' => 'string',
+        'label' => t('Video id'),
+      );
+    }
+    return static::$propertyDefinitions;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isEmpty() {
+    $value = $this->get('input')->getValue();
+    return $value === NULL || $value === '';
+  }
+
+}
\ No newline at end of file
diff --git a/lib/Drupal/youtube/Plugin/field/FieldWidget/YouTubeDefaultWidget.php b/lib/Drupal/youtube/Plugin/field/FieldWidget/YouTubeDefaultWidget.php
new file mode 100644
index 0000000..d487ccd
--- /dev/null
+++ b/lib/Drupal/youtube/Plugin/field/FieldWidget/YouTubeDefaultWidget.php
@@ -0,0 +1,98 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\youtube\Plugin\field\FieldWidget\YouTubeDefaultWidget.
+ */
+
+namespace Drupal\youtube\Plugin\field\FieldWidget;
+
+use Drupal\Core\Field\FieldItemListInterface;
+use Drupal\Core\Field\WidgetBase;
+
+/**
+ * Plugin implementation of the 'youtube_default' widget.
+ *
+ * @FieldWidget(
+ *   id = "youtube_default",
+ *   label = @Translation("YouTube video widget"),
+ *   field_types = {
+ *     "youtube"
+ *   },
+ *   settings = {
+ *     "placeholder_url" = ""
+ *   }
+ * )
+ */
+class YouTubeDefaultWidget extends WidgetBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsForm(array $form, array &$form_state) {
+    $elements = parent::settingsForm($form, $form_state);
+
+    $elements['placeholder_url'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Placeholder for URL'),
+      '#default_value' => $this->getSetting('placeholder_url'),
+      '#description' => t('Text that will be shown inside the field until a value is entered. This hint is usually a sample value or a brief description of the expected format.'),
+    );
+    return $elements;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function settingsSummary() {
+    $summary = array();
+
+    $placeholder_url = $this->getSetting('placeholder_url');
+    if (empty($placeholder_url)) {
+      $summary[] = t('No placeholders');
+    }
+    else {
+      if (!empty($placeholder_url)) {
+        $summary[] = t('URL placeholder: @placeholder_url', array('@placeholder_url' => $placeholder_url));
+      }
+    }
+
+    return $summary;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, array &$form_state) {
+    $element['input'] = array(
+      '#type' => 'textfield',
+      '#title' => t('Video url'),
+      '#placeholder' => $this->getSetting('placeholder_url'),
+      '#default_value' => isset($items[$delta]->input) ? $items[$delta]->input : NULL,
+      '#maxlength' => 255,
+      '#element_validate' => array(array($this, 'validateInput')),
+    );
+    
+    return $element;
+  }
+
+  /**
+   * Validate video URL.
+   */
+  public function validateInput(&$element, &$form_state, $form) {
+    $input = $element['#value'];
+    $video_id = youtube_get_video_id($input);
+
+    if ($video_id) {
+      $video_id_element = array(
+        '#parents' => $element['#parents'],
+      );
+      array_pop($video_id_element['#parents']);
+      $video_id_element['#parents'][] = 'video_id';
+      form_set_value($video_id_element, $video_id, $form_state);
+    } elseif (!empty($input)) {
+      form_error($element,'Invalid URL format');
+    }
+  }
+
+}
\ No newline at end of file
diff --git a/youtube.inc b/youtube.inc
deleted file mode 100644
index cbbb167..0000000
--- a/youtube.inc
+++ /dev/null
@@ -1,316 +0,0 @@
-<?php
-
-/**
- * @ file
- * YouTube field helper functions.
- */
-
-/**
- * Extracts the video_id from the submitted field value.
- *
- * @param $input
- *   The input submitted to the field.
- *
- * @return
- *   Returns the video_id if available, or FALSE if not.
- */
-function youtube_get_video_id($input) {
-  // The video URL in the format http://youtube.com/watch?v=1SqBdS0XkV4.
-  if (strstr($input, 'youtube.com/watch?') && preg_match('/v=[^&]*(?=&|$)/', $input, $matches)) {
-    $video_id = ltrim($matches[0], 'v=');
-  }
-
-  // The video URL in the format http://youtu.be/1SqBdS0XkV4.
-  elseif (strstr($input, 'youtu.be/')) {
-    $anchor = 'be/';
-    $position = strpos($input, $anchor);
-    $video_id = trim(substr($input, $position + strlen($anchor)));
-    // Remove additional query parameters.
-    if ($param = strpos($video_id, '?')) {
-      $video_id = substr($video_id, 0, $param);
-    }
-  }
-
-  if (!empty($video_id)) {
-    return $video_id;
-  }
-
-  return FALSE;
-}
-
-/**
- * Returns a list of standard YouTube video sizes.
- */
-function youtube_size_options() {
-  return array(
-    '420x315' => '450px by 315px',
-    '480x360' => '480px by 360px',
-    '640x480' => '640px by 480px',
-    '960x720' => '960px by 720px',
-    'custom' => 'custom',
-  );
-}
-
-/**
- * Splits height and width when given size, as from youtube_size_options.
- */
-function youtube_get_dimensions($size = NULL, $width = NULL, $height = NULL) {
-  $dimensions = array();
-  if ($size == 'custom') {
-    $dimensions['width'] = (int) $width;
-    $dimensions['height'] = (int) $height;
-  }
-  else {
-    // Locate the 'x'.
-    $strpos = strpos($size, 'x');
-    // Width is the first dimension.
-    $dimensions['width'] = substr($size, 0, $strpos);
-    // Height is the second dimension.
-    $dimensions['height'] = substr($size, $strpos + 1, strlen($size));
-  }
-
-  return $dimensions;
-}
-
-/**
- * Retreve youtube thumbnail image via YouTube API.
- *
- * TODO add error messaging if something goes wrong, and return FALSE.
- */
-function youtube_get_remote_image($id = NULL) {
-  $path = 'http://gdata.youtube.com/feeds/api/videos/' . $id;
-  $query = array(
-    'v' => '2',
-    'alt' => 'jsonc'
-  );
-  $url = url($path, array('query' => $query));
-  $result = drupal_http_request($url);
-  $data = json_decode($result->data);
-  // Get the high quality default thumbnail.
-  $src = $data->data->thumbnail->hqDefault;
-
-  // Make the actual request to download the file.
-  $image_result = drupal_http_request($src);
-
-  // Assure the youtube thumbnail directory exists.
-  $files = variable_get('file_public_path', conf_path() . '/files');
-  $youtube_dir = variable_get('youtube_thumb_dir', 'youtube');
-  $youtube_path = $files . '/' . $youtube_dir;
-  if (!file_prepare_directory($youtube_path, FILE_CREATE_DIRECTORY) && !mkdir($youtube_path, 0775, TRUE)) {
-    watchdog('youtube', 'Failed to create YouTube thumbnail directory: %dir', array('%dir' => $youtube_path), WATCHDOG_ERROR);
-  }
-
-  // Save the file.
-  $dest = $files . '/' . $youtube_dir . '/' . $id . '.png';
-  file_put_contents($dest, $image_result->data);
-
-  return TRUE;
-}
-
-/**
- * Get images by building correctly formed URL - kinda hackey.
- */
-function youtube_build_remote_image_path($id = NULL) {
-  if (!$id) {
-    return;
-  }
-  // Default image thumbnail.
-  $default = 'http://img.youtube.com/vi/' . $id . '/default.jpg';
-
-  // Full size image.
-  $full_size = 'http://img.youtube.com/vi/' . $id . '/0.jpg';
-  // High Quality version of the default thumbnail.
-  $hq_default = 'http://img.youtube.com/vi/' . $id . '/hqdefault.jpg';
-  // High Resolution version of the default thumbnail.
-  $max_res_default = 'http://img.youtube.com/vi/' . $id . '/maxresdefault.jpg'; // May not work.
-  // First thumbnail.
-  $thumb1 = 'http://img.youtube.com/vi/' . $id . '/1.jpg';
-  // Second thumbnail.
-  $thumb2 = 'http://img.youtube.com/vi/' . $id . '/2.jpg';
-  // Third thumbnail.
-  $thumb3 = 'http://img.youtube.com/vi/' . $id . '/3.jpg';
-
-  return url($default);
-}
-
-/**
- * Implements hook_feeds_processor_targets_alter().
- *
- * Adds a target option for YouTube fields to Feeds mapping options.
- *
- * @param &$targets
- *   Array containing the targets to be offered to the user. Add to this array
- *   to expose additional options. Remove from this array to suppress options.
- *   Remove with caution.
- * @param $entity_type
- *   The entity type of the target, for instance a 'node' entity.
- * @param $bundle_name
- *   The bundle name for which to alter targets.
- */
-function youtube_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
-  foreach (field_info_instances($entity_type, $bundle_name) as $name => $instance) {
-    $info = field_info_field($name);
-
-    if (in_array($info['type'], array('youtube'))) {
-      $targets[$name] = array(
-        'name' => check_plain($instance['label']),
-        'callback' => 'youtube_set_target',
-        'description' => t('The @label field of the node.', array('@label' => $instance['label'])),
-      );
-    }
-  }
-}
-
-/**
- * Callback to set the Feeds target for a YouTube field.
- *
- * @param $source
- *   Field mapper source settings.
- * @param $entity
- *   An entity object, for instance a node object.
- * @param $target
- *   A string identifying the target on the node.
- * @param $value
- *   The value to populate the target with.
- */
-function youtube_set_target($source, $entity, $target, $value, $mapping) {
-  $video_id = youtube_get_video_id($value);
-  if ($video_id) {
-    $entity->{$target}[LANGUAGE_NONE][0] = array(
-      'input' => $value,
-      'video_id' => $video_id,
-    );
-  }
-}
-
-/**
- * Implements hook_token_info_alter().
- *
- * Alters and adds tokens for each youtube field.
- *
- * @param $data
- *   The associative array of token definitions from hook_token_info().
- */
-function youtube_token_info_alter(&$data) {
-  // Get all youtube fields. Gather entity_type and bundle information.
-  $fields = field_info_fields();
-  $youtube_fields = array();
-  foreach ($fields as $name => $field) {
-    if ($field['type'] == 'youtube') {
-      foreach ($field['bundles'] as $type => $entity_type) {
-        foreach ($entity_type as $bundle) {
-          $youtube_fields[] = array(
-            'entity_type' => $type,
-            'bundle' => $bundle,
-            'field_name' => $name,
-          );
-        }
-      }
-    }
-  }
-
-  foreach ($youtube_fields as $field) {
-    $field_info = field_info_instance($field['entity_type'], $field['field_name'], $field['bundle']);
-    $field_label = $field_info['label'];
-
-    // Modify the default field token.
-    $data['tokens'][$field['entity_type']][$field['field_name']] = array(
-      'name' => $field_label . t(": Default"),
-      'description' => t("The YouTube video field value's Default (or Token if exists) view mode output."),
-    );
-
-    // Add two new tokens.
-    $data['tokens'][$field['entity_type']][$field['field_name'] . '__youtube_video_url'] = array(
-      'name' => $field_label . t(": Video URL"),
-      'description' => t("The YouTube video field value's youtube.com URL."),
-    );
-    $data['tokens'][$field['entity_type']][$field['field_name'] . '__youtube_image_url'] = array(
-      'name' => $field_label . t(": Image URL"),
-      'description' => t("The YouTube video field value's local image URL."),
-    );
-  }
-}
-
-/**
- * Provide replacement values for placeholder tokens.
- *
- * Replaces youtube_video_url and youtube_image_url tokens.
- *
- * @param $type
- *   The machine-readable name of the type (group) of token being replaced, such
- *   as 'node', 'user', or another type defined by a hook_token_info()
- *   implementation.
- * @param $tokens
- *   An array of tokens to be replaced. The keys are the machine-readable token
- *   names, and the values are the raw [type:token] strings that appeared in the
- *   original text.
- * @param $data
- *   (optional) An associative array of data objects to be used when generating
- *   replacement values, as supplied in the $data parameter to token_replace().
- * @param $options
- *   (optional) An associative array of options for token replacement; see
- *   token_replace() for possible values.
- *
- * @return
- *   An associative array of replacement values, keyed by the raw [type:token]
- *   strings from the original text.
- *
- * @see youtube_tokens_info_alter()
- */
-function youtube_tokens($type, $tokens, array $data = array(), array $options = array()) {
-  $url_options = array('absolute' => TRUE);
-  if (isset($options['language'])) {
-    $url_options['language'] = $options['language'];
-    $language_code = $options['language']->language;
-  }
-  else {
-    $language_code = NULL;
-  }
-  $sanitize = !empty($options['sanitize']);
-
-  $replacements = array();
-
-  if ($type == 'node' && !empty($data['node'])) {
-    $node = $data['node'];
-
-    foreach ($tokens as $name => $original) {
-      if (!strpos($name, '__youtube_')) {
-        // This isn't a youtube token!
-        return;
-      }
-
-      $token_pieces = explode('__', $name);
-      if (count($token_pieces) != 2) {
-        return;
-      }
-
-      $field_name = $token_pieces[0];
-      $token_name = $token_pieces[1];
-
-      switch ($token_name) {
-        case 'youtube_video_url':
-          $field = $node->$field_name;
-          $video_id = $field[LANGUAGE_NONE][0]['video_id'];
-          $replacements[$original] = 'http://www.youtube.com/watch?v=' . $video_id;
-          break;
-
-        case 'youtube_image_url':
-          global $base_url;
-          global $base_path;
-          $field = $node->$field_name;
-          $video_id = $field[LANGUAGE_NONE][0]['video_id'];
-          $file_path = variable_get('file_public_path', conf_path() . '/files') . '/';
-          $file_path .= variable_get('youtube_thumb_dir', 'youtube');
-          $file_path .= '/' . $video_id . '.png';
-          $full_path = $base_url . $base_path . $file_path;
-          if (!file_exists($full_path)) {
-            youtube_get_remote_image($video_id);
-          }
-          $replacements[$original] = $full_path;
-          break;
-      }
-    }
-  }
-
-  return $replacements;
-}
diff --git a/youtube.info b/youtube.info
deleted file mode 100644
index e34c9f5..0000000
--- a/youtube.info
+++ /dev/null
@@ -1,8 +0,0 @@
-name = YouTube Field
-description = Provides a YouTube widget for fields.
-package = Fields
-core = 7.x
-dependencies[] = field
-dependencies[] = image
-dependencies[] = file
-configure = admin/config/media/youtube
diff --git a/youtube.info.yml b/youtube.info.yml
new file mode 100644
index 0000000..295a9b0
--- /dev/null
+++ b/youtube.info.yml
@@ -0,0 +1,11 @@
+name: YouTube Field
+type: module
+description: 'Provides a YouTube widget for fields.'
+package: Fields
+version: 8.x-1.0
+core: 8.x
+dependencies:
+  - field
+  - image
+  - file
+configure: /admin/config/media/youtube
\ No newline at end of file
diff --git a/youtube.install b/youtube.install
deleted file mode 100644
index ec1f2eb..0000000
--- a/youtube.install
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-/**
- * @file
- * Install, update, and uninstall functions for the youtube module.
- */
-
-/**
- * Implements hook_field_schema().
- */
-function youtube_field_schema($field) {
-  $columns = array(
-    'input' => array(
-      'type' => 'varchar',
-      'length' => 1024,
-      'not null' => FALSE,
-    ),
-    'video_id' => array(
-      'type' => 'varchar',
-      'length' => 15,
-      'not null' => FALSE,
-    ),
-  );
-  $indexes = array(
-    'video_id' => array('video_id'),
-  );
-  return array(
-    'columns' => $columns,
-    'indexes' => $indexes,
-  );
-}
-
-/**
- * Implements hook_uninstall().
- */
-function youtube_uninstall() {
-  // Delete youtube variables when module is removed.
-  variable_del('youtube_suggest');
-  variable_del('youtube_modestbranding');
-  variable_del('youtube_theme');
-  variable_del('youtube_color');
-  variable_del('youtube_enablejsapi');
-  variable_del('youtube_playerid');
-  variable_del('youtube_privacy');
-  variable_del('youtube_thumb_dir');
-  variable_del('youtube_wmode');
-}
diff --git a/youtube.module b/youtube.module
index 6be2a54..17cf653 100644
--- a/youtube.module
+++ b/youtube.module
@@ -4,19 +4,19 @@
  * @file
  * Youtube field module adds a field for YouTube videos.
  */
-require_once (dirname(__FILE__) . '/youtube.inc');
+
+use Guzzle\Http\Exception\RequestException;
+use Drupal\field\Field;
 
 /**
  * Implements hook_menu().
  */
 function youtube_menu() {
   $items['admin/config/media/youtube'] = array(
-    'title' => 'YouTube settings',
-    'description' => 'Configure sitewide settings for embedded YouTube video fields.',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('youtube_settings_form'),
-    'access arguments' => array('administer youtube'),
-    'type' => MENU_NORMAL_ITEM,
+    'title' => 'YouTube settings', 
+    'description' => 'Settings form for Youtube field',
+    'route_name' => 'youtube_settings',
+    'type' => MENU_NORMAL_ITEM, 
   );
 
   return $items;
@@ -28,469 +28,468 @@ function youtube_menu() {
 function youtube_permission() {
   return array(
     'administer youtube' => array(
-      'title' => t('Administer YouTube field'),
-      'description' => t('Set default configurations for YouTube field settings.'),
-    ),
-  );
-}
-
-/**
- * Settings form for YouTube field module.
- */
-function youtube_settings_form($form) {
-  $form = array();
-  $form['text'] = array(
-    '#type' => 'markup',
-    '#markup' => '<p>' . t('The following settings will be used as default values
-      on all YouTube video fields.  More settings can be altered in the display
-      settings of individual fields.') . '</p>',
-  );
-  $form['youtube_global'] = array(
-    '#type' => 'fieldset',
-    '#title' => 'Video Parameters',
-  );
-  $form['youtube_global']['youtube_suggest'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Show suggested videos when the video finishes (rel).'),
-    '#default_value' => variable_get('youtube_suggest', TRUE),
-  );
-  $form['youtube_global']['youtube_modestbranding'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Do not show YouTube logo on video player (modestbranding).'),
-    '#default_value' => variable_get('youtube_modestbranding', FALSE),
-  );
-  $form['youtube_global']['youtube_theme'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Use a light colored control bar for video player controls (theme).'),
-    '#default_value' => variable_get('youtube_theme', FALSE),
-  );
-  $form['youtube_global']['youtube_color'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Use a white colored video progress bar (color).'),
-    '#default_value' => variable_get('youtube_color', FALSE),
-    '#description' => 'Note: the modestbranding parameter will be ignored when this is in use.',
-  );
-  $form['youtube_global']['youtube_enablejsapi'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Enable use of the JavaScript API (enablejsapi, origin).'),
-    '#default_value' => variable_get('youtube_enablejsapi', FALSE),
-    '#description' => 'For more information on the Javascript API and how to use it, see the <a href="https://developers.google.com/youtube/js_api_reference">JavaScript API documentation</a>.',
-  );
-  $form['youtube_global']['youtube_playerid'] = array(
-    '#type' => 'textfield',
-    '#title' => t('Javascript API Player ID'),
-    '#default_value' => variable_get('youtube_playerid', 'youtube-field-player'),
-    '#states' => array(
-      'visible' => array(
-        ':input[name="youtube_enablejsapi"]' => array('checked' => TRUE),
-      ),
+      'title' => t('Administer YouTube field'), 
     ),
   );
-  $form['youtube_global']['youtube_wmode'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Fix overlay problem in IE (wmode).'),
-    '#default_value' => variable_get('youtube_wmode', TRUE),
-    '#description' => t('Checking this will fix the issue of a YouTube video showing above elements with fixed or absolute positioning (including Drupal\'s Overlay and Toolbar).'),
-  );
-  $form['youtube_privacy'] = array(
-    '#type' => 'checkbox',
-    '#title' => t('Enable privacy-enhanced mode.'),
-    '#default_value' => variable_get('youtube_privacy', FALSE),
-    '#description' => t('Checking this box will prevent YouTube from setting cookies in your site visitors browser.'),
-  );
-  $form['youtube_thumb_dir'] = array(
-    '#type' => 'textfield',
-    '#title' => t('YouTube thumbnail directory'),
-    '#field_prefix' => variable_get('file_public_path', conf_path() . '/files') . '/',
-    '#field_suffix' => '/thumbnail.png',
-    '#description' => t('Location, within the files directory, where you would like the YouTube thumbnails stored.'),
-    '#default_value' => variable_get('youtube_thumb_dir', 'youtube'),
-  );
-
-  return system_settings_form($form);
 }
 
 /**
- * Implements hook_field_info().
+ * Extracts the video_id from the submitted field value.
+ *
+ * @param $input
+ *   The input submitted to the field.
+ *
+ * @return
+ *   Returns the video_id if available, or FALSE if not.
  */
-function youtube_field_info() {
-  return array(
-    // We name our field as the associative name of the array.
-    'youtube' => array(
-      'label' => t('YouTube video'),
-      'description' => t('A video hosted on YouTube.'),
-      'default_widget' => 'youtube',
-      'default_formatter' => 'youtube_video',
-    ),
-  );
-}
-
-/**
- * Implements hook_field_validate().
- */
-function youtube_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) {
-  foreach ($items as $delta => $item) {
-    if (!empty($item['input'])) {
-
-      $video_id = youtube_get_video_id($item['input']);
+function youtube_get_video_id($input) {
+  // The video URL in the format http://youtube.com/watch?v=1SqBdS0XkV4.
+  if (strstr($input, 'youtube.com/watch?') && preg_match('/v=[^&]*(?=&|$)/', $input, $matches)) {
+    $video_id = ltrim($matches[0], 'v=');
+  }
 
-      if (!$video_id) {
-        $errors[$field['field_name']][$langcode][$delta][] = array(
-          'error' => 'youtube_invalid',
-          'message' => t('Please provide a valid YouTube URL.'),
-        );
-      }
+  // The video URL in the format http://youtu.be/1SqBdS0XkV4.
+  elseif (strstr($input, 'youtu.be/')) {
+    $anchor = 'be/';
+    $position = strpos($input, $anchor);
+    $video_id = trim(substr($input, $position + strlen($anchor)));
+    // Remove additional query parameters.
+    if ($param = strpos($video_id, '?')) {
+      $video_id = substr($video_id, 0, $param);
     }
   }
+
+  if (!empty($video_id)) {
+    return $video_id;
+  }
+
+  return FALSE;
 }
 
 /**
- * Implements hook_field_is_empty().
+ * Returns a list of standard YouTube video sizes.
  */
-function youtube_field_is_empty($item, $field) {
-  return empty($item['input']);
+function youtube_size_options() {
+  return array(
+    '450x315' => '450px by 315px',
+    '480x360' => '480px by 360px',
+    '640x480' => '640px by 480px',
+    '960x720' => '960px by 720px',
+    'custom' => 'custom',
+  );
 }
 
 /**
- * Implements hook_field_formatter_info().
+ * Implements of hook_theme().
  */
-function youtube_field_formatter_info() {
-  $formatters =  array(
-    // This formatter displays your youtube video.
-    'youtube_video' => array(
-      'label' => t('YouTube video'),
-      'field types' => array('youtube'),
-      'settings' => array(
-        'youtube_size' => '420x315',
-        'youtube_width' => NULL,
-        'youtube_height' => NULL,
-        'youtube_autoplay' => FALSE,
-        'youtube_showinfo' => FALSE,
-        'youtube_controls' => FALSE,
-        'youtube_autohide' => FALSE,
-        'youtube_iv_load_policy' => FALSE,
-      ),
-    ),
-    // This formatter just displays a thumbnail for your video.
+function youtube_theme($existing, $type, $theme, $path) {
+  return array(
     'youtube_thumbnail' => array(
-      'label' => t('YouTube thumbnail'),
-      'field types' => array('youtube'),
-      'settings' => array(
-        'image_style' => 'thumbnail',
-        'image_link' => '',
+      'variables' => array('video_id' => NULL, 'image_style' => NULL, 'image_link' => NULL),
+    ),
+    'youtube_video' => array(
+      'variables' => array(
+        'video_id' => NULL,
+        'size' => NULL,
+        'width' => NULL,
+        'height' => NULL,
+        'autoplay' => FALSE,
+        'showinfo' => FALSE,
+        'controls' => FALSE,
+        'autohide' => FALSE,
+        'iv_load_policy' => FALSE,
       ),
     ),
   );
-
-  return $formatters;
 }
 
 /**
- * Implements hook_field_formatter_settings_form().
+ * Theme function for videos.
  */
-function youtube_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
-  $display = $instance['display'][$view_mode];
-  $settings = $display['settings'];
-
-  if ($display['type'] == 'youtube_video') {
-    $element['youtube_size'] = array(
-      '#type' => 'select',
-      '#title' => t('YouTube video size'),
-      '#options' => youtube_size_options(),
-      '#default_value' => $settings['youtube_size'],
-    );
-    $element['youtube_width'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Width'),
-      '#size' => 10,
-      '#default_value' => $settings['youtube_width'],
-      '#states' => array(
-        'visible' => array(
-          ':input[name="fields[' . $field['field_name'] . '][settings_edit_form][settings][youtube_size]"]' => array('value' => 'custom'),
-        ),
-      ),
-    );
-    $element['youtube_height'] = array(
-      '#type' => 'textfield',
-      '#title' => t('Height'),
-      '#size' => 10,
-      '#default_value' => $settings['youtube_height'],
-      '#states' => array(
-        'visible' => array(
-          ':input[name="fields[' . $field['field_name'] . '][settings_edit_form][settings][youtube_size]"]' => array('value' => 'custom'),
-        ),
-      ),
-    );
-    $element['youtube_autoplay'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Play video automatically when loaded (autoplay).'),
-      '#default_value' => $settings['youtube_autoplay'],
-    );
-    $element['youtube_showinfo'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Hide video title and uploader info (showinfo).'),
-      '#default_value' => $settings['youtube_showinfo'],
-    );
-    $element['youtube_controls'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Always hide video controls (controls).'),
-      '#default_value' => $settings['youtube_controls'],
-    );
-    $element['youtube_autohide'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Hide video controls after play begins (autohide).'),
-      '#default_value' => $settings['youtube_autohide'],
-    );
-    $element['youtube_iv_load_policy'] = array(
-      '#type' => 'checkbox',
-      '#title' => t('Hide video annotations by default (iv_load_policy).'),
-      '#default_value' => $settings['youtube_iv_load_policy'],
-    );
+function theme_youtube_video($variables) {
+  $id = $variables['video_id'];
+  $size = $variables['size'];
+  $width = $variables['width'];
+  $height = $variables['height'];
+  $autoplay = $variables['autoplay'];
+  $showinfo = $variables['showinfo'];
+  $controls = $variables['controls'];
+  $autohide = $variables['autohide'];
+  $iv_load_policy = $variables['iv_load_policy'];
+
+  // Get YouTube settings.
+  $suggest = \Drupal::config('youtube.settings')->get('youtube_suggest');
+  $privacy = \Drupal::config('youtube.settings')->get('youtube_privacy');
+  $modestbranding = \Drupal::config('youtube.settings')->get('youtube_modestbranding');
+  $theme = \Drupal::config('youtube.settings')->get('youtube_theme');
+  $color = \Drupal::config('youtube.settings')->get('youtube_color');
+  $enablejsapi = \Drupal::config('youtube.settings')->get('youtube_enablejsapi');
+  $wmode = \Drupal::config('youtube.settings')->get('youtube_wmode');
+  $dimensions = youtube_get_dimensions($size, $width, $height);
+
+  if ($enablejsapi) {
+    $playerid = \Drupal::config('youtube.settings')->get('youtube_playerid');
+    $playerid = empty($playerid) ? 'youtube-field-player' : $playerid;
+  }
+  else {
+    $playerid = 'youtube-field-player';
   }
 
-  if ($display['type'] == 'youtube_thumbnail') {
-    $element['image_style'] = array(
-      '#type' => 'select',
-      '#title' => t('Image style'),
-      '#options' => image_style_options(FALSE),
-      '#default_value' => $settings['image_style'],
-      '#empty_option' => t('None (original image)'),
-    );
+  $protocol = (isset($_SERVER['HTTPS'])) ? 'https' : 'http';
 
-    // Option to link the thumbnail to either it's original node or original youtube video.
-    $link_types = array(
-      'content' => t('Content'),
-      'youtube' => t('YouTube'),
-    );
-    $element['image_link'] = array(
-      '#title' => t('Link image to'),
-      '#type' => 'select',
-      '#default_value' => $settings['image_link'],
-      '#empty_option' => t('Nothing'),
-      '#options' => $link_types,
-    );
+  // Query string changes based on setings.
+  $query = array();
+  if (!$suggest) {
+    $query['rel'] = '0';
+  }
+  if ($modestbranding) {
+    $query['modestbranding'] = '1';
+  }
+  if ($theme) {
+    $query['theme'] = 'light';
+  }
+  if ($color) {
+    $query['color'] = 'white';
+  }
+  if ($enablejsapi) {
+    global $base_url;
+    $query['enablejsapi'] = '1';
+    $query['origin'] = parse_url($base_url, PHP_URL_HOST);
+  }
+  if ($wmode) {
+    $query['wmode'] = 'opaque';
+  }
+  if ($autoplay) {
+    $query['autoplay'] = '1';
+  }
+  if ($showinfo) {
+    $query['showinfo'] = '0';
+  }
+  if ($controls) {
+    $query['controls'] = '0';
   }
+  if ($autohide) {
+    $query['autohide'] = '1';
+  }
+  if ($iv_load_policy) {
+    $query['iv_load_policy'] = '3';
+  }
+
+  // Domain changes based on settings.
+  $domain = ($privacy) ? 'youtube-nocookie.com' : 'youtube.com';
+
+  $path = $protocol . '://www.' . $domain . '/embed/' . $id;
+  $src = url($path, array('query' => $query));
+
+  $output = '<iframe id="' . $playerid . '" width="' . $dimensions['width'] . '"
+    height="' . $dimensions['height'] . '" src="' . $src . '"
+    frameborder="0" allowfullscreen></iframe>';
 
-  return $element;
+  return $output;
 }
 
 /**
- * Implements hook_field_formatter_settings_summary().
+ * Theme function for thumbnails.
  */
-function youtube_field_formatter_settings_summary($field, $instance, $view_mode) {
-  $display = $instance['display'][$view_mode];
-  $settings = $display['settings'];
-
-  $parameters = array(
-    $settings['youtube_autoplay'],
-    $settings['youtube_showinfo'],
-    $settings['youtube_controls'],
-    $settings['youtube_autohide'],
-    $settings['youtube_iv_load_policy'],
-  );
-
-  // Summary for the video style.
-  if ($display['type'] == 'youtube_video') {
-    $video_sizes = youtube_size_options();
-    if (isset($video_sizes[$settings['youtube_size']])) {
-      $summary = t('YouTube video: @size', array('@size' => $video_sizes[$settings['youtube_size']]));
-    }
-    else {
-      $summary = t('YouTube video: 450px by 315px');
-    }
-    foreach ($parameters as $parameter) {
-      if ($parameter) {
-        $summary .= t(', custom parameters');
-        break;
-      }
+function theme_youtube_thumbnail($variables) {
+  $id = $variables['video_id'];
+  $style = $variables['image_style'];
+  $youtube_dir = \Drupal::config('youtube.settings')->get('youtube_thumb_dir');
+  $youtube_dir = empty($youtube_dir) ? 'youtube' : $youtube_dir;
+
+  $files = settings()->get('file_public_path', conf_path() . '/files');
+  $dest = $files . '/' . $youtube_dir . '/' . $id . '.png';
+
+  // Check to see if a thumbnail exists locally.
+  if (!file_exists($dest)) {
+    // Retrieve the image from YouTube.
+    if (!youtube_get_remote_image($id)) {
+      // Use the remote source if local copy fails.
+      $src = youtube_build_remote_image_path($id);
+      return theme('image', array('uri' => $src));
     }
-    return $summary;
+  }
+  if ($style) {
+    $uri = 'public://' . $youtube_dir . '/' . $id . '.png';
+    $image = theme('image_style', array('style_name' => $style, 'uri' => $uri));
+  }
+  else {
+    $path = $files . '/' . $youtube_dir . '/' . $id . '.png';
+    $image = theme('image', array('uri' => $path));
   }
 
-  // Summary for the thumbnail style.
-  if ($display['type'] == 'youtube_thumbnail') {
-    $image_styles = image_style_options(FALSE);
-    // Unset possible 'No defined styles' option.
-    unset($image_styles['']);
-    if (isset($image_styles[$settings['image_style']])) {
-      $summary = t('Image style: @style', array('@style' => $image_styles[$settings['image_style']]));
-    }
-    else {
-      $summary = t('Original image');
-    }
-    $link_types = array(
-      'content' => ' ' . t('linked to content'),
-      'youtube' => ' ' . t('linked to YouTube'),
-    );
-    // Display this setting only if image is linked.
-    if (isset($settings['image_link']) && isset($link_types[$settings['image_link']])) {
-      $summary .= $link_types[$settings['image_link']];
-    }
-    return $summary;
+  // Check if an url path is provided
+  if ($variables['image_link'] != NULL) {
+    $url_path = $variables['image_link']['path'];
+    $options = $variables['image_link']['options'];
+    $image = l($image, $url_path, $options);
   }
+
+  return $image;  
 }
 
 /**
- * Implements hook_field_formatter_view().
+ * Splits height and width when given size, as from youtube_size_options.
  */
-function youtube_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
-  $element = array();
-
-  switch ($display['type']) {
-    // This formatter outputs the youtube embed code.
-    case 'youtube_video':
-      foreach ($items as $delta => $item) {
-        $element[$delta] = array(
-          '#theme' => 'youtube_video',
-          '#video_id' => $item['video_id'],
-          '#size' => array_key_exists('youtube_size', $display['settings']) ? $display['settings']['youtube_size']: NULL,
-          '#width' => array_key_exists('youtube_width', $display['settings']) ? $display['settings']['youtube_width'] : NULL,
-          '#height' => array_key_exists('youtube_height', $display['settings']) ? $display['settings']['youtube_height'] : NULL,
-          '#autoplay' => array_key_exists('youtube_autoplay', $display['settings']) ? $display['settings']['youtube_autoplay'] : FALSE,
-          '#showinfo' => array_key_exists('youtube_showinfo', $display['settings']) ? $display['settings']['youtube_showinfo'] : FALSE,
-          '#controls' => array_key_exists('youtube_controls', $display['settings']) ? $display['settings']['youtube_controls'] : FALSE,
-          '#autohide' => array_key_exists('youtube_autohide', $display['settings']) ? $display['settings']['youtube_autohide'] : FALSE,
-          '#iv_load_policy' => array_key_exists('youtube_iv_load_policy', $display['settings']) ? $display['settings']['youtube_iv_load_policy'] : FALSE,
-        );
-      }
-      break;
-
-    // This formatter uses an imagecache preset to generate a thumbnail.
-    case 'youtube_thumbnail':
-
-      // Check if the formatter involves a link.
-      if (isset($display['settings']['image_link'])) {
-        if ($display['settings']['image_link'] == 'content') {
-          $uri = entity_uri($entity_type, $entity);
-          $uri['options']['html'] = TRUE;
-        }
-        elseif ($display['settings']['image_link'] == 'youtube') {
-          $link_youtube = TRUE;
-        }
-      }
-
-      foreach ($items as $delta => $item) {
-        // If the thumbnail is linked to it's youtube page, take the original url.
-        if (isset($link_youtube) && $link_youtube) {
-          $uri = array(
-            'path' => $item['input'],
-            'options' => array('html' => TRUE),
-          );
-        }
-
-        $element[$delta] = array(
-          '#theme' => 'youtube_thumbnail',
-          '#video_id' => $item['video_id'],
-          '#image_style' => $display['settings']['image_style'],
-          '#image_link' => isset($uri) ? $uri : '',
-        );
-      }
-      break;
+function youtube_get_dimensions($size = NULL, $width = NULL, $height = NULL) {
+  $dimensions = array();
+  if ($size == 'custom') {
+    $dimensions['width'] = (int) $width;
+    $dimensions['height'] = (int) $height;
+  }
+  else {
+    // Locate the 'x'.
+    $strpos = strpos($size, 'x');
+    // Width is the first dimension.
+    $dimensions['width'] = substr($size, 0, $strpos);
+    // Height is the second dimension.
+    $dimensions['height'] = substr($size, $strpos + 1, strlen($size));
   }
 
-  return $element;
+  return $dimensions;
 }
 
 /**
- * Implements hook_field_widget_info().
+ * Retrieve youtube thumbnail image via YouTube API.
+ *
+ * TODO add error messaging if something goes wrong, and return FALSE.
  */
-function youtube_field_widget_info() {
-  return array(
-    'youtube' => array(
-      'label' => t('YouTube'),
-      'field types' => array('youtube'),
-    ),
+function youtube_get_remote_image($id = NULL) {
+  $path = 'http://gdata.youtube.com/feeds/api/videos/' . $id;
+  $query = array(
+    'v' => '2', 
+    'alt' => 'jsonc'
   );
+  // Get thumbnail image url.
+  $url = url($path, array('query' => $query));
+  $request = Drupal::httpClient()->get($url);
+  try {
+    $response = $request->send();
+    $data = $response->getBody(TRUE);
+  }
+  catch (RequestException $e) {
+    watchdog_exception('youtube', $e);
+  }
+  $data = json_decode($data);
+  $src = $data->data->thumbnail->hqDefault;
+  // Get thumbnail image.
+  $image_request = Drupal::httpClient()->get($src);
+  try {
+    $response = $image_request->send();
+    $data = $response->getBody(TRUE);
+  }
+  catch (RequestException $e) {
+    watchdog_exception('youtube', $e);
+  }
+  $files = settings()->get('file_public_path', conf_path() . '/files');
+  $youtube_dir = \Drupal::config('youtube.settings')->get('youtube_thumb_dir');
+  $youtube_dir = empty($youtube_dir) ? 'youtube' : $youtube_dir;
+  $youtube_path = $files . '/' . $youtube_dir;
+
+  if (!file_prepare_directory($youtube_path, FILE_CREATE_DIRECTORY) && !mkdir($youtube_path, 0775, TRUE)) {
+    watchdog('youtube', 'Failed to create YouTube thumbnail directory: %dir', array('%dir' => $youtube_path), WATCHDOG_ERROR);
+  }
+  // Save the file.
+  $dest = $files . '/' . $youtube_dir . '/' . $id . '.png';
+  file_put_contents($dest, $data);
+  return TRUE;
 }
 
 /**
- * Implements hook_field_widget_form().
+ * Get images by building correctly formed URL - kinda hackey.
  */
-function youtube_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) {
-  $value = isset($items[$delta]['input']) ? $items[$delta]['input'] : '';
-
-  $element += array(
-    '#type' => 'textfield',
-    '#default_value' => $value,
-    '#size' => 60,
-    '#maxlength' => 1024,
-    '#element_validate' => array('youtube_input_validate'),
-    //'#value_callback' => 'youtube_widget_value',
-  );
-
-  // Add our own description if one is not provided by the UI.
-  if ($element['#description'] == '') {
-    $element['#description'] = t('Enter the YouTube URL. Valid URL formats
-      include: http://www.youtube.com/watch?v=1SqBdS0XkV4 and
-      http://youtu.be/1SqBdS0XkV4');
-  }
-  $return = array('input' => $element);
-
-  if (isset($items[$delta]['video_id'])) {
-    $video_id_element = array(
-      '#markup' => '<div class="youtube-video-id">' . t('YouTube video ID: ') . $items[$delta]['video_id'] . '</div>',
-    );
-    $return['video_id'] = $video_id_element;
+function youtube_build_remote_image_path($id = NULL) {
+  if (!$id) {
+    return;
   }
+  // Default image thumbnail.
+  $default = 'http://img.youtube.com/vi/' . $id . '/default.jpg';
 
-  return $return;
+  return url($default);
 }
 
 /**
- * Validation for the youtube field itself.
+ * Implements hook_feeds_processor_targets_alter().
+ *
+ * Adds a target option for YouTube fields to Feeds mapping options.
+ *
+ * @param &$targets
+ *   Array containing the targets to be offered to the user. Add to this array
+ *   to expose additional options. Remove from this array to suppress options.
+ *   Remove with caution.
+ * @param $entity_type
+ *   The entity type of the target, for instance a 'node' entity.
+ * @param $bundle_name
+ *   The bundle name for which to alter targets.
  */
-function youtube_input_validate($element, &$form_state, $form) {
-  $input = $element['#value'];
-
-  $video_id = youtube_get_video_id($input);
+function youtube_feeds_processor_targets_alter(&$targets, $entity_type, $bundle_name) {
+  foreach (Field::fieldInfo()->getBundleInstances($entity_type, $bundle_name) as $name => $instance) {
+    $info = Field::fieldInfo()->getField($entity_type,$name);
+
+    if (in_array($info['type'], array('youtube'))) {
+      $targets[$name] = array(
+        'name' => check_plain($instance['label']),
+        'callback' => 'youtube_set_target',
+        'description' => t('The @label field of the node.', array('@label' => $instance['label'])),
+      );
+    }
+  }
+}
 
+/**
+ * Callback to set the Feeds target for a YouTube field.
+ *
+ * @param $source
+ *   Field mapper source settings.
+ * @param $entity
+ *   An entity object, for instance a node object.
+ * @param $target
+ *   A string identifying the target on the node.
+ * @param $value
+ *   The value to populate the target with.
+ */
+function youtube_set_target($source, $entity, $target, $value, $mapping) {
+  $video_id = youtube_get_video_id($value);
   if ($video_id) {
-    $video_id_element = array(
-      '#parents' => $element['#parents'],
+    $entity->{$target}[$entity->language][0] = array(
+      'input' => $value,
+      'video_id' => $video_id,
     );
-    array_pop($video_id_element['#parents']);
-    $video_id_element['#parents'][] = 'video_id';
-    form_set_value($video_id_element, $video_id, $form_state);
   }
 }
 
 /**
- * Implements hook_field_widget_error().
+ * Implements hook_token_info_alter().
+ *
+ * Alters and adds tokens for each youtube field.
+ *
+ * @param $data
+ *   The associative array of token definitions from hook_token_info().
  */
-function youtube_field_widget_error($element, $error, $form, &$form_state) {
-  switch ($error['error']) {
-    case 'youtube_invalid':
-      form_error($element, $error['message']);
-      break;
+function youtube_token_info_alter(&$data) {
+  // Get all youtube fields. Gather entity_type and bundle information.
+  $fields = field_info_fields();
+  $youtube_fields = array();
+  foreach ($fields as $name => $field) {
+    if ($field['type'] == 'youtube') {
+      foreach ($field['bundles'] as $type => $entity_type) {
+        foreach ($entity_type as $bundle) {
+          $youtube_fields[] = array(
+            'entity_type' => $type,
+            'bundle' => $bundle,
+            'field_name' => $name,
+          );
+        }
+      }
+    }
+  }
+
+  foreach ($youtube_fields as $field) {
+    $field_info = Field::fieldInfo()->getInstance($field['entity_type'], $field['bundle'], $field['field_name']);
+    $field_label = $field_info['label'];
+
+    // Modify the default field token.
+    $data['tokens'][$field['entity_type']][$field['field_name']] = array(
+      'name' => $field_label . t(": Default"),
+      'description' => t("The YouTube video field value's Default (or Token if exists) view mode output."),
+    );
+
+    // Add two new tokens.
+    $data['tokens'][$field['entity_type']][$field['field_name'] . '__youtube_video_url'] = array(
+      'name' => $field_label . t(": Video URL"),
+      'description' => t("The YouTube video field value's youtube.com URL."),
+    );
+    $data['tokens'][$field['entity_type']][$field['field_name'] . '__youtube_image_url'] = array(
+      'name' => $field_label . t(": Image URL"),
+      'description' => t("The YouTube video field value's local image URL."),
+    );
   }
 }
 
 /**
- * Implements of hook_theme().
+ * Implements hook_tokens().
+ *
+ * Provide replacement values for placeholder tokens.
+ *
+ * Replaces youtube_video_url and youtube_image_url tokens.
+ *
+ * @param $type
+ *   The machine-readable name of the type (group) of token being replaced, such
+ *   as 'node', 'user', or another type defined by a hook_token_info()
+ *   implementation.
+ * @param $tokens
+ *   An array of tokens to be replaced. The keys are the machine-readable token
+ *   names, and the values are the raw [type:token] strings that appeared in the
+ *   original text.
+ * @param $data
+ *   (optional) An associative array of data objects to be used when generating
+ *   replacement values, as supplied in the $data parameter to token_replace().
+ * @param $options
+ *   (optional) An associative array of options for token replacement; see
+ *   token_replace() for possible values.
+ *
+ * @return
+ *   An associative array of replacement values, keyed by the raw [type:token]
+ *   strings from the original text.
+ *
+ * @see youtube_tokens_info_alter()
  */
-function youtube_theme($existing, $type, $theme, $path) {
-  return array(
-    'youtube_thumbnail' => array(
-      'variables' => array(
-        'video_id' => NULL,
-        'image_style' => NULL,
-        'image_link' => NULL
-      ),
-      'file' => 'youtube.theme.inc',
-    ),
-    'youtube_video' => array(
-      'variables' => array(
-        'video_id' => NULL,
-        'size' => NULL,
-        'width' => NULL,
-        'height' => NULL,
-        'autoplay' => FALSE,
-        'showinfo' => FALSE,
-        'controls' => FALSE,
-        'autohide' => FALSE,
-        'iv_load_policy' => FALSE,
-      ),
-      'file' => 'youtube.theme.inc',
-    ),
-  );
+function youtube_tokens($type, $tokens, array $data = array(), array $options = array()) {
+  $url_options = array('absolute' => TRUE);
+  if (isset($options['language'])) {
+    $url_options['language'] = $options['language'];
+    $language_code = $options['language']->language;
+  }
+  else {
+    $language_code = NULL;
+  }
+  $sanitize = !empty($options['sanitize']);
+
+  $replacements = array();
+
+  if ($type == 'node' && !empty($data['node'])) {
+    $node = $data['node'];
+
+    foreach ($tokens as $name => $original) {
+      if (!strpos($name, '__youtube_')) {
+        // This isn't a youtube token!
+        return;
+      }
+
+      $token_pieces = explode('__', $name);
+      if (count($token_pieces) != 2) {
+        return;
+      }
+
+      $field_name = $token_pieces[0];
+      $token_name = $token_pieces[1];
+
+      switch ($token_name) {
+        case 'youtube_video_url':
+          $field = $node->$field_name;
+          $video_id = $field[LANGUAGE_NONE][0]['video_id'];
+          $replacements[$original] = 'http://www.youtube.com/watch?v=' . $video_id;
+          break;
+
+        case 'youtube_image_url':
+          global $base_url;
+          global $base_path;
+          $field = $node->$field_name;
+          $video_id = $field[LANGUAGE_NONE][0]['video_id'];
+          $file_path = settings()->get('file_public_path', conf_path() . '/files') . '/';
+          $thumb_dir = \Drupal::config('youtube.settings')->get('youtube_thumb_dir');
+          $thumb_dir = empty($thumb_dir) ? 'youtube' : $thumb_dir;
+          $file_path .= $thumb_dir;
+          $file_path .= '/' . $video_id . '.png';
+          $full_path = $base_url . $base_path . $file_path;
+          if (!file_exists($full_path)) {
+            youtube_get_remote_image($video_id);
+          }
+          $replacements[$original] = $full_path;
+          break;
+      }
+    }
+  }
+
+  return $replacements;
 }
diff --git a/youtube.routing.yml b/youtube.routing.yml
new file mode 100644
index 0000000..ebf01e7
--- /dev/null
+++ b/youtube.routing.yml
@@ -0,0 +1,6 @@
+youtube_settings:
+  path: '/admin/config/media/youtube'
+  defaults:
+    _form: '\Drupal\youtube\Form\YoutubeSettingsForm'
+  requirements:
+    _permission: 'administer youtube'
\ No newline at end of file
diff --git a/youtube.theme.inc b/youtube.theme.inc
deleted file mode 100644
index 6648908..0000000
--- a/youtube.theme.inc
+++ /dev/null
@@ -1,138 +0,0 @@
-<?php
-/**
- * @file
- * Theme functions for the YouTube field module.
- */
-
-/**
- * Theme function for videos.
- */
-function theme_youtube_video($variables) {
-  $id = $variables['video_id'];
-
-  // Get field display settings.
-  $size = $variables['size'];
-  $width = array_key_exists('width', $variables)? $variables['width'] : NULL;
-  $height = array_key_exists('height', $variables)? $variables['height'] : NULL;
-  $autoplay = array_key_exists('autoplay', $variables)? $variables['autoplay'] : FALSE;
-  $showinfo = array_key_exists('showinfo', $variables)? $variables['showinfo'] : FALSE;
-  $controls = array_key_exists('controls', $variables)? $variables['controls'] : FALSE;
-  $autohide = array_key_exists('autohide', $variables)? $variables['autohide'] : FALSE;
-  $iv_load_policy = array_key_exists('iv_load_policy', $variables)? $variables['iv_load_policy'] : FALSE;
-
-  // Get YouTube settings.
-  $suggest = variable_get('youtube_suggest', TRUE);
-  $privacy = variable_get('youtube_privacy', FALSE);
-  $modestbranding = variable_get('youtube_modestbranding', FALSE);
-  $theme = variable_get('youtube_theme', FALSE);
-  $color = variable_get('youtube_color', FALSE);
-  $enablejsapi = variable_get('youtube_enablejsapi', FALSE);
-  $wmode = variable_get('youtube_wmode', TRUE);
-  $privacy = variable_get('youtube_privacy', FALSE);
-  $dimensions = youtube_get_dimensions($size, $width, $height);
-
-  if ($enablejsapi) {
-    $playerid = variable_get('youtube_playerid', 'youtube-field-player');
-  }
-  else {
-    $playerid = 'youtube-field-player';
-  }
-
-  // Protocol changes based on current page TODO.
-  $protocol = (isset($_SERVER['HTTPS'])) ? 'https' : 'http';
-
-  // Query string changes based on setings.
-  $query = array();
-  if (!$suggest) {
-    $query['rel'] = '0';
-  }
-  if ($modestbranding) {
-    $query['modestbranding'] = '1';
-  }
-  if ($theme) {
-    $query['theme'] = 'light';
-  }
-  if ($color) {
-    $query['color'] = 'white';
-  }
-  if ($enablejsapi) {
-    global $base_url;
-    $query['enablejsapi'] = '1';
-    $query['origin'] = parse_url($base_url, PHP_URL_HOST);
-  }
-  if ($wmode) {
-    $query['wmode'] = 'opaque';
-  }
-  if ($autoplay) {
-    $query['autoplay'] = '1';
-  }
-  if ($showinfo) {
-    $query['showinfo'] = '0';
-  }
-  if ($controls) {
-    $query['controls'] = '0';
-  }
-  if ($autohide) {
-    $query['autohide'] = '1';
-  }
-  if ($iv_load_policy) {
-    $query['iv_load_policy'] = '3';
-  }
-
-  // Domain changes based on settings.
-  $domain = ($privacy) ? 'youtube-nocookie.com' : 'youtube.com';
-
-  $path = $protocol . '://www.' . $domain . '/embed/' . $id;
-  $src = url($path, array('query' => $query));
-
-  $output = '<iframe id="' . $playerid . '" width="' . $dimensions['width'] . '"
-    height="' . $dimensions['height'] . '" src="' . $src . '"
-    frameborder="0" allowfullscreen></iframe>';
-
-  return $output;
-}
-
-
-/**
- * Theme function for thumbnails.
- */
-function theme_youtube_thumbnail($variables) {
-  $id = $variables['video_id'];
-  $style = $variables['image_style'];
-
-  // Get YouTube settings - TODO is this needed?
-  $size = variable_get('youtube_size', '420x315');
-  $dimensions = youtube_get_dimensions($size);
-
-  $files = variable_get('file_public_path', conf_path() . '/files');
-  $youtube = variable_get('youtube_thumb_dir', 'youtube');
-  $dest = $files . '/' . $youtube . '/' . $id . '.png';
-
-  // Check to see if a thumbnail exists locally.
-  if (!file_exists($dest)) {
-    // Retrieve the image from YouTube.
-    if (!youtube_get_remote_image($id)) {
-      // Use the remote source if local copy fails.
-      $src = youtube_build_remote_image_path($id);
-      return theme('image', array('path' => $src));
-    }
-  }
-
-  if ($style) {
-    $uri = 'public://' . $youtube . '/' . $id . '.png';
-    $image = theme('image_style', array('style_name' => $style, 'path' => $uri));
-  }
-  else {
-    $path = $files . '/' . $youtube . '/' . $id . '.png';
-    $image = theme('image', array('path' => $path));
-  }
-
-  // Check if an url path is provided
-  if ($variables['image_link'] != NULL) {
-    $url_path = $variables['image_link']['path'];
-    $options = $variables['image_link']['options'];
-    $image = l($image, $url_path, $options);
-  }
-
-  return $image;
-}
