diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..491f666
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/vendor/
+.idea/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..22c2e9b
--- /dev/null
+++ b/README.md
@@ -0,0 +1,30 @@
+# Template Plumbing
+
+This little tool gives you an easy way to organize your page (or custom post type) templates better. By "templates" I mean the templates you can select from the "Templates" dropdown in the editor.
+
+## Usage
+
+First, install the package:
+
+```bash
+composer require livy/plumbing-template
+```
+
+Then call the tool like this, somewhere where it'll be run early (i.e. `functions.php`):
+
+```php
+Livy\Plumbing\Templates\register_template_directory('custom-templates');
+```
+
+By default, the plugin assumes you're changing the template for the `page` post type, but you can specify _any_ post type by passing a second parameter:
+
+```php
+// Define templates for the `event` post type:
+Livy\Plumbing\Templates\register_template_directory('event-templates', 'event');
+```
+
+## Limitations
+
+The tool looks in your template directory (i.e. the result of `get_template_directory()`) when looking for the directory you specify. If will silently fail if it can't find the directory, or if you try to do something clever (i.e. `../../../usr/bin`) for your template path.
+
+Currently this tool can only point to a single directory per post type.
\ No newline at end of file
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..ea67030
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,18 @@
+{
+    "name": "livy/plumbing-templates",
+    "description": "Put your page (or custom post type) templates in better directories. Works with Sage!",
+    "license": "MIT",
+    "authors": [
+        {
+            "name": "Ben Martinez-Bateman",
+            "email": "ben@alwaysblank.org"
+        }
+    ],
+    "autoload": {
+      "files": ["src/functions.php"]
+    },
+    "require": {
+        "php": ">=7.0",
+        "symfony/finder": "^4.0"
+    }
+}
diff --git a/composer.lock b/composer.lock
new file mode 100644
index 0000000..8033ac9
--- /dev/null
+++ b/composer.lock
@@ -0,0 +1,69 @@
+{
+    "_readme": [
+        "This file locks the dependencies of your project to a known state",
+        "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
+        "This file is @generated automatically"
+    ],
+    "content-hash": "ab99e93e4579936158ab4fcfc17c9340",
+    "packages": [
+        {
+            "name": "symfony/finder",
+            "version": "v4.0.6",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/finder.git",
+                "reference": "44a796d2ecc2a16a5fc8f2956a34ee617934d55f"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/finder/zipball/44a796d2ecc2a16a5fc8f2956a34ee617934d55f",
+                "reference": "44a796d2ecc2a16a5fc8f2956a34ee617934d55f",
+                "shasum": ""
+            },
+            "require": {
+                "php": "^7.1.3"
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "4.0-dev"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Finder\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Symfony Finder Component",
+            "homepage": "https://symfony.com",
+            "time": "2018-03-05T18:28:26+00:00"
+        }
+    ],
+    "packages-dev": [],
+    "aliases": [],
+    "minimum-stability": "stable",
+    "stability-flags": [],
+    "prefer-stable": false,
+    "prefer-lowest": false,
+    "platform": {
+        "php": ">=7.0"
+    },
+    "platform-dev": []
+}
diff --git a/src/functions.php b/src/functions.php
new file mode 100644
index 0000000..e432e82
--- /dev/null
+++ b/src/functions.php
@@ -0,0 +1,85 @@
+<?php
+
+namespace Livy\Plumbing\Templates;
+
+use Symfony\Component\Finder\Finder;
+
+function register_template_directory(string $path, $post_type = 'page')
+{
+    add_filter("theme_{$post_type}_templates", function($templates) use ($path, $post_type) {
+        return array_merge($templates, set_template_directory($path, $post_type));
+    });
+}
+
+function set_template_directory(string $path, string $post_type = 'page')
+{
+    $checked_path = check_path_segment($path);
+    $full_path = realpath(get_wordpress_template_directory($post_type) . DIRECTORY_SEPARATOR . $checked_path) ?: '';
+
+    // Make sure you're not trying to go somewhere weird
+    if (0 !== strpos($full_path, get_wordpress_template_directory($post_type))) {
+        return [];
+    }
+
+    $templates = [];
+
+    if (is_dir($full_path)) {
+        $inline_identifier = get_inline_identifier($post_type);
+        $finder = new Finder();
+        $finder->files()->in($full_path)->name(get_file_extenstion($post_type));
+        foreach ($finder as $file) {
+
+            // Set $name so it'll be sure to have a value.
+            $name = false;
+
+            // Look in each file to find the name; leave as soon as we have it.
+            if ($opened_file = fopen($file->getRealPath(), 'r')) {
+                while (($line = fgets($opened_file)) !== false) {
+                    if (strpos($line, $inline_identifier)) {
+                        $name = trim(str_replace($inline_identifier, '', $line));
+                        break;
+                    }
+                }
+            }
+            fclose($opened_file);
+
+            // Only add to list if we have a viable $name.
+            if ($name) {
+                $templates[$checked_path . $file->getFilename()] = $name;
+            }
+
+            // Don't want to accidentally pass these to the next iteration.
+            unset($name, $opened_file);
+        }
+    }
+
+    return $templates;
+}
+
+/**
+ * @return string
+ */
+function get_wordpress_template_directory($post_type)
+{
+    return apply_filters('template-dir/theme-directory', get_template_directory(), $post_type);
+}
+
+function get_inline_identifier($post_type)
+{
+    return apply_filters('template-dir/inline-identifier', 'Template Name:', $post_type);
+}
+
+function get_file_extenstion($post_type)
+{
+    return apply_filters('template-dir/file-extension', '*.php', $post_type);
+}
+
+function check_path_segment(string $path)
+{
+    // Need a trailing slash.
+    $trailingslashed = trailingslashit($path);
+
+    // Don't want a leading slash.
+    $frontchecked = ltrim($trailingslashed, '\\/');
+    return $frontchecked;
+}
\ No newline at end of file