diff --git a/config/schema/media_entity.schema.yml b/config/schema/media_entity.schema.yml
index 1c1f720..2d88660 100644
--- a/config/schema/media_entity.schema.yml
+++ b/config/schema/media_entity.schema.yml
@@ -67,3 +67,13 @@ field.formatter.settings.media_thumbnail:
     image_style:
       type: string
       label: 'Image style'
+
+media_entity.bundle.field_aware_type:
+  type: mapping
+  mapping:
+    source_field:
+      type: string
+      label: 'Source field'
+
+media_entity.bundle.type.generic:
+  type: media_entity.bundle.field_aware_type
diff --git a/src/Annotation/MediaType.php b/src/Annotation/MediaType.php
index 65a3d70..0d43633 100644
--- a/src/Annotation/MediaType.php
+++ b/src/Annotation/MediaType.php
@@ -40,4 +40,11 @@ class MediaType extends Plugin {
    */
   public $description = '';
 
+  /**
+   * The field types that can be used as a source field for this type.
+   *
+   * @var string[]
+   */
+  public $allowed_field_types = [];
+
 }
diff --git a/src/Entity/MediaBundle.php b/src/Entity/MediaBundle.php
index 8833f82..2101771 100644
--- a/src/Entity/MediaBundle.php
+++ b/src/Entity/MediaBundle.php
@@ -2,12 +2,15 @@
 
 namespace Drupal\media_entity\Entity;
 
-use Drupal\Core\Entity\EntityDescriptionInterface;
 use Drupal\Core\Config\Entity\ConfigEntityBundleBase;
+use Drupal\Core\Entity\EntityDescriptionInterface;
+use Drupal\Core\Entity\EntityStorageInterface;
 use Drupal\Core\Entity\EntityWithPluginCollectionInterface;
 use Drupal\Core\Plugin\DefaultSingleLazyPluginCollection;
+use Drupal\field\FieldStorageConfigInterface;
 use Drupal\media_entity\MediaBundleInterface;
 use Drupal\media_entity\MediaInterface;
+use Drupal\media_entity\SourceFieldInterface;
 
 /**
  * Defines the Media bundle configuration entity.
@@ -121,7 +124,7 @@ class MediaBundle extends ConfigEntityBundleBase implements MediaBundleInterface
   /**
    * Default status of this media bundle.
    *
-   * @var array
+   * @var bool
    */
   public $status = TRUE;
 
@@ -241,4 +244,57 @@ class MediaBundle extends ConfigEntityBundleBase implements MediaBundleInterface
     $this->new_revision = $new_revision;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function preSave(EntityStorageInterface $storage) {
+    parent::preSave($storage);
+
+    $type_plugin = $this->getType();
+    if ($type_plugin instanceof SourceFieldInterface) {
+      $storage = $type_plugin->getSourceField($this)->getFieldStorageDefinition();
+      if ($storage instanceof FieldStorageConfigInterface && $storage->isNew()) {
+        $storage->save();
+      }
+      $configuration = $type_plugin->getConfiguration();
+      $configuration['source_field'] = $storage->getName();
+      $this->setTypeConfiguration($configuration);
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function postSave(EntityStorageInterface $storage, $update = TRUE) {
+    parent::postSave($storage, $update);
+
+    $type_plugin = $this->getType();
+    if ($type_plugin instanceof SourceFieldInterface) {
+      $field = $type_plugin->getSourceField($this);
+
+      if ($field->isNew()) {
+        $entity_type = $field->getTargetEntityTypeId();
+        $bundle = $field->getTargetBundle();
+
+        if ($field->isDisplayConfigurable('form')) {
+          $component = \Drupal::service('plugin.manager.field.widget')
+            ->prepareConfiguration($field->getType(), []);
+
+          entity_get_form_display($entity_type, $bundle, 'default')
+            ->setComponent($field->getName(), $component)
+            ->save();
+        }
+        if ($field->isDisplayConfigurable('view')) {
+          $component = \Drupal::service('plugin.manager.field.formatter')
+            ->prepareConfiguration($field->getType(), []);
+
+          entity_get_display($entity_type, $bundle, 'default')
+            ->setComponent($field->getName(), $component)
+            ->save();
+        }
+        $field->save();
+      }
+    }
+  }
+
 }
diff --git a/src/MediaBundleForm.php b/src/MediaBundleForm.php
index 014a538..5d310f0 100644
--- a/src/MediaBundleForm.php
+++ b/src/MediaBundleForm.php
@@ -373,7 +373,7 @@ class MediaBundleForm extends EntityForm {
 
     // Override the "status" base field default value, for this bundle.
     $fields = $this->entityFieldManager->getFieldDefinitions('media', $bundle->id());
-    $media = $this->entityTypeManager->getStorage('media')->create(array('bundle' => $bundle->id()));
+    $media = $this->entityTypeManager->getStorage('media')->create(['bundle' => $bundle->id()]);
     $value = (bool) $form_state->getValue(['options', 'status']);
     if ($media->status->value != $value) {
       $fields['status']->getConfig($bundle->id())->setDefaultValue($value)->save();
diff --git a/src/MediaTypeBase.php b/src/MediaTypeBase.php
index a472e7d..0a04e35 100644
--- a/src/MediaTypeBase.php
+++ b/src/MediaTypeBase.php
@@ -3,19 +3,19 @@
 namespace Drupal\media_entity;
 
 use Drupal\Component\Plugin\PluginBase;
+use Drupal\Component\Utility\NestedArray;
 use Drupal\Core\Config\Config;
 use Drupal\Core\Entity\EntityFieldManagerInterface;
 use Drupal\Core\Entity\EntityTypeManagerInterface;
-use Drupal\Core\StringTranslation\StringTranslationTrait;
+use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
-use Drupal\Component\Utility\NestedArray;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Symfony\Component\DependencyInjection\ContainerInterface;
-use Drupal\Core\Form\FormStateInterface;
 
 /**
  * Base implementation of media type plugin.
  */
-abstract class MediaTypeBase extends PluginBase implements MediaTypeInterface, ContainerFactoryPluginInterface {
+abstract class MediaTypeBase extends PluginBase implements MediaTypeInterface, SourceFieldInterface, ContainerFactoryPluginInterface {
   use StringTranslationTrait;
 
   /**
@@ -105,7 +105,9 @@ abstract class MediaTypeBase extends PluginBase implements MediaTypeInterface, C
    * {@inheritdoc}
    */
   public function defaultConfiguration() {
-    return [];
+    return [
+      'source_field' => NULL,
+    ];
   }
 
   /**
@@ -138,7 +140,27 @@ abstract class MediaTypeBase extends PluginBase implements MediaTypeInterface, C
    * {@inheritdoc}
    */
   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
-    return [];
+    $options = [];
+
+    foreach ($this->entityFieldManager->getFieldStorageDefinitions('media') as $field_name => $field) {
+      $allowed_type = in_array($field->getType(), $this->pluginDefinition['allowed_field_types']);
+      if ($allowed_type && !$field->isBaseField()) {
+        $options[$field_name] = $field->getLabel();
+      }
+    }
+
+    // If there are existing fields to choose from, allow the user to reuse one.
+    if ($options) {
+      $form['source_field'] = [
+        '#type' => 'select',
+        '#title' => $this->t('Field with source information.'),
+        '#default_value' => $this->configuration['source_field'],
+        '#empty_option' => $this->t('- Create -'),
+        '#empty_value' => NULL,
+        '#options' => $options,
+      ];
+    }
+    return $form;
   }
 
   /**
@@ -158,4 +180,85 @@ abstract class MediaTypeBase extends PluginBase implements MediaTypeInterface, C
     return 'media:' . $media->bundle() . ':' . $media->uuid();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function getSourceField(MediaBundleInterface $bundle) {
+    if (empty($this->configuration['source_field'])) {
+      return $this->createSourceField($bundle);
+    }
+    $id = 'media.' . $bundle->id() . '.' . $this->configuration['source_field'];
+
+    return $this->entityTypeManager
+      ->getStorage('field_config')
+      ->load($id)
+      ?:
+      $this->createSourceField($bundle);
+  }
+
+  /**
+   * Returns the source field storage definition.
+   *
+   * @return \Drupal\field\FieldStorageConfigInterface
+   *   The field storage definition. Will be unsaved if new.
+   */
+  protected function getSourceFieldStorage() {
+    if ($this->configuration['source_field']) {
+      $id = 'media.' . $this->configuration['source_field'];
+
+      return $this->entityTypeManager
+        ->getStorage('field_storage_config')
+        ->load($id);
+    }
+    else {
+      return $this->createSourceFieldStorage();
+    }
+  }
+
+  /**
+   * Creates the source field storage definition.
+   *
+   * @return \Drupal\field\FieldStorageConfigInterface
+   *   The unsaved field storage definition.
+   */
+  abstract protected function createSourceFieldStorage();
+
+  /**
+   * Creates the source field definition for a bundle.
+   *
+   * @param \Drupal\media_entity\MediaBundleInterface $bundle
+   *   The bundle.
+   *
+   * @return \Drupal\field\FieldConfigInterface
+   *   The unsaved field definition. The field storage definition, if new,
+   *   should also be unsaved.
+   */
+  abstract protected function createSourceField(MediaBundleInterface $bundle);
+
+  /**
+   * Determine a free field name to use as the default field.
+   *
+   * @return string
+   *   An appropriate field name that was determined to be available.
+   */
+  protected function getSourceFieldName() {
+    $base_id = 'field_media_' . $this->getPluginId();
+    $tries = 0;
+    $storage = $this->entityTypeManager->getStorage('field_storage_config');
+
+    // Iterate at least once, until no field with the generated ID is found.
+    do {
+      $id = $base_id;
+      // If we've tried before, increment and append the suffix.
+      if ($tries) {
+        $id .= '_' . $tries;
+      }
+      $field = $storage->load('media.' . $id);
+      $tries++;
+    }
+    while ($field);
+
+    return $id;
+  }
+
 }
diff --git a/src/MediaTypeInterface.php b/src/MediaTypeInterface.php
index 2a171c2..767217f 100644
--- a/src/MediaTypeInterface.php
+++ b/src/MediaTypeInterface.php
@@ -2,8 +2,8 @@
 
 namespace Drupal\media_entity;
 
-use Drupal\Component\Plugin\PluginInspectionInterface;
 use Drupal\Component\Plugin\ConfigurablePluginInterface;
+use Drupal\Component\Plugin\PluginInspectionInterface;
 use Drupal\Core\Plugin\PluginFormInterface;
 
 /**
diff --git a/src/Plugin/Action/DeleteMedia.php b/src/Plugin/Action/DeleteMedia.php
index b2a98d2..4a5a48e 100644
--- a/src/Plugin/Action/DeleteMedia.php
+++ b/src/Plugin/Action/DeleteMedia.php
@@ -84,7 +84,7 @@ class DeleteMedia extends ActionBase implements ContainerFactoryPluginInterface
    * {@inheritdoc}
    */
   public function execute($object = NULL) {
-    $this->executeMultiple(array($object));
+    $this->executeMultiple([$object]);
   }
 
   /**
diff --git a/src/Plugin/MediaEntity/Type/Generic.php b/src/Plugin/MediaEntity/Type/Generic.php
index b83ba9d..7fe313e 100644
--- a/src/Plugin/MediaEntity/Type/Generic.php
+++ b/src/Plugin/MediaEntity/Type/Generic.php
@@ -3,6 +3,7 @@
 namespace Drupal\media_entity\Plugin\MediaEntity\Type;
 
 use Drupal\Core\Form\FormStateInterface;
+use Drupal\media_entity\MediaBundleInterface;
 use Drupal\media_entity\MediaInterface;
 use Drupal\media_entity\MediaTypeBase;
 
@@ -12,7 +13,8 @@ use Drupal\media_entity\MediaTypeBase;
  * @MediaType(
  *   id = "generic",
  *   label = @Translation("Generic media"),
- *   description = @Translation("Generic media type.")
+ *   description = @Translation("Generic media type."),
+ *   allowed_field_types = {"string"}
  * )
  */
 class Generic extends MediaTypeBase {
@@ -42,6 +44,8 @@ class Generic extends MediaTypeBase {
    * {@inheritdoc}
    */
   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $form = parent::buildConfigurationForm($form, $form_state);
+
     $form['text'] = [
       '#type' => 'markup',
       '#markup' => $this->t("This type provider doesn't need configuration."),
@@ -50,4 +54,32 @@ class Generic extends MediaTypeBase {
     return $form;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  protected function createSourceFieldStorage() {
+    return $this->entityTypeManager
+      ->getStorage('field_storage_config')
+      ->create([
+        'entity_type' => 'media',
+        'field_name' => $this->getSourceFieldName(),
+        // Strings are harmless, inoffensive puppies: a good choice for a
+        // generic media type.
+        'type' => 'string',
+      ]);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function createSourceField(MediaBundleInterface $bundle) {
+    /** @var \Drupal\field\FieldConfigInterface $field */
+    return $this->entityTypeManager
+      ->getStorage('field_config')
+      ->create([
+        'field_storage' => $this->getSourceFieldStorage(),
+        'bundle' => $bundle->id(),
+      ]);
+  }
+
 }
diff --git a/src/SourceFieldInterface.php b/src/SourceFieldInterface.php
new file mode 100644
index 0000000..9c6ad65
--- /dev/null
+++ b/src/SourceFieldInterface.php
@@ -0,0 +1,20 @@
+<?php
+
+namespace Drupal\media_entity;
+
+/**
+ * Interface for media type plugins that depend on a field.
+ */
+interface SourceFieldInterface {
+
+  /**
+   * Returns the source field for a bundle using this plugin.
+   *
+   * @param \Drupal\media_entity\MediaBundleInterface $bundle
+   *   The media bundle.
+   *
+   * @return \Drupal\field\FieldConfigInterface
+   */
+  public function getSourceField(MediaBundleInterface $bundle);
+
+}
diff --git a/tests/modules/media_entity_test_type/config/schema/media_entity_test_type.schema.yml b/tests/modules/media_entity_test_type/config/schema/media_entity_test_type.schema.yml
index 6ff7e14..257c840 100644
--- a/tests/modules/media_entity_test_type/config/schema/media_entity_test_type.schema.yml
+++ b/tests/modules/media_entity_test_type/config/schema/media_entity_test_type.schema.yml
@@ -5,3 +5,6 @@ media_entity.bundle.type.test_type:
     test_config_value:
       type: string
       label: 'Test config value'
+    source_field:
+      type: string
+      label: 'Source field'
diff --git a/tests/modules/media_entity_test_type/src/Plugin/MediaEntity/Type/TestType.php b/tests/modules/media_entity_test_type/src/Plugin/MediaEntity/Type/TestType.php
index 60d68a0..46bfa5f 100644
--- a/tests/modules/media_entity_test_type/src/Plugin/MediaEntity/Type/TestType.php
+++ b/tests/modules/media_entity_test_type/src/Plugin/MediaEntity/Type/TestType.php
@@ -11,7 +11,8 @@ use Drupal\media_entity\Plugin\MediaEntity\Type\Generic;
  * @MediaType(
  *   id = "test_type",
  *   label = @Translation("Test type"),
- *   description = @Translation("Test media type.")
+ *   description = @Translation("Test media type."),
+ *   allowed_field_types = {"string"}
  * )
  */
 class TestType extends Generic {
@@ -30,7 +31,7 @@ class TestType extends Generic {
    * {@inheritdoc}
    */
   public function defaultConfiguration() {
-    return [
+    return parent::defaultConfiguration() + [
       'test_config_value' => 'This is default value.',
     ];
   }
@@ -39,12 +40,16 @@ class TestType extends Generic {
    * {@inheritdoc}
    */
   public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
+    $form = parent::buildConfigurationForm($form, $form_state);
+
     $form['test_config_value'] = [
       '#type' => 'textfield',
       '#title' => $this->t('Test config value'),
       '#default_value' => empty($this->configuration['test_config_value']) ? NULL : $this->configuration['test_config_value'],
     ];
 
+    $form['source_field']['#description'] = $this->t('Field on media entity that stores the source information.');
+
     return $form;
   }
 
diff --git a/tests/src/FunctionalJavascript/BundleCreationTest.php b/tests/src/FunctionalJavascript/BundleCreationTest.php
new file mode 100644
index 0000000..f0a3099
--- /dev/null
+++ b/tests/src/FunctionalJavascript/BundleCreationTest.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace Drupal\Tests\media_entity\FunctionalJavascript;
+use Drupal\media_entity\Entity\MediaBundle;
+
+/**
+ * Tests the media bundle creation.
+ *
+ * @group media_entity
+ */
+class BundleCreationTest extends MediaEntityJavascriptTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = [
+    'media_entity_test_type',
+  ];
+
+  /**
+   * Tests the media bundle creation form.
+   */
+  public function testBundleCreationFormWithDefaultField() {
+    $label = 'Bundle with Default Field';
+    $bundleMachineName = str_replace(' ', '_', strtolower($label));
+
+    $this->drupalGet('admin/structure/media/add');
+    $page = $this->getSession()->getPage();
+
+    // Fill in a label to the bundle.
+    $page->fillField('label', $label);
+    // Wait for machine name generation. Default: waitUntilVisible(), does not
+    // work properly.
+    $this->getSession()
+      ->wait(5000, "jQuery('.machine-name-value').text() === '{$bundleMachineName}'");
+
+    // Select our test bundle type.
+    $this->assertSession()->fieldExists('Type provider');
+    $this->assertSession()->optionExists('Type provider', 'test_type');
+    $page->selectFieldOption('Type provider', 'test_type');
+    $this->assertSession()->assertWaitOnAjaxRequest();
+
+    $page->pressButton('Save media bundle');
+
+    // Check whether the source field was correctly created.
+    $this->drupalGet("admin/structure/media/manage/{$bundleMachineName}/fields");
+
+    // Check 2nd column of first data row, to be machine name for field name.
+    $this->assertSession()
+      ->elementContains('xpath', '(//table[@id="field-overview"]//tr)[2]//td[2]', 'field_media_test_type');
+    // Check 3rd column of first data row, to be correct field type.
+    $this->assertSession()
+      ->elementTextContains('xpath', '(//table[@id="field-overview"]//tr)[2]//td[3]', 'Text (plain)');
+
+    // Check that the source field is correctly assigned to media bundle.
+    $this->drupalGet("admin/structure/media/manage/{$bundleMachineName}");
+
+    $this->assertSession()
+      ->fieldValueEquals('type_configuration[test_type][source_field]', 'field_media_test_type');
+  }
+
+  /**
+   * Test creation of media bundle, reusing an existing source field.
+   */
+  public function testBundleCreationReuseSourceField() {
+    // Create a new bundle, which should create a new field we can reuse.
+    MediaBundle::create([
+      'id' => 'pastafazoul',
+      'label' => 'Pastafazoul',
+      'type' => 'generic',
+    ])->save();
+
+    $label = 'Bundle reusing Default Field';
+    $bundleMachineName = str_replace(' ', '_', strtolower($label));
+
+    $this->drupalGet('admin/structure/media/add');
+    $page = $this->getSession()->getPage();
+
+    // Fill in a label to the bundle.
+    $page->fillField('label', $label);
+
+    // Wait for machine name generation. Default: waitUntilVisible(), does not
+    // work properly.
+    $this->getSession()
+      ->wait(5000, "jQuery('.machine-name-value').text() === '{$bundleMachineName}'");
+
+    // Select our test bundle type.
+    $this->assertSession()->fieldExists('Type provider');
+    $this->assertSession()->optionExists('Type provider', 'test_type');
+    $page->selectFieldOption('Type provider', 'test_type');
+    $this->assertSession()->assertWaitOnAjaxRequest();
+    // Select the existing field for re-use.
+    $page->selectFieldOption('type_configuration[test_type][source_field]', 'field_media_generic');
+    $page->pressButton('Save media bundle');
+
+    // Check that there are not fields created.
+    $this->drupalGet("admin/structure/media/manage/{$bundleMachineName}/fields");
+    // The reused field should be present...
+    $this->assertSession()->pageTextContains('field_media_generic');
+    // ...not a new, unique one.
+    $this->assertSession()->pageTextNotContains('field_media_generic_1');
+  }
+
+}
diff --git a/tests/src/FunctionalJavascript/MediaUiJavascriptTest.php b/tests/src/FunctionalJavascript/MediaUiJavascriptTest.php
index c8219fe..4cd1c7e 100644
--- a/tests/src/FunctionalJavascript/MediaUiJavascriptTest.php
+++ b/tests/src/FunctionalJavascript/MediaUiJavascriptTest.php
@@ -140,6 +140,11 @@ class MediaUiJavascriptTest extends MediaEntityJavascriptTestBase {
     $this->assertFalse($loaded_bundle->getStatus());
     $this->assertEquals($loaded_bundle->field_map, ['field_1' => 'name']);
 
+    // We need to clear the statically cached field definitions to account for
+    // fields that have been created by API calls in this test, since they exist
+    // in a separate memory space from the web server.
+    $this->container->get('entity_field.manager')->clearCachedFieldDefinitions();
+
     // Test that a media being created with default status to "FALSE" will be
     // created unpublished.
     /** @var \Drupal\media_entity\MediaInterface $unpublished_media */
diff --git a/tests/src/Kernel/BasicCreationTest.php b/tests/src/Kernel/BasicCreationTest.php
index 306b553..38f74e8 100644
--- a/tests/src/Kernel/BasicCreationTest.php
+++ b/tests/src/Kernel/BasicCreationTest.php
@@ -79,7 +79,7 @@ class BasicCreationTest extends KernelTestBase {
     $this->assertEquals($test_bundle->get('label'), 'Test bundle', 'Could not assure the correct bundle label.');
     $this->assertEquals($test_bundle->get('description'), 'Test bundle.', 'Could not assure the correct bundle description.');
     $this->assertEquals($test_bundle->get('type'), 'generic', 'Could not assure the correct bundle plugin type.');
-    $this->assertEquals($test_bundle->get('type_configuration'), [], 'Could not assure the correct plugin configuration.');
+    $this->assertEquals($test_bundle->get('type_configuration'), ['source_field' => 'field_media_generic_1'], 'Could not assure the correct plugin configuration.');
     $this->assertEquals($test_bundle->get('field_map'), [], 'Could not assure the correct field map.');
   }
 
