diff --git a/config/test.exs b/config/test.exs
index 86322de..f857fc1 100644
--- a/config/test.exs
+++ b/config/test.exs
@@ -29,3 +29,5 @@ config :phoenix, :plug_init_mode, :runtime
 # Enable helpful, but potentially expensive runtime checks
 config :phoenix_live_view,
   enable_expensive_runtime_checks: true
+
+config :phoenix_test, :endpoint, CMSWeb.Endpoint
diff --git a/lib/cms_web/components/layouts/app.html.heex b/lib/cms_web/components/layouts/app.html.heex
index 0fffe7f..3fbbe6f 100644
--- a/lib/cms_web/components/layouts/app.html.heex
+++ b/lib/cms_web/components/layouts/app.html.heex
@@ -1,6 +1,7 @@
 <div class="sticky top-0 z-50 flex flex-row bg-white justify-between py-1 md:mb-2 border-b border-gray-200">
   <div class="flex flex-col md:flex-row">
     <section class="flex flex-row gap-x-2 md:border-r border-gray-200 px-2">
+      <span>💜</span>
       <.a href={~p"/"} class="font-bold">sloanelybutsurely.com</.a>
       <nav>
         <ul class="flex flex-row gap-x-2">
diff --git a/mix.exs b/mix.exs
index 1a94067..7e8fc8e 100644
--- a/mix.exs
+++ b/mix.exs
@@ -55,7 +55,10 @@ defmodule CMS.MixProject do
       {:typed_struct, "~> 0.3.0"},
 
       # dev/test only
-      {:styler, "~> 1.4", only: [:dev, :test], runtime: false}
+      {:styler, "~> 1.4", only: [:dev, :test], runtime: false},
+      {:ex_machina, "~> 2.8.0", only: :test},
+      {:faker, "~> 0.18.0", only: [:dev, :test]},
+      {:phoenix_test, "~> 0.5.2", only: :test, runtime: false}
     ]
   end
 
diff --git a/mix.lock b/mix.lock
index c80adeb..b154bac 100644
--- a/mix.lock
+++ b/mix.lock
@@ -12,7 +12,9 @@
   "ecto_sql": {:hex, :ecto_sql, "3.12.1", "c0d0d60e85d9ff4631f12bafa454bc392ce8b9ec83531a412c12a0d415a3a4d0", [:mix], [{:db_connection, "~> 2.4.1 or ~> 2.5", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.12", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.7", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "aff5b958a899762c5f09028c847569f7dfb9cc9d63bdb8133bff8a5546de6bf5"},
   "elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
   "esbuild": {:hex, :esbuild, "0.9.0", "f043eeaca4932ca8e16e5429aebd90f7766f31ac160a25cbd9befe84f2bc068f", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "b415027f71d5ab57ef2be844b2a10d0c1b5a492d431727f43937adce22ba45ae"},
+  "ex_machina": {:hex, :ex_machina, "2.8.0", "a0e847b5712065055ec3255840e2c78ef9366634d62390839d4880483be38abe", [:mix], [{:ecto, "~> 2.2 or ~> 3.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_sql, "~> 3.0", [hex: :ecto_sql, repo: "hexpm", optional: true]}], "hexpm", "79fe1a9c64c0c1c1fab6c4fa5d871682cb90de5885320c187d117004627a7729"},
   "expo": {:hex, :expo, "1.1.0", "f7b9ed7fb5745ebe1eeedf3d6f29226c5dd52897ac67c0f8af62a07e661e5c75", [:mix], [], "hexpm", "fbadf93f4700fb44c331362177bdca9eeb8097e8b0ef525c9cc501cb9917c960"},
+  "faker": {:hex, :faker, "0.18.0", "943e479319a22ea4e8e39e8e076b81c02827d9302f3d32726c5bf82f430e6e14", [:mix], [], "hexpm", "bfbdd83958d78e2788e99ec9317c4816e651ad05e24cfd1196ce5db5b3e81797"},
   "file_system": {:hex, :file_system, "1.1.0", "08d232062284546c6c34426997dd7ef6ec9f8bbd090eb91780283c9016840e8f", [:mix], [], "hexpm", "bfcf81244f416871f2a2e15c1b515287faa5db9c6bcf290222206d120b3d43f6"},
   "floki": {:hex, :floki, "0.37.0", "b83e0280bbc6372f2a403b2848013650b16640cd2470aea6701f0632223d719e", [:mix], [], "hexpm", "516a0c15a69f78c47dc8e0b9b3724b29608aa6619379f91b1ffa47109b5d0dd3"},
   "gettext": {:hex, :gettext, "0.26.2", "5978aa7b21fada6deabf1f6341ddba50bc69c999e812211903b169799208f2a8", [:mix], [{:expo, "~> 0.5.1 or ~> 1.0", [hex: :expo, repo: "hexpm", optional: false]}], "hexpm", "aa978504bcf76511efdc22d580ba08e2279caab1066b76bb9aa81c4a1e0a32a5"},
@@ -33,6 +35,7 @@
   "phoenix_live_view": {:hex, :phoenix_live_view, "1.0.4", "327491b033e79db2f887b065c5a2993228449091883d74cfa1baa12f8c98d5eb", [:mix], [{:floki, "~> 0.36", [hex: :floki, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a9865316ddf8d78f382d63af278d20436b52d262b60239956817a61279514366"},
   "phoenix_pubsub": {:hex, :phoenix_pubsub, "2.1.3", "3168d78ba41835aecad272d5e8cd51aa87a7ac9eb836eabc42f6e57538e3731d", [:mix], [], "hexpm", "bba06bc1dcfd8cb086759f0edc94a8ba2bc8896d5331a1e2c2902bf8e36ee502"},
   "phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
+  "phoenix_test": {:hex, :phoenix_test, "0.5.2", "8c717080e36ca5700165da4dfa2f55b5d80643bcfc6d1f69f31368e4ca5cac43", [:mix], [{:floki, ">= 0.30.0", [hex: :floki, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, ">= 1.0.0", [hex: :mime, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.7.10", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.20 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}], "hexpm", "18fd19cc5d7239ecf74e24bb8f6ab7b2e9761134b23aa8982f8b425d5aa04fb3"},
   "plug": {:hex, :plug, "1.16.1", "40c74619c12f82736d2214557dedec2e9762029b2438d6d175c5074c933edc9d", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "a13ff6b9006b03d7e33874945b2755253841b238c34071ed85b0e86057f8cddc"},
   "plug_crypto": {:hex, :plug_crypto, "2.1.0", "f44309c2b06d249c27c8d3f65cfe08158ade08418cf540fd4f72d4d6863abb7b", [:mix], [], "hexpm", "131216a4b030b8f8ce0f26038bc4421ae60e4bb95c5cf5395e1421437824c4fa"},
   "postgrex": {:hex, :postgrex, "0.20.0", "363ed03ab4757f6bc47942eff7720640795eb557e1935951c1626f0d303a3aed", [:mix], [{:db_connection, "~> 2.1", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "d36ef8b36f323d29505314f704e21a1a038e2dc387c6409ee0cd24144e187c0f"},
diff --git a/test/cms_web/controllers/page_controller_test.exs b/test/cms_web/controllers/page_controller_test.exs
deleted file mode 100644
index 6eea161..0000000
--- a/test/cms_web/controllers/page_controller_test.exs
+++ /dev/null
@@ -1,8 +0,0 @@
-defmodule CMSWeb.PageControllerTest do
-  use CMSWeb.ConnCase
-
-  test "GET /", %{conn: conn} do
-    conn = get(conn, ~p"/")
-    assert html_response(conn, 200) =~ "Peace of mind from prototype to production"
-  end
-end
diff --git a/test/cms_web/controllers/post_controller_test.exs b/test/cms_web/controllers/post_controller_test.exs
new file mode 100644
index 0000000..89d1fc6
--- /dev/null
+++ b/test/cms_web/controllers/post_controller_test.exs
@@ -0,0 +1,16 @@
+defmodule CMSWeb.PostControllerTest do
+  use CMSWeb.ConnCase, async: true
+
+  import CMS.Factory
+
+  describe "GET /writing/:post_id" do
+    test "includes the title", %{conn: conn} do
+      post = insert(:post)
+
+      conn
+      |> visit(~p"/writing/#{post}")
+      |> assert_has("h1", text: post.title)
+      |> open_browser()
+    end
+  end
+end
diff --git a/test/support/conn_case.ex b/test/support/conn_case.ex
index 82631ca..64c56c1 100644
--- a/test/support/conn_case.ex
+++ b/test/support/conn_case.ex
@@ -23,7 +23,9 @@ defmodule CMSWeb.ConnCase do
 
       import CMSWeb.ConnCase
       import Phoenix.ConnTest
+      import PhoenixTest
       import Plug.Conn
+
       # The default endpoint for testing
       @endpoint CMSWeb.Endpoint
 
diff --git a/test/support/factory.ex b/test/support/factory.ex
new file mode 100644
index 0000000..c0c4b12
--- /dev/null
+++ b/test/support/factory.ex
@@ -0,0 +1,14 @@
+defmodule CMS.Factory do
+  @moduledoc false
+
+  use ExMachina.Ecto, repo: CMS.Repo
+
+  alias CMS.Posts.Post
+
+  def post_factory do
+    %Post{
+      title: Faker.Lorem.sentence(2..10),
+      body: Faker.Lorem.paragraph()
+    }
+  end
+end
diff --git a/test/test_helper.exs b/test/test_helper.exs
index dbebc90..d88c0b1 100644
--- a/test/test_helper.exs
+++ b/test/test_helper.exs
@@ -1,2 +1,4 @@
+{:ok, _} = Application.ensure_all_started(:ex_machina)
+Faker.start()
 ExUnit.start()
 Ecto.Adapters.SQL.Sandbox.mode(CMS.Repo, :manual)