diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3a8f6cb080013e40fd61279e6be21b24b08fbb39..e9530261221d1863318d1f0574f6592b8aae4001 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -24,29 +24,42 @@ before_script:
   - composer global require automattic/vipwpcs
   - phpcs --config-set installed_paths $HOME/.composer/vendor/wp-coding-standards/wpcs,$HOME/.composer/vendor/automattic/vipwpcs
 
-test_7.0:
+PHPunit:PHP5.3:MySQL:
+  image: containers.ethitter.com:443/docker/images/php:5.3
+  services:
+    - mysql:5.6
+  script:
+    - phpcs -n
+    - phpunit
+
+PHPunit:PHP5.6:MySQL:
+  image: containers.ethitter.com:443/docker/images/php:5.6
+  services:
+    - mysql:5.6
+  script:
+    - phpcs -n
+    - phpunit
+
+PHPunit:PHP7.0:MySQL:
   image: containers.ethitter.com:443/docker/images/php:7.0
   services:
     - mysql:5.6
   script:
-    - find . -type "f" -iname "*.php" | xargs -L "1" php -l
     - phpcs -n
     - phpunit
 
-test_7.1:
+PHPunit:PHP7.1:MySQL:
   image: containers.ethitter.com:443/docker/images/php:7.1
   services:
     - mysql:5.6
   script:
-    - find . -type "f" -iname "*.php" | xargs -L "1" php -l
     - phpcs -n
     - phpunit
 
-test_7.2:
+PHPunit:PHP7.2:MySQL:
   image: containers.ethitter.com:443/docker/images/php:7.2
   services:
     - mysql:5.6
   script:
-    - find . -type "f" -iname "*.php" | xargs -L "1" php -l
     - phpcs -n
     - phpunit
diff --git a/README.md b/README.md
index fa835b3b4d9705de32fcf155e1a12d81ee2ee2c8..c19e0354724a3aa3f46a3a19d7256abb68012ef7 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,6 @@
 **Donate link:** https://ethitter.com/donate/  
 **Tags:** image, proxy, cdn  
 **Requires at least:** 4.9  
-**Requires PHP:** 7.0  
 **Tested up to:** 4.9  
 **Stable tag:** 0.1.0  
 **License:** GPLv2 or later  
diff --git a/camo-image-proxy.php b/camo-image-proxy.php
index 9ed3d6e82970288e689fb4688c5ea76568ee3433..1c407ca4b6eaf7dc68e0ad0c029719869946afbd 100755
--- a/camo-image-proxy.php
+++ b/camo-image-proxy.php
@@ -13,58 +13,3 @@
  */
 
 namespace Camo_Image_Proxy;
-
-const PLUGIN_PATH = __DIR__;
-
-/**
- * Trait for singletons
- */
-require_once PLUGIN_PATH . '/inc/trait-singleton.php';
-
-/**
- * Plugin options
- */
-require_once PLUGIN_PATH . '/inc/class-options.php';
-
-/**
- * Options page
- */
-require_once PLUGIN_PATH . '/inc/class-options-page.php';
-
-/**
- * URL Building
- */
-require_once PLUGIN_PATH . '/inc/class-url.php';
-
-/**
- * Rewrite WordPress-generated URLs
- */
-require_once PLUGIN_PATH . '/inc/class-rewrite-urls.php';
-
-/**
- * Rewrite URLs in post content
- */
-require_once PLUGIN_PATH . '/inc/class-rewrite-content.php';
-
-/**
- * Assorted functions
- */
-require_once PLUGIN_PATH . '/inc/functions.php';
-
-/**
- * Load plugin singletons
- */
-function init() {
-	Options::instance();
-	URL::instance();
-
-	if ( is_admin() ) {
-		Options_Page::instance();
-	}
-
-	if ( URL::instance()->can_rewrite() ) {
-		Rewrite_URLs::instance();
-		Rewrite_Content::instance();
-	}
-}
-add_action( 'init', __NAMESPACE__ . '\init' );
diff --git a/inc/class-options-page.php b/inc/class-options-page.php
deleted file mode 100644
index 2e9540697b0a2be04cf06dbc1d68c149581a28cf..0000000000000000000000000000000000000000
--- a/inc/class-options-page.php
+++ /dev/null
@@ -1,86 +0,0 @@
-<?php
-/**
- * Plugin options page
- *
- * @package Camo_Image_Proxy
- */
-
-namespace Camo_Image_Proxy;
-
-/**
- * Class Options_Page
- */
-class Options_Page {
-	use Singleton;
-
-	/**
-	 * Settings screen section
-	 *
-	 * @var string
-	 */
-	private $section = 'camp-image-proxy';
-
-	/**
-	 * Field labels
-	 *
-	 * @var array
-	 */
-	private $labels = [];
-
-	/**
-	 * Option name
-	 *
-	 * @var string
-	 */
-	private $name;
-
-	/**
-	 * Hooks
-	 */
-	public function setup() {
-		$this->name = Options::instance()->name;
-
-		$this->labels['host'] = __( 'Host', 'camo-image-proxy' );
-		$this->labels['key']  = __( 'Shared Key', 'camo-image-proxy' );
-
-		add_action( 'admin_init', [ $this, 'action_admin_init' ] );
-	}
-
-	/**
-	 * Add fields to Media settings page
-	 */
-	public function action_admin_init() {
-		register_setting( 'media', $this->name, [ Options::instance(), 'sanitize_all' ] );
-		add_settings_section( $this->section, __( 'Camo Image Proxy', 'camo-image-proxy' ), '__return_false', 'media' );
-
-		foreach ( $this->labels as $key => $label ) {
-			$args = [
-				'option' => $key,
-				'label'  => $label,
-			];
-			add_settings_field( $key, $label, [ $this, 'screen' ], 'media', $this->section, $args );
-		}
-	}
-
-	/**
-	 * Render options field
-	 *
-	 * @param array $args Field arguments.
-	 */
-	public function screen( $args ) {
-		$value      = Options::instance()->get( $args['option'] );
-		$input_type = 'host' === $args['option'] ? 'url' : 'text';
-		$name       = sprintf( '%1$s[%2$s]', $this->name, $args['option'] );
-		$html_id    = sprintf( '%1$s-%2$s', str_replace( '_', '-', $this->name ), $args['option'] );
-
-		?>
-		<input
-			type="<?php echo esc_attr( $input_type ); ?>"
-			name="<?php echo esc_attr( $name ); ?>"
-			class="regular-text"
-			id="<?php echo esc_attr( $html_id ); ?>"
-			value="<?php echo esc_attr( $value ); ?>"
-		/>
-		<?php
-	}
-}
diff --git a/inc/class-options.php b/inc/class-options.php
deleted file mode 100644
index 888477643126d055e138888218cc3f497ffbf446..0000000000000000000000000000000000000000
--- a/inc/class-options.php
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-/**
- * Plugin options
- *
- * @package Camo_Image_Proxy
- */
-
-namespace Camo_Image_Proxy;
-
-/**
- * Class Options
- */
-class Options {
-	use Singleton;
-
-	/**
-	 * Option name
-	 *
-	 * @var string
-	 */
-	private $name = 'camo_image_proxy_opts';
-
-	/**
-	 * Allowed options
-	 *
-	 * @var array
-	 */
-	private $allowed_options = [
-		'host' => '',
-		'key'  => '',
-	];
-
-	/**
-	 * Access certain private properties
-	 *
-	 * @param string $name Property name.
-	 * @return mixed
-	 */
-	public function __get( string $name ) {
-		switch ( $name ) {
-			case 'name':
-				return $this->name;
-
-			default:
-				return new \WP_Error( 'invalid-property', __( 'Invalid property requested.', 'camo-image-proxy' ), $name );
-		}
-	}
-
-	/**
-	 * Retrieve full plugin options
-	 *
-	 * @return array
-	 */
-	private function get_all() : array {
-		$options = get_option( $this->name, [] );
-		$options = wp_parse_args( $options, $this->allowed_options );
-		return $options;
-	}
-
-	/**
-	 * Get plugin option
-	 *
-	 * @param string $option Plugin option to retrieve.
-	 * @return mixed
-	 */
-	public function get( string $option ) {
-		if ( ! array_key_exists( $option, $this->allowed_options ) ) {
-			return false;
-		}
-
-		$options = $this->get_all();
-		return $options[ $option ] ?? false;
-	}
-
-	/**
-	 * Set plugin option
-	 *
-	 * @param string $option Plugin option to set.
-	 * @param mixed  $value Option value.
-	 * @return bool
-	 */
-	public function set( string $option, $value ) : bool {
-		$value              = $this->sanitize( $option, $value );
-		$options            = $this->get_all();
-		$options[ $option ] = $value;
-
-		return update_option( $this->name, $options );
-	}
-
-	/**
-	 * Sanitize option
-	 *
-	 * @param string $option Plugin option.
-	 * @param mixed  $value Option value to sanitize.
-	 * @return mixed
-	 */
-	public function sanitize( string $option, $value ) {
-		switch ( $option ) {
-			case 'host':
-				$value = esc_url( $value );
-
-				if ( ! empty( $value ) ) {
-					$value = untrailingslashit( $value );
-				}
-
-				break;
-
-			case 'key':
-				$value = sanitize_text_field( $value );
-				break;
-
-			default:
-				return false;
-		}
-
-		return $value;
-	}
-
-	/**
-	 * Sanitize array of options
-	 *
-	 * @param array $options Options to sanitize.
-	 * @return array
-	 */
-	public function sanitize_all( array $options ) : array {
-		foreach ( $options as $option => $value ) {
-			$options[ $option ] = $this->sanitize( $option, $value );
-		}
-
-		return $options;
-	}
-}
diff --git a/inc/class-rewrite-content.php b/inc/class-rewrite-content.php
deleted file mode 100644
index ccf31a0a317a083ed6eeedb47785d6f1fd33fb78..0000000000000000000000000000000000000000
--- a/inc/class-rewrite-content.php
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-/**
- * Rewrite images in content
- *
- * @package Camo_Image_Proxy
- */
-
-namespace Camo_Image_Proxy;
-
-/**
- * Class Rewrite_Content
- */
-class Rewrite_Content {
-	use Singleton;
-
-	/**
-	 * Filter priority
-	 *
-	 * @var int
-	 */
-	private $priority;
-
-	/**
-	 * Hooks
-	 */
-	public function setup() {
-		$priority       = apply_filters( 'camo_image_proxy_rewrite_content_priority', PHP_INT_MAX - 1 );
-		$this->priority = absint( $priority );
-
-		add_filter( 'the_content', [ $this, 'filter_the_content' ], $this->priority );
-	}
-
-	/**
-	 * Rewrite image URLs in content
-	 *
-	 * @param string $content Post content.
-	 * @return string
-	 */
-	public function filter_the_content( string $content ) : string {
-		// TODO: only deal with image srcs, use DOM Document.
-		return $content;
-	}
-}
diff --git a/inc/class-rewrite-urls.php b/inc/class-rewrite-urls.php
deleted file mode 100644
index cd68b690bb0f07dc10f95e4201f315547181bfe2..0000000000000000000000000000000000000000
--- a/inc/class-rewrite-urls.php
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/**
- * Force Core's image functions to use Camo
- *
- * @package Camo_Image_Proxy
- */
-
-namespace Camo_Image_Proxy;
-
-/**
- * Class Rewrite_URLs
- */
-class Rewrite_URLs {
-	use Singleton;
-
-	/**
-	 * Hooks
-	 */
-	public function setup() {
-		add_filter( 'wp_get_attachment_image_src', [ $this, 'encode_image' ] );
-	}
-
-	/**
-	 * Camouflage attachment URL
-	 *
-	 * @param array $image Image data.
-	 * @return array
-	 */
-	public function encode_image( array $image ) : array {
-		$url = URL::instance()->encode( $image[0] );
-
-		if ( is_string( $url ) ) {
-			$image[0] = $url;
-		}
-
-		return $image;
-	}
-}
diff --git a/inc/class-url.php b/inc/class-url.php
deleted file mode 100644
index 33b4496143841e0b94eb78ba4d2b63035651c2bf..0000000000000000000000000000000000000000
--- a/inc/class-url.php
+++ /dev/null
@@ -1,93 +0,0 @@
-<?php
-/**
- * URL Building
- *
- * @package Camo_Image_Proxy
- */
-
-namespace Camo_Image_Proxy;
-
-/**
- * Class URL
- */
-class URL {
-	use Singleton;
-
-	/**
-	 * Can URLs be rewritten to use Camo?
-	 *
-	 * @return bool
-	 */
-	public function can_rewrite() : bool {
-		// Never rewrite in admin.
-		if ( is_admin() ) {
-			return false;
-		}
-
-		$host = Options::instance()->get( 'host' );
-		$key  = Options::instance()->get( 'key' );
-
-		$can_rewrite = true;
-
-		// Validate host.
-		if ( ! $this->is_valid_url( $host ) ) {
-			$can_rewrite = false;
-		}
-
-		// Validate key.
-		// TODO: make sure it's an HMAC or something?
-		if ( empty( $key ) || ! is_string( $key ) ) {
-			$can_rewrite = false;
-		}
-
-		return apply_filters( 'camo_image_proxy_can_rewrite', $can_rewrite, $host, $key );
-	}
-
-	/**
-	 * Encode image URL
-	 *
-	 * @param string $url Image URL to encode.
-	 * @return string|bool
-	 */
-	public function encode( string $url ) : string {
-		if ( ! $this->can_rewrite() || ! $this->is_valid_url( $url ) ) {
-			return false;
-		}
-
-		$key         = hash_hmac( 'sha1', $url, Options::instance()->get( 'key' ) );
-		$url_encoded = bin2hex( $url );
-
-		$url_encoded = sprintf( '%1$s/%2$s/%3$s', Options::instance()->get( 'host' ), $key, $url_encoded );
-		$url_encoded = set_url_scheme( $url_encoded, 'https' );
-
-		return $url_encoded;
-	}
-
-	/**
-	 * Decode encoded URL
-	 *
-	 * @param string $url Camo URL to decode.
-	 * @return string|bool
-	 */
-	public function decode( string $url ) : string {
-		return false;
-	}
-
-	/**
-	 * Can we encode this URL?
-	 *
-	 * @param string $url URL to validate.
-	 * @return bool
-	 */
-	private function is_valid_url( string $url ) : bool {
-		if ( empty( $url ) ) {
-			return false;
-		}
-
-		if ( false === filter_var( $url, FILTER_VALIDATE_URL ) && false === filter_var( $url, FILTER_VALIDATE_IP ) ) {
-			return false;
-		}
-
-		return true;
-	}
-}
diff --git a/inc/functions.php b/inc/functions.php
deleted file mode 100644
index 9fce3b24cf1505bbec4cf71f004f19bcb5f9fbc2..0000000000000000000000000000000000000000
--- a/inc/functions.php
+++ /dev/null
@@ -1,8 +0,0 @@
-<?php
-/**
- * Assorted helpers
- *
- * @package Camo_Image_Proxy
- */
-
-namespace Camo_Image_Proxy;
diff --git a/inc/trait-singleton.php b/inc/trait-singleton.php
deleted file mode 100644
index b890d8dea40792bc78dbf38c352bc4eaf030840d..0000000000000000000000000000000000000000
--- a/inc/trait-singleton.php
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/**
- * Trait file for Singletons.
- *
- * @package Camo_Image_Proxy
- */
-
-namespace Camo_Image_Proxy;
-
-/**
- * Make a class into a singleton.
- */
-trait Singleton {
-	/**
-	 * Existing instance.
-	 *
-	 * @var object
-	 */
-	protected static $instance;
-
-	/**
-	 * Get class instance.
-	 *
-	 * @return object
-	 */
-	public static function instance() {
-		if ( ! isset( static::$instance ) ) {
-			static::$instance = new static();
-			static::$instance->setup();
-		}
-		return static::$instance;
-	}
-
-	/**
-	 * Setup the singleton.
-	 */
-	public function setup() {
-		// Silence.
-	}
-}
diff --git a/languages/camo-image-proxy.pot b/languages/camo-image-proxy.pot
index 85a017c1f7a04dbb132fd2d8fe6faadf6df288c9..41db33f1d396c42e2424d5947384583cff1abf12 100644
--- a/languages/camo-image-proxy.pot
+++ b/languages/camo-image-proxy.pot
@@ -4,7 +4,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Camo Image Proxy 0.1.0\n"
 "Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/camo-image-proxy\n"
-"POT-Creation-Date: 2018-02-19 01:54:23+00:00\n"
+"POT-Creation-Date: 2018-02-18 19:07:54+00:00\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=utf-8\n"
 "Content-Transfer-Encoding: 8bit\n"
@@ -24,22 +24,10 @@ msgstr ""
 "X-Poedit-Bookmarks: \n"
 "X-Textdomain-Support: yes\n"
 
-#: inc/class-options-page.php:43
-msgid "Host"
-msgstr ""
-
-#: inc/class-options-page.php:44
-msgid "Shared Key"
-msgstr ""
-
 #. Plugin Name of the plugin/theme
 msgid "Camo Image Proxy"
 msgstr ""
 
-#: inc/class-options.php:45
-msgid "Invalid property requested."
-msgstr ""
-
 #. Plugin URI of the plugin/theme
 msgid "https://ethitter.com/plugins/"
 msgstr ""
diff --git a/readme.txt b/readme.txt
index 877751af577415030358442c66a82c49dfa14ed7..62370f4c382a6d0ebcb33b5ed03f44e478780698 100755
--- a/readme.txt
+++ b/readme.txt
@@ -3,7 +3,6 @@ Contributors: ethitter
 Donate link: https://ethitter.com/donate/
 Tags: image, proxy, cdn
 Requires at least: 4.9
-Requires PHP: 7.0
 Tested up to: 4.9
 Stable tag: 0.1.0
 License: GPLv2 or later