diff --git a/libraries.api.php b/libraries.api.php
index 6281a16b4bec68bcb59cf996b5eab0d250445929..2c832ebe80cf865a2ff9f3b9f0cfa5d904da0b5b 100644
--- a/libraries.api.php
+++ b/libraries.api.php
@@ -14,11 +14,15 @@
  * Drupal request-response process in a generic way.
  *
  * @section sec_definitions Library definitions
- * In order to do be useful to other modules Libraries API needs a list of
- * known libraries and metadata about each of the libraries. Because multiple
- * modules or themes may integrate with the same external library a key
- * objective of Libraries API is to keep this information separate from any one
- * module or theme.
+ * In order to be useful to other modules Libraries API needs a list of known
+ * libraries and metadata about each of the libraries. Because multiple modules
+ * themes may integrate with the same external library a key objective of
+ * Libraries API is to keep this information separate from any one module or
+ * theme.
+ *
+ * Definitions are accessed via a discovery that is responsible for checking
+ * whether a given definition exists and fetching it, if it is. See
+ * LibraryRegistryInterface and StreamDefinitionDiscovery for more information.
  *
  * @subsection sub_definitions_machine_name
  * A central part of a library's metadata is the library's machine name or ID.
@@ -35,37 +39,11 @@
  * race conditions between modules providing information for the same library.
  * Thus, in Drupal 8 there is no longer a hook making it necessary to properly
  * solve the problem of centrally maintaining and distributing library info
- * files. This has yet to be done.
- *
- * @subsection sub_definitions_stream_wrapper
- * In anticipation of a central repository of library information that will
- * distribute library definitions as separate files Libraries API provides a
- * 'library-definitions' stream wrapper. Due to that a library's definition can
- * be accessed given only it's machine name, for example at
- * 'library-definitions://example.yml' for a library with the machine name
- * 'example'. YAML is chosen as the file format because it is used in many parts
- * of Drupal 8 already. Using a stream wrapper has the benefit of being able to
- * swap out the specific storage implementation without any other part of the
- * code needing to change. For example, the specific directory which holds the
- * library definitions on disk can be changed, multiple directories can be
- * layered as though they were one, or the library definitions can even be
- * read from a remote location without any part of the code other than the
- * stream wrapper implementation itself needing to change.
- *
- * By default the library definitions stream wrapper reads from a single
- * directory that is configurable and points to the 'library-definitions'
- * directory within the public files directory by default. This makes library
- * definitions writable by the webserver by default, which is in anticipation of
- * a user interface that fetches definitions from a remote repository and stores
- * them locally. For improved security the library definitions can be managed
- * manually (or put under version control) and placed in a directory that is not
- * writable by the webserver. The idea of using a stream wrapper for this as
- * well as the default location is taken from the 'translations' stream wrapper
- * provided by the Interface Translation module.
+ * files. This has yet to be done. See https://www.drupal.org/node/773508 for
+ * more information.
  *
- * @see \Drupal\libraries\ExternalLibrary\Registry\LibraryRegistryInterface
- * @see \Drupal\libraries\ExternalLibrary\Registry\LibraryRegistry
- * @see \Drupal\libraries\StreamWrapper\LibraryDefinitionsStream
+ * @see \Drupal\libraries\ExternalLibrary\Definition\DefinitionDiscoveryInterface
+ * @see \Drupal\libraries\ExternalLibrary\Definition\StreamDefinitionDiscovery
  *
  * @}
  */
diff --git a/libraries.module b/libraries.module
index 34e2913c89a54bccbe389344746c27475cbe1a16..77d3f455292e6c667599aad41b1ec4d0871b91b2 100644
--- a/libraries.module
+++ b/libraries.module
@@ -17,8 +17,9 @@ function libraries_library_info_build() {
   $library_manager = \Drupal::service('libraries.manager');
 
   $core_libraries = [];
-  foreach ($library_manager->getRequiredLibraries() as $external_library) {
-    // @todo Consider using a library type listener instead.
+  foreach ($library_manager->getRequiredLibraryIds() as $external_library_id) {
+    $external_library = $library_manager->getLibrary($external_library_id);
+    // @todo Use a library type listener instead.
     if ($external_library instanceof AssetLibraryInterface) {
       $core_libraries += $external_library->getAttachableAssetLibraries();
     }
diff --git a/libraries.services.yml b/libraries.services.yml
index 1ee8a6fd043d7366c9ff4e14a6239ae070ad3285..18d36cabf84bd236a5cd8b7b66a0e33a6b5c35e5 100644
--- a/libraries.services.yml
+++ b/libraries.services.yml
@@ -2,15 +2,15 @@ services:
   libraries.manager:
     class: Drupal\libraries\ExternalLibrary\LibraryManager
     arguments:
-      - '@libraries.registry'
+      - '@libraries.definitions.discovery'
+      - '@plugin.manager.libraries.library_type'
       - '@libraries.extension_handler'
-      - '@libraries.php_file_loader'
-  libraries.registry:
-    class: Drupal\libraries\ExternalLibrary\Registry\LibraryRegistry
-    arguments: ['@serialization.yaml', '@plugin.manager.libraries.library_type']
+  libraries.definitions.discovery:
+    class: Drupal\libraries\ExternalLibrary\Definition\StreamDefinitionDiscovery
+    arguments: ['@serialization.yaml']
 
   plugin.manager.libraries.library_type:
-    class: Drupal\libraries\ExternalLibrary\LibraryType\LibraryTypeManager
+    class: Drupal\libraries\ExternalLibrary\LibraryType\LibraryTypeFactory
     parent: default_plugin_manager
   plugin.manager.libraries.locator:
     class: Drupal\libraries\ExternalLibrary\Local\LocatorManager
diff --git a/src/ExternalLibrary/Definition/DefinitionDiscoveryInterface.php b/src/ExternalLibrary/Definition/DefinitionDiscoveryInterface.php
new file mode 100644
index 0000000000000000000000000000000000000000..2d7bebdf87d141bd901ea96bbbbf7605cac82aa1
--- /dev/null
+++ b/src/ExternalLibrary/Definition/DefinitionDiscoveryInterface.php
@@ -0,0 +1,43 @@
+<?php
+
+namespace Drupal\libraries\ExternalLibrary\Definition;
+
+/**
+ * Provides an interface for library definition discoveries.
+ *
+ * This is similar to the plugin system's DiscoveryInterface, except that this
+ * does not require knowing all definitions upfront, so there is no
+ * getDefinitions() method.
+ *
+ * @see \Drupal\Component\Plugin\Discovery\DiscoveryInterface
+ */
+interface DefinitionDiscoveryInterface {
+
+  /**
+   * Checks whether a library definition exists.
+   *
+   * @param string $id
+   *   The library ID.
+   *
+   * @return bool
+   *   TRUE if a library definition with the given ID exists; FALSE otherwise.
+   */
+  public function hasDefinition($id);
+
+  /**
+   * Gets a library definition by its ID.
+   *
+   * @param string $id
+   *   The library ID.
+   *
+   * @return array
+   *   The library definition.
+   *
+   * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException
+   *
+   * @todo Consider returning a classed object instead of an array or at least
+   *   document and validate the array structure.
+   */
+  public function getDefinition($id);
+
+}
diff --git a/src/ExternalLibrary/Definition/StreamDefinitionDiscovery.php b/src/ExternalLibrary/Definition/StreamDefinitionDiscovery.php
new file mode 100644
index 0000000000000000000000000000000000000000..328b0429babe0e745437e4056502cac608b27e1d
--- /dev/null
+++ b/src/ExternalLibrary/Definition/StreamDefinitionDiscovery.php
@@ -0,0 +1,96 @@
+<?php
+
+namespace Drupal\libraries\ExternalLibrary\Definition;
+
+use Drupal\Component\Serialization\SerializationInterface;
+use Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException;
+
+/**
+ * Provides a stream-based implementation of a libraries definition discovery.
+ *
+ * Given a library ID of 'example', it reads the library definition from the URI
+ * 'library-definitions://example.yml'. See LibraryDefinitionsStream for more
+ * information.
+ *
+ * Using a stream wrapper has the benefit of being able to swap out the specific
+ * storage implementation without any other part of the code needing to change.
+ * For example, the specific directory which holds the library definitions on
+ * disk can be changed, multiple directories can be layered as though they were
+ * one, or the library definitions can even be read from a remote location
+ * without any part of the code other than the stream wrapper implementation
+ * itself needing to change.
+ *
+ * @see \Drupal\libraries\StreamWrapper\LibraryDefinitionsStream
+ */
+class StreamDefinitionDiscovery implements DefinitionDiscoveryInterface {
+
+  /**
+   * The serializer for the library definition files.
+   *
+   * @var \Drupal\Component\Serialization\SerializationInterface
+   */
+  protected $serializer;
+
+  /**
+   * The scheme of the stream to use for library definitions.
+   *
+   * @var string
+   */
+  protected $scheme = 'library-definitions';
+
+  /**
+   * Constructs a stream-based library definition discovery.
+   *
+   * @param \Drupal\Component\Serialization\SerializationInterface $serializer
+   *   The serializer for the library definition files.
+   */
+  public function __construct(SerializationInterface $serializer) {
+    $this->serializer = $serializer;
+  }
+
+  /**
+   * Checks whether a library definition exists for the given ID.
+   *
+   * @param string $id
+   *   The library ID to check for.
+   *
+   * @return bool
+   *  TRUE if the library definition exists; FALSE otherwise.
+   */
+  public function hasDefinition($id) {
+    return file_exists($this->getFileUri($id));
+  }
+
+  /**
+   * Returns the library definition for the given ID.
+   *
+   * @param string $id
+   *   The library ID to retrieve the definition for.
+   *
+   * @return array
+   *   The library definition array parsed from the definition JSON file.
+   *
+   * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException
+   */
+  public function getDefinition($id) {
+    if (!$this->hasDefinition($id)) {
+      throw new LibraryDefinitionNotFoundException($id);
+    }
+    return $this->serializer->decode(file_get_contents($this->getFileUri($id)));
+  }
+
+  /**
+   * Returns the file URI of the library definition file for a given library ID.
+   *
+   * @param $id
+   *   The ID of the external library.
+   *
+   * @return string
+   *   The file URI of the file the library definition resides in.
+   */
+  protected function getFileUri($id) {
+    $filename = $id . '.' . $this->serializer->getFileExtension();
+    return "$this->scheme://$filename";
+  }
+
+}
diff --git a/src/ExternalLibrary/Exception/LibraryClassNotFoundException.php b/src/ExternalLibrary/Exception/LibraryClassNotFoundException.php
deleted file mode 100644
index 0e64d8516c15c52446aa5fe8d58d3d20e7c788ec..0000000000000000000000000000000000000000
--- a/src/ExternalLibrary/Exception/LibraryClassNotFoundException.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\libraries\ExternalLibrary\Exception\LibraryClassNotFoundException.
- */
-
-namespace Drupal\libraries\ExternalLibrary\Exception;
-
-use Drupal\libraries\ExternalLibrary\Utility\LibraryIdAccessorTrait;
-use Exception;
-
-/**
- * Provides an exception for a library definition without a class declaration..
- */
-class LibraryClassNotFoundException extends \RuntimeException {
-
-  use LibraryIdAccessorTrait;
-
-  /**
-   * Constructs a library exception.
-   *
-   * @param string $library_id
-   *   The library ID.
-   * @param string $message
-   *   (optional) The exception message.
-   * @param int $code
-   *   (optional) The error code.
-   * @param \Exception $previous
-   *   (optional) The previous exception.
-   */
-  public function __construct(
-    $library_id,
-    $message = '',
-    $code = 0,
-    \Exception $previous = NULL
-  ) {
-    $this->libraryId = (string) $library_id;
-    $message = $message ?: "The library class for the library '{$this->libraryId}' could not be found.";
-    parent::__construct($message, $code, $previous);
-  }
-
-}
diff --git a/src/ExternalLibrary/LibraryManager.php b/src/ExternalLibrary/LibraryManager.php
index 49a642b73edebc8d5eeb8c8ce30dd2c936242ab3..6cfef1db04c624e14d12a9128bbf722bd95aee09 100644
--- a/src/ExternalLibrary/LibraryManager.php
+++ b/src/ExternalLibrary/LibraryManager.php
@@ -6,10 +6,12 @@
  */
 
 namespace Drupal\libraries\ExternalLibrary;
+use Drupal\Component\Plugin\Factory\FactoryInterface;
 use Drupal\libraries\Extension\ExtensionHandlerInterface;
+use Drupal\libraries\ExternalLibrary\Exception\LibraryTypeNotFoundException;
+use Drupal\libraries\ExternalLibrary\LibraryType\LibraryCreationListenerInterface;
 use Drupal\libraries\ExternalLibrary\LibraryType\LibraryLoadingListenerInterface;
-use Drupal\libraries\ExternalLibrary\PhpFile\PhpFileLoaderInterface;
-use Drupal\libraries\ExternalLibrary\Registry\LibraryRegistryInterface;
+use Drupal\libraries\ExternalLibrary\Definition\DefinitionDiscoveryInterface;
 
 /**
  * Provides a manager for external libraries.
@@ -17,11 +19,18 @@ use Drupal\libraries\ExternalLibrary\Registry\LibraryRegistryInterface;
 class LibraryManager implements LibraryManagerInterface {
 
   /**
-   * The library registry.
+   * The library definition discovery.
    *
-   * @var \Drupal\libraries\ExternalLibrary\Registry\LibraryRegistryInterface
+   * @var \Drupal\libraries\ExternalLibrary\Definition\DefinitionDiscoveryInterface
    */
-  protected $registry;
+  protected $definitionDiscovery;
+
+  /**
+   * The library type factory.
+   *
+   * @var \Drupal\Component\Plugin\Factory\FactoryInterface
+   */
+  protected $libraryTypeFactory;
 
   /**
    * The extension handler.
@@ -33,48 +42,88 @@ class LibraryManager implements LibraryManagerInterface {
   /**
    * Constructs an external library manager.
    *
-   * @param \Drupal\libraries\ExternalLibrary\Registry\LibraryRegistryInterface $registry
+   * @param \Drupal\libraries\ExternalLibrary\Definition\DefinitionDiscoveryInterface $definition_disovery
    *   The library registry.
+   * @param \Drupal\Component\Plugin\Factory\FactoryInterface $library_type_factory
+   *   The library type factory.
    * @param \Drupal\libraries\Extension\ExtensionHandlerInterface $extension_handler
    *   The extension handler.
-   * @param \Drupal\libraries\ExternalLibrary\PhpFile\PhpFileLoaderInterface $php_file_loader
-   *   The PHP file loader.
    */
   public function __construct(
-    LibraryRegistryInterface $registry,
-    ExtensionHandlerInterface $extension_handler,
-    PhpFileLoaderInterface $php_file_loader
+    DefinitionDiscoveryInterface $definition_disovery,
+    FactoryInterface $library_type_factory,
+    ExtensionHandlerInterface $extension_handler
   ) {
-    $this->registry = $registry;
+    $this->definitionDiscovery = $definition_disovery;
+    $this->libraryTypeFactory = $library_type_factory;
     $this->extensionHandler = $extension_handler;
-    $this->phpFileLoader = $php_file_loader;
   }
 
   /**
    * {@inheritdoc}
    */
-  public function getRequiredLibraries() {
-    $libraries = [];
+  public function getLibrary($id) {
+    $definition = $this->definitionDiscovery->getDefinition($id);
+    return $this->getLibraryFromDefinition($id, $definition);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getRequiredLibraryIds() {
+    $library_ids = [];
     foreach ($this->extensionHandler->getExtensions() as $extension) {
       foreach ($extension->getLibraryDependencies() as $library_id) {
-        // Do not bother instantiating a library multiple times.
-        if (!isset($libraries[$library_id])) {
-          $libraries[$library_id] = $this->registry->getLibrary($library_id);
-        }
+        $library_ids[] = $library_id;
       }
     }
-    return $libraries;
+    return array_unique($library_ids);
   }
 
   /**
    * {@inheritdoc}
    */
   public function load($id) {
-    $library_type = $this->registry->getLibraryType($id);
+    $definition = $this->definitionDiscovery->getDefinition($id);
+    $library_type = $this->getLibraryType($id, $definition);
     // @todo Throw an exception instead of silently failing.
     if ($library_type instanceof LibraryLoadingListenerInterface) {
-      $library_type->onLibraryLoad($this->registry->getLibrary($id));
-   }
+      $library_type->onLibraryLoad($this->getLibraryFromDefinition($id, $definition));
+    }
+  }
+
+  /**
+   * @param $id
+   * @param $definition
+   * @return mixed
+   */
+  protected function getLibraryFromDefinition($id, $definition) {
+    $library_type = $this->getLibraryType($id, $definition);
+
+    // @todo Make this alter-able.
+    $class = $library_type->getLibraryClass();
+
+    // @todo Make sure that the library class implements the correct interface.
+    $library = $class::create($id, $definition);
+
+    if ($library_type instanceof LibraryCreationListenerInterface) {
+      $library_type->onLibraryCreate($library);
+      return $library;
+    }
+    return $library;
+  }
+
+  /**
+   * @param $id
+   * @param $definition
+   * @return object
+   */
+  protected function getLibraryType($id, $definition) {
+    // @todo Validate that the type is a string.
+    if (!isset($definition['type'])) {
+      throw new LibraryTypeNotFoundException($id);
+    }
+    return $this->libraryTypeFactory->createInstance($definition['type']);
   }
 
 }
diff --git a/src/ExternalLibrary/LibraryManagerInterface.php b/src/ExternalLibrary/LibraryManagerInterface.php
index 58e7dc8ad485e3fdb31335c16bce886c96d11a2a..0cd7ef7832a65fac0f288dbac795fd922a615115 100644
--- a/src/ExternalLibrary/LibraryManagerInterface.php
+++ b/src/ExternalLibrary/LibraryManagerInterface.php
@@ -13,27 +13,42 @@ namespace Drupal\libraries\ExternalLibrary;
  */
 interface LibraryManagerInterface {
 
+  /**
+   * Gets a library by its ID.
+   *
+   * @param string $id
+   *   The library ID.
+   *
+   * @return \Drupal\libraries\ExternalLibrary\LibraryInterface
+   *   The library object.
+   *
+   * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException
+   * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryTypeNotFoundException
+   * @throws \Drupal\Component\Plugin\Exception\PluginException
+   */
+  public function getLibrary($id);
+
   /**
    * Gets the list of libraries that are required by enabled extensions.
    *
    * Modules, themes, and installation profiles can declare library dependencies
-   * in their info files.
+   * by specifying a 'library_dependencies' key in their info files.
    *
-   * @return \Drupal\libraries\ExternalLibrary\LibraryInterface[]|\Generator
-   *   An array of libraries keyed by their ID.
-   *
-   * @todo Expand the documentation.
-   * @todo Consider returning just library IDs.
+   * @return string[]
+   *   An array of library IDs.
    */
-  public function getRequiredLibraries();
+  public function getRequiredLibraryIds();
 
   /**
    * Loads library files for a library.
    *
+   * Note that not all library types support explicit loading. Asset libraries,
+   * in particular, are declared to Drupal core's library system and are then
+   * loaded using that.
+   *
    * @param string $id
    *   The ID of the library.
    *
-   * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryClassNotFoundException
    * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException
    * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryNotInstalledException
    */
diff --git a/src/ExternalLibrary/LibraryType/LibraryTypeManager.php b/src/ExternalLibrary/LibraryType/LibraryTypeFactory.php
similarity index 76%
rename from src/ExternalLibrary/LibraryType/LibraryTypeManager.php
rename to src/ExternalLibrary/LibraryType/LibraryTypeFactory.php
index 6ca779cd6244882a8a5770d09ca5b941d47814e4..dff4668b9d31843401e1e04128f000692f45de83 100644
--- a/src/ExternalLibrary/LibraryType/LibraryTypeManager.php
+++ b/src/ExternalLibrary/LibraryType/LibraryTypeFactory.php
@@ -1,12 +1,8 @@
 <?php
 
-/**
- * @file
- * Contains \Drupal\libraries\ExternalLibrary\LibraryType\LibraryTypeManager.
- */
-
 namespace Drupal\libraries\ExternalLibrary\LibraryType;
 
+use Drupal\Component\Plugin\Factory\FactoryInterface;
 use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\Plugin\DefaultPluginManager;
@@ -15,7 +11,7 @@ use Drupal\libraries\Annotation\LibraryType;
 /**
  * Provides a plugin manager for library type plugins.
  */
-class LibraryTypeManager extends DefaultPluginManager implements LibraryTypeManagerInterface {
+class LibraryTypeFactory extends DefaultPluginManager {
 
   /**
    * Constructs a locator manager.
@@ -35,13 +31,4 @@ class LibraryTypeManager extends DefaultPluginManager implements LibraryTypeMana
     $this->setCacheBackend($cache_backend, 'libraries_library_type_info');
   }
 
-  /**
-   * {@inheritdoc}
-   */
-  public function getLibraryClass(LibraryTypeInterface $library_type) {
-    // @todo Make this alter-able.
-    return $library_type->getLibraryClass();
-  }
-
-
 }
diff --git a/src/ExternalLibrary/LibraryType/LibraryTypeManagerInterface.php b/src/ExternalLibrary/LibraryType/LibraryTypeManagerInterface.php
deleted file mode 100644
index d3b68a6acd6b556e5af4b8129142ed529e7a73f1..0000000000000000000000000000000000000000
--- a/src/ExternalLibrary/LibraryType/LibraryTypeManagerInterface.php
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\libraries\ExternalLibrary\LibraryType\LibraryTypeManagerInterface.
- */
-
-namespace Drupal\libraries\ExternalLibrary\LibraryType;
-
-use Drupal\Component\Plugin\Factory\FactoryInterface;
-
-/**
- * Provides an interface for library type managers.
- */
-interface LibraryTypeManagerInterface extends FactoryInterface {
-
-  /**
-   * Gets the library class to use for a given library type.
-   *
-   * @param \Drupal\libraries\ExternalLibrary\LibraryType\LibraryTypeInterface $library_type
-   *   The library type to return the library class for.
-   *
-   * @return string
-   *   The library class.
-   */
-  public function getLibraryClass(LibraryTypeInterface $library_type);
-
-}
-
diff --git a/src/ExternalLibrary/Registry/LibraryRegistry.php b/src/ExternalLibrary/Registry/LibraryRegistry.php
deleted file mode 100644
index 2555ffd93b05028167e7f9b49714a5ccea99d6f9..0000000000000000000000000000000000000000
--- a/src/ExternalLibrary/Registry/LibraryRegistry.php
+++ /dev/null
@@ -1,129 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\libraries\ExternalLibrary\Registry\LibraryRegistry.
- */
-
-namespace Drupal\libraries\ExternalLibrary\Registry;
-
-use Drupal\Component\Plugin\Factory\FactoryInterface;
-use Drupal\Component\Serialization\SerializationInterface;
-use Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException;
-use Drupal\libraries\ExternalLibrary\Exception\LibraryTypeNotFoundException;
-use Drupal\libraries\ExternalLibrary\LibraryType\LibraryCreationListenerInterface;
-
-/**
- * Provides an implementation of a registry of external libraries.
- *
- * @todo Consider moving parts of this logic into LibraryManager.
- * @todo Allow for JavaScript CDN's, Packagist, etc. to act as library
- *   registries.
- */
-class LibraryRegistry implements LibraryRegistryInterface {
-
-  /**
-   * The serializer for the library definition files.
-   *
-   * @var \Drupal\Component\Serialization\SerializationInterface
-   */
-  protected $serializer;
-
-  /**
-   * The library type manager.
-   *
-   * @var \Drupal\Component\Plugin\Factory\FactoryInterface
-   */
-  protected $libraryTypeFactory;
-
-  /**
-   * Constructs a registry of external libraries.
-   *
-   * @param \Drupal\Component\Serialization\SerializationInterface $serializer
-   *   The serializer for the library definition files.
-   * @param \Drupal\Component\Plugin\Factory\FactoryInterface $library_type_factory
-   *   The library type manager.
-   */
-  public function __construct(
-    SerializationInterface $serializer,
-    FactoryInterface $library_type_factory
-  ) {
-    $this->serializer = $serializer;
-    $this->libraryTypeFactory = $library_type_factory;
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getLibrary($id) {
-    $library_type = $this->getLibraryType($id);
-
-    $class = $this->libraryTypeFactory->getLibraryClass($library_type);
-    // @todo Make sure that the library class implements the correct interface.
-    $library = $class::create($id, $this->getDefinition($id));
-
-    if ($library_type instanceof LibraryCreationListenerInterface) {
-      $library_type->onLibraryCreate($library);
-    }
-
-    return $library;
-  }
-
-  /**
-   * Checks whether a library definition exists for the given ID.
-   *
-   * @param string $id
-   *   The library ID to check for.
-   *
-   * @return bool
-   *  TRUE if the library definition exists; FALSE otherwise.
-   */
-  protected function hasDefinition($id) {
-    return file_exists($this->getFileUri($id));
-  }
-
-  /**
-   * Returns the library definition for the given ID.
-   *
-   * @param string $id
-   *   The library ID to retrieve the definition for.
-   *
-   * @return array
-   *   The library definition array parsed from the definition JSON file.
-   *
-   * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException
-   */
-  protected function getDefinition($id) {
-    if (!$this->hasDefinition($id)) {
-      throw new LibraryDefinitionNotFoundException($id);
-    }
-    return $this->serializer->decode(file_get_contents($this->getFileUri($id)));
-  }
-
-  /**
-   * Returns the file URI of the library definition file for a given library ID.
-   *
-   * @param $id
-   *   The ID of the external library.
-   *
-   * @return string
-   *   The file URI of the file the library definition resides in.
-   */
-  protected function getFileUri($id) {
-    $filename = $id . '.' . $this->serializer->getFileExtension();
-    return "library-definitions://$filename";
-  }
-
-  /**
-   * {@inheritdoc}
-   */
-  public function getLibraryType($id) {
-    $definition = $this->getDefinition($id);
-    // @todo Validate that the type is a string.
-    if (!isset($definition['type'])) {
-      throw new LibraryTypeNotFoundException($id);
-    }
-    return  $this->libraryTypeFactory->createInstance($definition['type']);
-  }
-
-}
diff --git a/src/ExternalLibrary/Registry/LibraryRegistryInterface.php b/src/ExternalLibrary/Registry/LibraryRegistryInterface.php
deleted file mode 100644
index 146c28383a511be8725331b3d1ad2f3b41e15259..0000000000000000000000000000000000000000
--- a/src/ExternalLibrary/Registry/LibraryRegistryInterface.php
+++ /dev/null
@@ -1,53 +0,0 @@
-<?php
-
-/**
- * @file
- * Contains \Drupal\libraries\ExternalLibrary\Registry\LibraryRegistryInterface.
- */
-
-namespace Drupal\libraries\ExternalLibrary\Registry;
-
-
-/**
- * Provides an interface for library registries.
- */
-interface LibraryRegistryInterface {
-
-  /**
-   * Gets a library by its ID.
-   *
-   * @param string $id
-   *   The library ID.
-   *
-   * @return \Drupal\libraries\ExternalLibrary\LibraryInterface
-   *   The library.
-   *
-   * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryClassNotFoundException
-   * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException
-   */
-  public function getLibrary($id);
-
-  /**
-   * Returns the library type for a library ID.
-   *
-   * Note that the passed ID is not the ID of the library type, but the library
-   * ID itself. Use the LibraryTypeManager to retrieve a library type given its
-   * ID.
-   *
-   * @param string $id
-   *   The ID of the external library.
-   *
-   * @return string|\Drupal\libraries\ExternalLibrary\LibraryType\LibraryTypeInterface
-   *   The library type.
-   *
-   * @see \Drupal\libraries\ExternalLibrary\LibraryTypeManager
-   *
-   * @throws \Drupal\libraries\ExternalLibrary\Exception\LibraryClassNotFoundException
-   * @throws \Drupal\Component\Plugin\Exception\PluginException
-   *
-   * @todo Consider making this protected again, when this is moved to the
-   *   LibraryManager.
-   */
-  public function getLibraryType($id);
-
-}
diff --git a/src/Plugin/libraries/LibraryType/PhpFileLibraryType.php b/src/Plugin/libraries/LibraryType/PhpFileLibraryType.php
index 821bf6a3096a0a0b34674a3d028bf9ba25ca8049..0575e9c1386ef3f8c614a30e414db7d0cca06d0a 100644
--- a/src/Plugin/libraries/LibraryType/PhpFileLibraryType.php
+++ b/src/Plugin/libraries/LibraryType/PhpFileLibraryType.php
@@ -106,10 +106,10 @@ class PhpFileLibraryType implements
    */
   public function onLibraryLoad(LibraryInterface $library) {
     /** @var \Drupal\libraries\ExternalLibrary\PhpFile\PhpFileLibraryInterface $library */
+    // @todo Prevent loading a library multiple times.
     foreach ($library->getPhpFiles() as $file) {
       $this->phpFileLoader->load($file);
     }
-
   }
 
 }
diff --git a/src/StreamWrapper/LibraryDefinitionsStream.php b/src/StreamWrapper/LibraryDefinitionsStream.php
index 674866031759b802cc0039170d56891c2cc11c0f..c199fa0378600c85bb665d45be0f0f0e71821f45 100644
--- a/src/StreamWrapper/LibraryDefinitionsStream.php
+++ b/src/StreamWrapper/LibraryDefinitionsStream.php
@@ -13,9 +13,24 @@ use Drupal\Core\StreamWrapper\LocalStream;
  * Provides a stream wrapper for library definitions.
  *
  * Can be used with the 'library-definitions' scheme, for example
- * 'library-definitions://example.yml'.
+ * 'library-definitions://example.yml' for a library ID of 'example'.
+ *
+ * By default this stream wrapper reads from a single directory that is
+ * configurable and points to the 'library-definitions' directory within the
+ * public files directory by default. This makes library definitions writable
+ * by the webserver by default, which is in anticipation of a user interface
+ * that fetches definitions from a remote repository and stores them locally.
+ * For improved security the library definitions can be managed manually (or put
+ * under version control) and placed in a directory that is not writable by the
+ * webserver.
+ *
+ * The idea of using a stream wrapper for this as well as the default location
+ * is taken from the 'translations' stream wrapper provided by the Interface
+ * Translation module.
  *
  * @see \Drupal\locale\StreamWrapper\TranslationsStream
+ *
+ * @todo Use a setting instead of configuration for the directory.
  */
 class LibraryDefinitionsStream extends LocalStream {
 
diff --git a/tests/src/Kernel/ExternalLibrary/Asset/AssetLibraryTest.php b/tests/src/Kernel/ExternalLibrary/Asset/AssetLibraryTest.php
index 9b840d4bf7873c92632ff28ffd844facbc31d7e3..e0e444cb9f56f07e8734b76edc53e2f2cc40d687 100644
--- a/tests/src/Kernel/ExternalLibrary/Asset/AssetLibraryTest.php
+++ b/tests/src/Kernel/ExternalLibrary/Asset/AssetLibraryTest.php
@@ -2,18 +2,15 @@
 
 namespace Drupal\Tests\libraries\Kernel\ExternalLibrary\Asset;
 
-use Drupal\libraries\ExternalLibrary\Asset\AssetLibrary;
-use Drupal\libraries\ExternalLibrary\Exception\LibraryClassNotFoundException;
-use Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException;
 use Drupal\Tests\libraries\Kernel\ExternalLibrary\TestLibraryFilesStream;
-use Drupal\Tests\libraries\Kernel\LibraryKernelTestBase;
+use Drupal\Tests\libraries\Kernel\LibraryTypeKernelTestBase;
 
 /**
  * Tests that external asset libraries are registered as core asset libraries.
  *
  * @group libraries
  */
-class AssetLibraryTest extends LibraryKernelTestBase {
+class AssetLibraryTypeTest extends LibraryTypeKernelTestBase {
 
   /**
    * {@inheritdoc}
@@ -28,41 +25,36 @@ class AssetLibraryTest extends LibraryKernelTestBase {
    *
    * @var \Drupal\Core\Asset\LibraryDiscoveryInterface
    */
-  protected $libraryDiscovery;
+  protected $coreLibraryDiscovery;
 
   /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
-
-    $this->libraryDiscovery = $this->container->get('library.discovery');
+    $this->coreLibraryDiscovery = $this->container->get('library.discovery');
   }
 
   /**
-   * Tests that library metadata is correctly gathered.
+   * {@inheritdoc}
    */
-  public function testMetadata() {
-    try {
-      /** @var \Drupal\libraries\ExternalLibrary\Asset\AssetLibrary $library */
-      $library = $this->externalLibraryRegistry->getLibrary('test_asset_library');
-      $this->assertInstanceOf(AssetLibrary::class, $library);
+  protected function getLibraryTypeId() {
+    return 'asset';
+  }
 
-      $this->assertEquals('test_asset_library', $library->getId());
-      $expected = ['test_asset_library' => [
-        'version' => '1.0.0',
-        'css' => ['base' => ['http://example.com/example.css' => []]],
-        'js' => ['http://example.com/example.js' => []],
-        'dependencies' => [],
-      ]];
-      $this->assertEquals($expected, $library->getAttachableAssetLibraries());
-    }
-    catch (LibraryClassNotFoundException $exception) {
-      $this->fail();
-    }
-    catch (LibraryDefinitionNotFoundException $exception) {
-      $this->fail();
-    }
+  /**
+   * Tests that attachable asset library info is correctly gathered.
+   */
+  public function testAttachableAssetInfo() {
+    /** @var \Drupal\libraries\ExternalLibrary\Asset\AssetLibrary $library */
+    $library = $this->getLibrary();
+    $expected = ['test_asset_library' => [
+      'version' => '1.0.0',
+      'css' => ['base' => ['http://example.com/example.css' => []]],
+      'js' => ['http://example.com/example.js' => []],
+      'dependencies' => [],
+    ]];
+    $this->assertEquals($expected, $library->getAttachableAssetLibraries());
   }
 
   /**
@@ -77,7 +69,7 @@ class AssetLibraryTest extends LibraryKernelTestBase {
    * @see \Drupal\libraries\ExternalLibrary\Registry\ExternalLibraryRegistry
    */
   public function testAssetLibraryRemote() {
-    $library = $this->libraryDiscovery->getLibraryByName('libraries', 'test_asset_library');
+    $library = $this->coreLibraryDiscovery->getLibraryByName('libraries', 'test_asset_library');
     $expected = [
       'version' => '1.0.0',
       'css' => [[
@@ -112,8 +104,8 @@ class AssetLibraryTest extends LibraryKernelTestBase {
       $this->container->get('string_translation'),
       'assets/vendor'
     ));
-    $this->libraryDiscovery->clearCachedDefinitions();
-    $library = $this->libraryDiscovery->getLibraryByName('libraries', 'test_asset_library');
+    $this->coreLibraryDiscovery->clearCachedDefinitions();
+    $library = $this->coreLibraryDiscovery->getLibraryByName('libraries', 'test_asset_library');
     $expected = [
       'version' => '1.0.0',
       'css' => [[
diff --git a/tests/src/Kernel/ExternalLibrary/PhpFile/PhpFileLibraryTest.php b/tests/src/Kernel/ExternalLibrary/PhpFile/PhpFileLibraryTest.php
index 9e5d1e86a6deaebc313076ae9dac42e5ae61060d..9209758913323dccff163832f417487d320562d1 100644
--- a/tests/src/Kernel/ExternalLibrary/PhpFile/PhpFileLibraryTest.php
+++ b/tests/src/Kernel/ExternalLibrary/PhpFile/PhpFileLibraryTest.php
@@ -2,39 +2,29 @@
 
 namespace Drupal\Tests\libraries\Kernel\ExternalLibrary\PhpFile;
 
-use Drupal\libraries\ExternalLibrary\Exception\LibraryClassNotFoundException;
 use Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException;
 use Drupal\libraries\ExternalLibrary\PhpFile\PhpFileLibrary;
 use Drupal\Tests\libraries\Kernel\ExternalLibrary\TestLibraryFilesStream;
-use Drupal\Tests\libraries\Kernel\LibraryKernelTestBase;
+use Drupal\Tests\libraries\Kernel\LibraryTypeKernelTestBase;
 
 /**
  * Tests that the external library manager properly loads PHP file libraries.
  *
  * @group libraries
  */
-class PhpFileLibraryTest extends LibraryKernelTestBase {
+class PhpFileLibraryTypeTest extends LibraryTypeKernelTestBase {
 
   /**
    * {@inheritdoc}
    */
   public static $modules = ['libraries', 'libraries_test'];
 
-  /**
-   * The external library manager.
-   *
-   * @var \Drupal\libraries\ExternalLibrary\LibraryManagerInterface
-   */
-  protected $externalLibraryManager;
-
   /**
    * {@inheritdoc}
    */
   protected function setUp() {
     parent::setUp();
 
-    $this->externalLibraryManager = $this->container->get('libraries.manager');
-
     $this->container->set('stream_wrapper.php_file_libraries', new TestLibraryFilesStream(
       $this->container->get('module_handler'),
       $this->container->get('string_translation'),
@@ -43,24 +33,22 @@ class PhpFileLibraryTest extends LibraryKernelTestBase {
   }
 
   /**
-   * Tests that library metadata is correctly gathered.
+   * {@inheritdoc}
    */
-  public function testMetadata() {
-    try {
-      /** @var \Drupal\libraries\ExternalLibrary\PhpFile\PhpFileLibrary $library */
-      $library = $this->externalLibraryRegistry->getLibrary('test_php_file_library');
-      $this->assertInstanceOf(PhpFileLibrary::class, $library);
+  protected function getLibraryTypeId() {
+    return 'php_file';
+  }
 
-      $this->assertEquals('test_php_file_library', $library->getId());
-      $expected = [$this->modulePath . DIRECTORY_SEPARATOR . 'tests/libraries/test_php_file_library/test_php_file_library.php'];
-      $this->assertEquals($expected, $library->getPhpFiles());
-    }
-    catch (LibraryClassNotFoundException $exception) {
-      $this->fail();
-    }
-    catch (LibraryDefinitionNotFoundException $exception) {
-      $this->fail();
-    }
+  /**
+   * Tests that the list of PHP files is correctly gathered.
+   */
+  public function testPhpFileInfo() {
+    /** @var \Drupal\libraries\ExternalLibrary\PhpFile\PhpFileLibrary $library */
+    $library = $this->getLibrary();
+    $this->assertTrue($library->isInstalled());
+    $library_path = $this->modulePath . DIRECTORY_SEPARATOR . 'tests/libraries/test_php_file_library';
+    $this->assertEquals($library_path, $library->getLocalPath());
+    $this->assertEquals(["$library_path/test_php_file_library.php"], $library->getPhpFiles());
   }
 
   /**
@@ -78,7 +66,7 @@ class PhpFileLibraryTest extends LibraryKernelTestBase {
     }
 
     $this->assertFalse(function_exists($function_name));
-    $this->externalLibraryManager->load('test_php_file_library');
+    $this->libraryManager->load('test_php_file_library');
     $this->assertTrue(function_exists($function_name));
   }
 
diff --git a/tests/src/Kernel/LibraryKernelTestBase.php b/tests/src/Kernel/LibraryKernelTestBase.php
deleted file mode 100644
index 6b5cc968229ea119eb84cf27a7e9dcc8d1294908..0000000000000000000000000000000000000000
--- a/tests/src/Kernel/LibraryKernelTestBase.php
+++ /dev/null
@@ -1,46 +0,0 @@
-<?php
-
-namespace Drupal\Tests\libraries\Kernel;
-
-use Drupal\KernelTests\KernelTestBase;
-
-/**
- * Provides an improved version of the core kernel test base class.
- */
-abstract class LibraryKernelTestBase extends KernelTestBase {
-
-  /**
-   * The external library registry.
-   *
-   * @var \Drupal\libraries\ExternalLibrary\Registry\LibraryRegistryInterface
-   */
-  protected $externalLibraryRegistry;
-
-  /**
-   * The absolute path to the Libraries API module.
-   *
-   * @var string
-   */
-  protected $modulePath;
-
-  /**
-   * {@inheritdoc}
-   */
-  protected function setUp() {
-    parent::setUp();
-
-    $this->externalLibraryRegistry = $this->container->get('libraries.registry');
-
-    /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
-    $module_handler = $this->container->get('module_handler');
-    $this->modulePath = $module_handler->getModule('libraries')->getPath();
-
-    $this->installConfig('libraries');
-    /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */
-    $config_factory = $this->container->get('config.factory');
-    $config_factory->getEditable('libraries.settings')
-      ->set('library_definitions.local.path', "{$this->modulePath}/tests/library_definitions")
-      ->save();
-  }
-
-}
diff --git a/tests/src/Kernel/LibraryTypeKernelTestBase.php b/tests/src/Kernel/LibraryTypeKernelTestBase.php
new file mode 100644
index 0000000000000000000000000000000000000000..c0ccaf96f0d8d97186e810bf082aeb60f19b474b
--- /dev/null
+++ b/tests/src/Kernel/LibraryTypeKernelTestBase.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace Drupal\Tests\libraries\Kernel;
+
+use Drupal\Component\Plugin\Exception\PluginException;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\libraries\ExternalLibrary\Exception\LibraryDefinitionNotFoundException;
+use Drupal\libraries\ExternalLibrary\Exception\LibraryTypeNotFoundException;
+use Drupal\libraries\ExternalLibrary\LibraryInterface;
+use Drupal\libraries\ExternalLibrary\LibraryType\LibraryTypeInterface;
+
+/**
+ * Provides an improved version of the core kernel test base class.
+ */
+abstract class LibraryTypeKernelTestBase extends KernelTestBase {
+
+  /**
+   * The external library manager.
+   *
+   * @var \Drupal\libraries\ExternalLibrary\LibraryManagerInterface
+   */
+  protected $libraryManager;
+
+  /**
+   * The library type factory.
+   *
+   * @var \Drupal\Component\Plugin\Factory\FactoryInterface
+   */
+  protected $libraryTypeFactory;
+
+  /**
+   * The absolute path to the Libraries API module.
+   *
+   * @var string
+   */
+  protected $modulePath;
+
+  abstract protected function getLibraryTypeId();
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->libraryManager = $this->container->get('libraries.manager');
+    $this->libraryTypeFactory = $this->container->get('plugin.manager.libraries.library_type');
+
+    /** @var \Drupal\Core\Extension\ModuleHandlerInterface $module_handler */
+    $module_handler = $this->container->get('module_handler');
+    $this->modulePath = $module_handler->getModule('libraries')->getPath();
+
+    $this->installConfig('libraries');
+    /** @var \Drupal\Core\Config\ConfigFactoryInterface $config_factory */
+    $config_factory = $this->container->get('config.factory');
+    $config_factory->getEditable('libraries.settings')
+      ->set('library_definitions.local.path', "{$this->modulePath}/tests/library_definitions")
+      ->save();
+  }
+
+  /**
+   * Tests that the library type can be instantiated.
+   */
+  public function testLibraryType() {
+    $type_id = $this->getLibraryTypeId();
+    try {
+      $this->libraryTypeFactory->createInstance($type_id);
+      $this->assertTrue(TRUE, "Library type '$type_id' can be instantiated.");
+    }
+    catch (PluginException $exception) {
+      $this->fail("Library type '$type_id' cannot be instantiated.");
+    }
+  }
+
+  /**
+   * Tests that the test library can be instantiated.
+   */
+  public function testLibrary() {
+    $type_id = $this->getLibraryTypeId();
+    $id = $this->getLibraryId();
+    try {
+      $library = $this->libraryManager->getLibrary($id);
+      $this->assertTrue(TRUE, "Test $type_id library can be instantiated.");
+      $this->assertInstanceOf($this->getLibraryType()->getLibraryClass(), $library);
+      $this->assertEquals($this->getLibraryId(), $library->getId());
+
+    }
+    catch (LibraryDefinitionNotFoundException $exception) {
+      $this->fail();
+      $this->fail("Missing library definition for test $type_id library.");
+    }
+    catch (LibraryTypeNotFoundException $exception) {
+      $this->fail();
+      $this->fail("Missing library type declaration for test $type_id library.");
+    }
+  }
+
+  /**
+   * @return \Drupal\libraries\ExternalLibrary\LibraryType\LibraryTypeInterface
+   */
+  protected function getLibraryType() {
+    try {
+      $library_type = $this->libraryTypeFactory->createInstance($this->getLibraryTypeId());
+    }
+    catch (PluginException $exception) {
+      $library_type = $this->prophesize(LibraryTypeInterface::class)->reveal();
+    }
+    finally {
+      return $library_type;
+    }
+  }
+
+  /**
+   * @return \Drupal\libraries\ExternalLibrary\LibraryInterface
+   */
+  protected function getLibrary() {
+    try {
+      $library = $this->libraryManager->getLibrary($this->getLibraryId());
+    }
+    catch (LibraryDefinitionNotFoundException $exception) {
+      $library = $this->prophesize(LibraryInterface::class)->reveal();
+    }
+    catch (LibraryTypeNotFoundException $exception) {
+      $library = $this->prophesize(LibraryInterface::class)->reveal();
+    }
+    catch (PluginException $exception) {
+      $library = $this->prophesize(LibraryInterface::class)->reveal();
+    }
+    finally {
+      return $library;
+    }
+  }
+
+  /**
+   * @param $type_id
+   * @return string
+   */
+  protected function getLibraryId() {
+    $type_id = $this->getLibraryTypeId();
+    return "test_{$type_id}_library";
+  }
+
+}