diff --git a/lib/Drupal/media_entity/Entity/Media.php b/lib/Drupal/media_entity/Entity/Media.php
new file mode 100644
index 0000000..aa3916a
--- /dev/null
+++ b/lib/Drupal/media_entity/Entity/Media.php
@@ -0,0 +1,304 @@
+<?php
+
+/**
+ * @file
+ * Definition of Drupal\media_entity\Entity\Media.
+ */
+
+namespace Drupal\media_entity\Entity;
+
+use Drupal\Core\Entity\ContentEntityBase;
+use Drupal\Core\Entity\EntityStorageControllerInterface;
+use Drupal\media_entity\MediaInterface;
+
+/**
+ * Defines the media entity class.
+ *
+ * @EntityType(
+ *   id = "media",
+ *   label = @Translation("Media"),
+ *   bundle_label = @Translation("Media bundle"),
+ *   module = "media_entity",
+ *   controllers = {
+ *     "storage" = "Drupal\media_entity\MediaStorageController",
+ *     "render" = "Drupal\media_entity\MediaRenderController",
+ *     "access" = "Drupal\media_entity\MediaAccessController",
+ *     "form" = {
+ *       "default" = "Drupal\media_entity\MediaFormController",
+ *       "delete" = "Drupal\media_entity\Form\MediaDeleteForm",
+ *       "edit" = "Drupal\media_entity\MediaFormController"
+ *     },
+ *     "translation" = "Drupal\media_entity\MediaTranslationController"
+ *   },
+ *   base_table = "media",
+ *   data_table = "media_field_data",
+ *   revision_table = "media_revision",
+ *   revision_data_table = "media_field_revision",
+ *   uri_callback = "media_uri",
+ *   fieldable = TRUE,
+ *   translatable = TRUE,
+ *   render_cache = FALSE,
+ *   entity_keys = {
+ *     "id" = "mid",
+ *     "bundle" = "bundle",
+ *     "label" = "name",
+ *     "uuid" = "uuid"
+ *   },
+ *   bundle_keys = {
+ *     "bundle" = "bundle"
+ *   },
+ *   route_base_path = "admin/structure/media/manage/{bundle}",
+ *   permission_granularity = "bundle",
+ *   links = {
+ *     "canonical" = "/media/{media}",
+ *     "edit-form" = "/media/{media}/edit",
+ *     "version-history" = "/media/{media}/revisions"
+ *   }
+ * )
+ */
+class Media extends ContentEntityBase implements MediaInterface {
+
+  /**
+   * Value that represents the media being published.
+   */
+  const PUBLISHED = 1;
+
+  /**
+   * Value that represents the media being unpublished.
+   */
+  const NOT_PUBLISHED = 0;
+
+  /**
+   * Implements Drupal\Core\Entity\EntityInterface::id().
+   */
+  public function id() {
+    return $this->get('mid')->value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageControllerInterface $storage_controller) {
+    parent::preSave($storage_controller);
+
+    // Before saving the node, set changed and revision times.
+    $this->changed->value = REQUEST_TIME;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getBundle() {
+    return $this->bundle();
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getName() {
+    return $this->get('name')->value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setName($title) {
+    $this->set('name', $title);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCreatedTime() {
+    return $this->get('created')->value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setCreatedTime($timestamp) {
+    $this->set('created', $timestamp);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getChangedTime() {
+    return $this->get('changed')->value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function isPublished() {
+    return (bool) $this->get('status')->value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setPublished($published) {
+    $this->set('status', $published ? Media::PUBLISHED : Media::NOT_PUBLISHED);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPublisher() {
+    return $this->get('uid')->entity;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getPublisherId() {
+    return $this->get('uid')->target_id;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setPublisherId($uid) {
+    $this->set('uid', $uid);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getType() {
+    return $this->get('type')->value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setType($type) {
+    $this->set('type', $type);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getResourceId() {
+    return $this->get('resource_id')->value;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setResourceId($id) {
+    $this->set('resource_id', $id);
+    return $this;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function baseFieldDefinitions($entity_type) {
+    $properties['mid'] = array(
+      'label' => t('Media ID'),
+      'description' => t('The media ID.'),
+      'type' => 'integer_field',
+      'read-only' => TRUE,
+    );
+    $properties['uuid'] = array(
+      'label' => t('UUID'),
+      'description' => t('The media UUID.'),
+      'type' => 'uuid_field',
+      'read-only' => TRUE,
+    );
+    $properties['bundle'] = array(
+      'label' => t('Bundle'),
+      'description' => t('The media bundle.'),
+      'type' => 'string_field',
+      'read-only' => TRUE,
+    );
+    $properties['langcode'] = array(
+      'label' => t('Language code'),
+      'description' => t('The media language code.'),
+      'type' => 'language_field',
+    );
+    $properties['name'] = array(
+      'label' => t('Name'),
+      'description' => t('The name of this node.'),
+      'type' => 'string_field',
+      'required' => TRUE,
+      'settings' => array(
+        'default_value' => '',
+      ),
+      'property_constraints' => array(
+        'value' => array('Length' => array('max' => 255)),
+      ),
+    );
+    $properties['uid'] = array(
+      'label' => t('Publisher ID'),
+      'description' => t('The user ID of the media publisher.'),
+      'type' => 'entity_reference_field',
+      'settings' => array(
+        'target_type' => 'user',
+        'default_value' => 0,
+      ),
+    );
+    $properties['status'] = array(
+      'label' => t('Publishing status'),
+      'description' => t('A boolean indicating whether the media is published.'),
+      'type' => 'boolean_field',
+    );
+    $properties['created'] = array(
+      'label' => t('Created'),
+      'description' => t('The time that the media was created.'),
+      'type' => 'integer_field',
+    );
+    $properties['changed'] = array(
+      'label' => t('Changed'),
+      'description' => t('The time that the media was last edited.'),
+      'type' => 'integer_field',
+      'property_constraints' => array(
+        'value' => array('EntityChanged' => array()),
+      ),
+    );
+    $properties['type'] = array(
+      'label' => t('Type'),
+      'description' => t('The type of this media.'),
+      'required' => TRUE,
+      'type' => 'string_field',
+      'property_constraints' => array(
+        'value' => array('Length' => array('max' => 255)),
+      ),
+    );
+    $properties['resource_id'] = array(
+      'label' => t('Resource ID'),
+      'description' => t('The unique identifier of media resource that is associated with this media.'),
+      'required' => TRUE,
+      'type' => 'string_field',
+      'property_constraints' => array(
+        'value' => array('Length' => array('max' => 255)),
+      ),
+    );
+    $properties['revision_timestamp'] = array(
+      'label' => t('Revision timestamp'),
+      'description' => t('The time that the current revision was created.'),
+      'type' => 'integer_field',
+      'queryable' => FALSE,
+    );
+    $properties['revision_uid'] = array(
+      'label' => t('Revision publisher ID'),
+      'description' => t('The user ID of the publisher of the current revision.'),
+      'type' => 'entity_reference_field',
+      'settings' => array('target_type' => 'user'),
+      'queryable' => FALSE,
+    );
+    $properties['log'] = array(
+      'label' => t('Log'),
+      'description' => t('The log entry explaining the changes in this version.'),
+      'type' => 'string_field',
+    );
+    return $properties;
+  }
+
+}
diff --git a/lib/Drupal/media_entity/MediaInterface.php b/lib/Drupal/media_entity/MediaInterface.php
new file mode 100644
index 0000000..163b335
--- /dev/null
+++ b/lib/Drupal/media_entity/MediaInterface.php
@@ -0,0 +1,151 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\media_entity\MediaInterface.
+ */
+
+namespace Drupal\media_entity;
+
+use Drupal\Core\Entity\EntityChangedInterface;
+use Drupal\Core\Entity\ContentEntityInterface;
+use Drupal\user\UserInterface;
+
+/**
+ * Provides an interface defining a media entity.
+ */
+interface MediaInterface extends ContentEntityInterface, EntityChangedInterface {
+
+  /**
+   * Returns the media bundle.
+   *
+   * @return string
+   *   The media type.
+   */
+  public function getBundle();
+
+  /**
+   *
+   * Returns the media name.
+   *
+   * @return string
+   *   Name of the media.
+   */
+  public function getName();
+
+  /**
+   * Sets the media name.
+   *
+   * @param string $name
+   *   The media name.
+   *
+   * @return \Drupal\media_entity\MediaInterface
+   *   The called media entity.
+   */
+  public function setName($title);
+
+  /**
+   * Returns the media creation timestamp.
+   *
+   * @return int
+   *   Creation timestamp of the media.
+   */
+  public function getCreatedTime();
+
+  /**
+   * Sets the media creation timestamp.
+   *
+   * @param int $timestamp
+   *   The media creation timestamp.
+   *
+   * @return \Drupal\media_entity\MediaInterface
+   *   The called media entity.
+   */
+  public function setCreatedTime($timestamp);
+
+  /**
+   * Returns the media publisher user entity.
+   *
+   * @return \Drupal\user\UserInterface
+   *   The author user entity.
+   */
+  public function getPublisher();
+
+  /**
+   * Returns the media publisher user ID.
+   *
+   * @return int
+   *   The author user ID.
+   */
+  public function getPublisherId();
+
+  /**
+   * Sets the media publisher user ID.
+   *
+   * @param int $uid
+   *   The author user id.
+   *
+   * @return \Drupal\media_entity\MediaInterface
+   *   The called media entity.
+   */
+  public function setPublisherId($uid);
+
+  /**
+   * Returns the media published status indicator.
+   *
+   * Unpublished media are only visible to their authors and to administrators.
+   *
+   * @return bool
+   *   TRUE if the media is published.
+   */
+  public function isPublished();
+
+  /**
+   * Sets the published status of a media.
+   *
+   * @param bool $published
+   *   TRUE to set this media to published, FALSE to set it to unpublished.
+   *
+   * @return \Drupal\media_entity\MediaInterface
+   *   The called media entity.
+   */
+  public function setPublished($published);
+
+  /**
+   * Returns the media type.
+   *
+   * @return string
+   *   The media type.
+   */
+  public function getType();
+
+  /**
+   * Sets the media type.
+   *
+   * @param string $type
+   *   The media type.
+   *
+   * @return \Drupal\media_entity\MediaInterface
+   *   The called media entity.
+   */
+  public function setType($type);
+
+  /**
+   * Returns the media resource ID.
+   *
+   * @return string
+   *   The media resource ID.
+   */
+  public function getResourceId();
+
+  /**
+   * Sets the media resource ID..
+   *
+   * @param string id
+   *   The media resource ID.
+   *
+   * @return \Drupal\media_entity\MediaInterface
+   *   The called media entity.
+   */
+  public function setResourceId($id);
+}
diff --git a/media_entity.install b/media_entity.install
new file mode 100644
index 0000000..61d41f5
--- /dev/null
+++ b/media_entity.install
@@ -0,0 +1,315 @@
+<?php
+
+/**
+ * @file
+ * Install, update, uninstall and other related hooks.
+ */
+
+/**
+ * Implements hook_schema().
+ */
+function media_entity_schema() {
+  $schema = array();
+
+  // Media base table.
+  $schema['media'] = array(
+    'description' => 'The base table for media.',
+    'fields' => array(
+      'mid' => array(
+        'description' => 'Media ID.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'uuid' => array(
+        'description' => 'Unique Key: Universally unique identifier for this entity.',
+        'type' => 'varchar',
+        'length' => 128,
+        'not null' => FALSE,
+      ),
+      'bundle' => array(
+        'description' => 'The bundle of this media.',
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'vid' => array(
+        'description' => 'The current {media_revision}.vid version identifier.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => FALSE,
+        'default' => NULL,
+      ),
+    ),
+    'indexes' => array(
+      'media_bundle' => array(array('bundle', 4)),
+    ),
+    'unique keys' => array(
+      'uuid' => array('uuid'),
+      'vid' => array('vid'),
+    ),
+    'primary key' => array('mid'),
+  );
+
+  // Media revision table.
+  $schema['media_revision'] = array(
+    'description' => 'Stores information about each saved version of a {media}.',
+    'fields' => array(
+      'mid' => array(
+        'description' => 'The {media} this version belongs to.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'vid' => array(
+        'description' => 'The primary identifier for this version.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'revision_uid' => array(
+        'description' => 'The {users}.uid that created this version.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'log' => array(
+        'description' => 'The log entry explaining the changes in this version.',
+        'type' => 'text',
+        'not null' => FALSE,
+        'size' => 'big',
+      ),
+      'revision_timestamp' => array(
+        'description' => 'The Unix timestamp when the version was created.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'langcode' => array(
+        'description' => 'The {language}.langcode of this version.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+    ),
+    'indexes' => array(
+      'mid' => array('mid'),
+      'revision_uid' => array('revision_uid'),
+      'media_langcode' => array('langcode'),
+    ),
+    'foreign keys' => array(
+      'versioned_media' => array(
+        'table' => 'media',
+        'columns' => array('mid' => 'mid'),
+      ),
+      'version_author' => array(
+        'table' => 'users',
+        'columns' => array('revision_uid' => 'uid'),
+      ),
+    ),
+    'primary key' => array('vid'),
+  );
+
+  // Media base fields storage.
+  $schema['media_field_data'] = array(
+    'description' => 'Base table for media properties.',
+    'fields' => array(
+      'mid' => array(
+        'description' => 'The primary identifier for a media.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'vid' => array(
+        'description' => 'The current {media_revision}.vid version identifier.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'bundle' => array(
+        'description' => 'The {media_type}.bundle of this media.',
+        'type' => 'varchar',
+        'length' => 32,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'langcode' => array(
+        'description' => 'The {language}.langcode of these media property values.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'default_langcode' => array(
+        'description' => 'Indicates that this row holds data for original language of this media.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'name' => array(
+        'description' => 'The name of this media.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'uid' => array(
+        'description' => 'The {users}.uid that owns this media; initially, this is the user that published it.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'status' => array(
+        'description' => 'Boolean indicating whether the media translation is published (visible to non-administrators).',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'resource_id' => array(
+        'description' => 'Base ID of a media resource, that is associated with the media entity. Understood by the appropriate media plugin.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'type' => array(
+        'description' => 'Type of the media entity. Provides information about the plugin that should be used with the media entity.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'created' => array(
+        'description' => 'The Unix timestamp when the media translation was created.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'changed' => array(
+        'description' => 'The Unix timestamp when the media translation was most recently saved.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array(
+      'media_changed' => array('changed'),
+      'media_created' => array('created'),
+      'media_default_langcode' => array('default_langcode'),
+      'media_langcode' => array('langcode'),
+      'media_type' => array(array('type', 4)),
+      'mid' => array('mid'),
+    ),
+    'foreign keys' => array(
+      'media_base' => array(
+        'table' => 'media',
+        'columns' => array('mid' => 'mid'),
+      ),
+      'media_publisher' => array(
+        'table' => 'users',
+        'columns' => array('uid' => 'uid'),
+      ),
+    ),
+    'primary key' => array('mid', 'langcode'),
+  );
+
+  // Revision table for media base fields..
+  $schema['media_field_revision'] = array(
+    'description' => 'Revision table for media base fields.',
+    'fields' => array(
+      'mid' => array(
+        'description' => 'The primary identifier for a media.',
+        'type' => 'serial',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'vid' => array(
+        'description' => 'The current {media_revision}.vid version identifier.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+      ),
+      'langcode' => array(
+        'description' => 'The {language}.langcode of these media property values.',
+        'type' => 'varchar',
+        'length' => 12,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'default_langcode' => array(
+        'description' => 'Indicates that this row holds data for original language of this media.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'name' => array(
+        'description' => 'The name of this media.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'uid' => array(
+        'description' => 'The {users}.uid that owns this media; initially, this is the user that published it.',
+        'type' => 'int',
+        'unsigned' => TRUE,
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'status' => array(
+        'description' => 'Boolean indicating whether the media translation is published (visible to non-administrators).',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 1,
+      ),
+      'resource_id' => array(
+        'description' => 'Base ID of a media resource, that is associated with the media entity. Understood by the appropriate media plugin.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'type' => array(
+        'description' => 'Type of the media entity. Provides information about the plugin that should be used with the media entity.',
+        'type' => 'varchar',
+        'length' => 255,
+        'not null' => TRUE,
+        'default' => '',
+      ),
+      'created' => array(
+        'description' => 'The Unix timestamp when the media translation was created.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+      'changed' => array(
+        'description' => 'The Unix timestamp when the media translation was most recently saved.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+      ),
+    ),
+    'indexes' => array(
+      'uid' => array('uid'),
+      'media_default_langcode' => array('default_langcode'),
+      'media_langcode' => array('langcode'),
+    ),
+    'foreign keys' => array(
+      'versioned_media' => array(
+        'table' => 'media',
+        'columns' => array('mid' => 'mid'),
+      ),
+      'media_publisher' => array(
+        'table' => 'users',
+        'columns' => array('uid' => 'uid'),
+      ),
+    ),
+    'primary key' => array('vid', 'langcode'),
+  );
+
+  return $schema;
+}
diff --git a/media_entity.module b/media_entity.module
new file mode 100644
index 0000000..b3d9bbc
--- /dev/null
+++ b/media_entity.module
@@ -0,0 +1 @@
+<?php
