Add Pagefind search, local server, move pages_dir to config
Pagefind indexes episode pages for full-text search. Local
server via rake serve uses Puma directly.
Assisted-by: Claude Opus 4.6 via pi
diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 5b2e264..069804a 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -26,6 +26,9 @@ jobs:
with:
bundler-cache: true
+ - name: Install uv
+ uses: astral-sh/setup-uv@v5
+
- name: Generate pages
run: bundle exec rake pages
diff --git a/Gemfile b/Gemfile
index 105965a..e385e9f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,4 +1,5 @@
source "https://rubygems.org"
gem "nokogiri"
+gem "puma"
gem "rake"
diff --git a/Gemfile.lock b/Gemfile.lock
index 186f700..fec29e6 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -1,6 +1,7 @@
GEM
remote: https://rubygems.org/
specs:
+ nio4r (2.7.5)
nokogiri (1.19.2-aarch64-linux-gnu)
racc (~> 1.4)
nokogiri (1.19.2-aarch64-linux-musl)
@@ -17,6 +18,8 @@ GEM
racc (~> 1.4)
nokogiri (1.19.2-x86_64-linux-musl)
racc (~> 1.4)
+ puma (7.2.0)
+ nio4r (~> 2.0)
racc (1.8.1)
rake (13.3.1)
@@ -32,7 +35,8 @@ PLATFORMS
DEPENDENCIES
nokogiri
+ puma
rake
BUNDLED WITH
- 4.0.9
+ 4.0.9
diff --git a/Rakefile b/Rakefile
index 374be99..9ba69b1 100644
--- a/Rakefile
+++ b/Rakefile
@@ -123,8 +123,6 @@ task :retranscribe, [:number] do |_t, args|
Rake::Task[et.text_path].invoke
end
-PAGES_DIR = Pathname("pages")
-
desc "Generate HTML transcript pages"
task :pages do
require "cgi"
@@ -145,15 +143,39 @@ task :pages do
}
end
- PAGES_DIR.mkpath
+ CONFIG.pages_dir.mkpath
transcripts.each do |ep|
html = episode_template.result(binding)
- (PAGES_DIR / "#{ep[:slug]}.html").write(html)
+ (CONFIG.pages_dir / "#{ep[:slug]}.html").write(html)
end
html = index_template.result(binding)
- (PAGES_DIR / "index.html").write(html)
+ (CONFIG.pages_dir / "index.html").write(html)
puts "Generated #{transcripts.length} episode pages + index."
+
+ sh "uv", "run", "--with", "pagefind[bin]", "python3", "-m", "pagefind", "--site", CONFIG.pages_dir.to_s
+end
+
+desc "Serve the generated pages locally"
+task serve: :pages do
+ require "puma"
+ require "puma/configuration"
+ require "puma/launcher"
+ require "rack/files"
+
+ files = Rack::Files.new(CONFIG.pages_dir.to_s)
+ app = ->(env) do
+ env["PATH_INFO"] = "/index.html" if env["PATH_INFO"] == "/"
+ files.call(env)
+ end
+ config = Puma::Configuration.new do |c|
+ c.port 8000
+ c.app app
+ c.log_requests
+ end
+
+ puts "Serving #{CONFIG.pages_dir} at http://localhost:8000"
+ Puma::Launcher.new(config).run
end
diff --git a/lib/config.rb b/lib/config.rb
index b9e110e..ed7658d 100644
--- a/lib/config.rb
+++ b/lib/config.rb
@@ -5,6 +5,7 @@ module CookingIssues
:cache_dir,
:audio_dir,
:transcripts_dir,
+ :pages_dir,
:hrn_feed_path,
:hrn_feed_url,
:acast_feed_path,
@@ -22,6 +23,7 @@ module CookingIssues
cache_dir: cache_dir,
audio_dir: cache_dir / "audio",
transcripts_dir: Pathname("transcripts"),
+ pages_dir: Pathname("pages"),
hrn_feed_path: cache_dir / "hrn_feed.xml",
hrn_feed_url: "https://rss.art19.com/cooking-issues",
acast_feed_path: cache_dir / "acast_feed.xml",
diff --git a/lib/pages/index.html.erb b/lib/pages/index.html.erb
index bc0f578..21819f1 100644
--- a/lib/pages/index.html.erb
+++ b/lib/pages/index.html.erb
@@ -4,10 +4,12 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Cooking Issues Transcripts</title>
+<link href="pagefind/pagefind-ui.css" rel="stylesheet">
<style>
* { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: system-ui, sans-serif; line-height: 1.6; color: #222; max-width: 50rem; margin: 0 auto; padding: 1rem; }
h1 { margin-bottom: 1rem; }
+ #search { margin-bottom: 1.5rem; }
ul { list-style: none; }
li { padding: 0.4rem 0; border-bottom: 1px solid #eee; }
a { color: #0066cc; text-decoration: none; }
@@ -17,6 +19,9 @@
<body>
<h1>Cooking Issues Transcripts</h1>
+
+<div id="search"></div>
+
<p><%= transcripts.length %> episodes</p>
<ul>
@@ -25,5 +30,12 @@
<% end %>
</ul>
+<script src="/pagefind/pagefind-ui.js"></script>
+<script>
+ window.addEventListener('DOMContentLoaded', (event) => {
+ new PagefindUI({ element: "#search", showSubResults: true });
+ });
+</script>
+
</body>
</html>