Conversation
Move templates and theme CSS into themes/default/ directory structure,
making it possible to create alternate themes by adding new theme
folders and switching via the "theme" setting.
Structure:
themes/{name}/templates/*.html - Template files
themes/{name}/static/ - Theme CSS/assets served at /theme/
Changes:
- Move all templates from templates/ to themes/default/templates/
- Move goblog.css from www/css/ to themes/default/static/css/
- Load templates from themes/{active_theme}/templates/ based on
the "theme" setting (defaults to "default")
- Serve theme static files at /theme/ path
- Extract duplicated admin nav into shared admin_nav.html partial
(was copy-pasted across 9 admin templates with different active
states). Active link now highlighted via JS based on current URL.
- Add "theme" setting to seed defaults
Closes #481
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR introduces a theme-based template/static loading mechanism (with a new default theme) and adds a set of new HTML templates for the blog, admin UI, and install wizard flows.
Changes:
- Add a
themesetting and load templates/static assets fromthemes/<theme>/...(defaulting todefault). - Introduce the
themes/defaulttheme (templates + CSS) including install wizard pages and multiple blog/admin pages. - Refactor admin navigation into a shared
admin_nav.htmlinclude.
Reviewed changes
Copilot reviewed 15 out of 41 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/migrate.go | Seeds a new default theme setting (default). |
| goblog.go | Loads templates from the active theme directory and serves theme static assets under /theme/. |
| blog/blog_test.go | Updates test template glob path to the new default theme templates. |
| admin/admin_test.go | Updates test template glob path to the new default theme templates. |
| themes/default/static/css/goblog.css | Adds theme-specific CSS (now served via /theme/css/goblog.css). |
| themes/default/templates/header.html | Updates stylesheet path to /theme/css/goblog.css. |
| themes/default/templates/footer.html | Adds new footer layout and “Most Recent Post” section. |
| themes/default/templates/admin_nav.html | New shared admin navigation partial + active link script. |
| themes/default/templates/admin.html | Switches to using admin_nav.html. |
| themes/default/templates/admin_all_posts.html | Switches to using admin_nav.html. |
| themes/default/templates/admin_dashboard.html | Switches to using admin_nav.html. |
| themes/default/templates/admin_new_post.html | Switches to using admin_nav.html. |
| themes/default/templates/admin_pages.html | Switches to using admin_nav.html. |
| themes/default/templates/admin_edit_page.html | Switches to using admin_nav.html. |
| themes/default/templates/admin_post_types.html | Switches to using admin_nav.html. |
| themes/default/templates/admin_edit_post_type.html | Switches to using admin_nav.html. |
| themes/default/templates/admin_settings.html | Switches to using admin_nav.html. |
| themes/default/templates/wizard_db.html | New DB setup wizard page with AJAX “test DB”. |
| themes/default/templates/wizard_settings.html | New settings wizard page that posts settings via JS. |
| themes/default/templates/wizard_auth.html | New GitHub OAuth wizard page for client id/secret. |
| themes/default/templates/wizard_success.html | New wizard completion page with timed redirect. |
| themes/default/templates/home.html | New home/landing page template. |
| themes/default/templates/login.html | New login page template with GitHub OAuth flow script. |
| themes/default/templates/post.html | New post view template with markdown rendering + comments UI. |
| themes/default/templates/post-admin.html | New post admin editor template with preview + revisions. |
| themes/default/templates/posts.html | New posts listing template. |
| themes/default/templates/search.html | New search page template and results listing. |
| themes/default/templates/tags.html | New tags index template. |
| themes/default/templates/tag.html | New single-tag listing template. |
| themes/default/templates/archives.html | New archives index template. |
| themes/default/templates/page_archives.html | New archives page template variant using year/month groupings. |
| themes/default/templates/page_content.html | New generic “page markdown content” renderer template. |
| themes/default/templates/page_research.html | New research page template variant. |
| themes/default/templates/page_tags.html | New tags page template variant. |
| themes/default/templates/page_writing.html | New writing page template listing posts. |
| themes/default/templates/post_type_listing.html | New post-type listing template. |
| themes/default/templates/research.html | New research/publications template. |
| themes/default/templates/projects.html | New projects page template (video hero + placeholder text). |
| themes/default/templates/presentations.html | New presentations/speaking template (placeholder text). |
| themes/default/templates/about.html | New about page template content. |
| themes/default/templates/error.html | New error page template. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
A clean, modern theme with visual differences from the default: - Inter sans-serif font instead of Source Code Pro monospace - Blue accent color (#2563eb) instead of gray - Rounded corners on inputs and buttons - Simplified home page layout - Streamlined footer with narrower content width - Slate-colored footer bar instead of dark gray To test: set the "theme" setting to "minimal" and restart. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Scan themes/ directory for available themes and display as a dropdown in admin settings instead of a text input - Hot-reload templates when theme setting changes via OnThemeChange callback — no server restart required - Serve theme static files dynamically based on active theme so CSS switches immediately too - Handle <select> elements in settings JS to preserve "text" type Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Header: horizontal nav bar with site name as text (not logo box), blue accent border, flexbox layout instead of centered float - Posts listing: narrower content column (720px), article cards with bottom borders, long-form date format, no video hero - Single post: narrower column, larger h1 title, horizontal rule separator, increased line-height for readability - Footer: subtle top border, narrower "Latest" section, short date Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Landing page: - Squared profile image (not circle) with side-by-side name layout - Two-column layout: recent posts list + tag cloud - No socials on landing page (moved to footer only) Header: - Light gray background bar with 1px border (no logo box) - Site initials as text link, nav links inline, search on the right Pages: - No hero images/videos — clean text-only layouts - Narrower 720px content column throughout Footer: - Light gray background with socials + powered-by in a row - No "Most Recent Post" section (landing page handles this) Also fix hardcoded "Software Engineer" title in Home handler — now uses site_subtitle setting. Pass recent_posts and tags to home template so themes can use them. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add getTopTags(n) that sorts tags by number of associated posts (most popular first) and limits to n. The home page now shows the 20 most-used tags instead of all tags. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ath traversal Minimal theme login: - Clean centered card with "Sign In" heading and "Continue with GitHub" button instead of circle photo + social button - Uses site_title setting in the description text Default theme login: - Replace hardcoded img/jason.jpg with landing_page_image setting - Replace hardcoded "Jason Ernst" alt text with site_title setting Security: - Sanitize theme static file path with filepath.Clean and filepath.Join to prevent path traversal via ../ Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…atching - Guard GetSettings() call with IsDbNil() check so the server can start before DB is configured (install wizard flow) - Validate theme names: only allow alphanumeric/hyphens/underscores, verify the theme directory exists on disk before loading - Fall back to default theme with a warning if the configured theme is invalid or fails to parse - Admin nav now highlights parent sections for nested pages (e.g. /admin/pages/123 highlights the Pages tab) using prefix matching, with dashboard excluded to avoid false matches Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces a WordPress-style theme system. Templates and theme-specific CSS now live in
themes/{name}/directories, and the active theme is configurable via thethemeadmin setting.Directory structure
How to create a new theme
themes/default/tothemes/my-theme/themesetting tomy-themein admin settingsChanges
templates/→themes/default/templates/www/css/goblog.css→themes/default/static/css/goblog.cssthemes/{active_theme}/templates/based on thethemesetting/theme/URL pathadmin_nav.htmlpartial — was copy-pasted across 9 admin templates with hardcoded active states. Now uses JS to highlight the active link based on the current URL.themesetting to seed defaults (value:"default")What stays in
www/General static assets that aren't theme-specific: favicon, images, uploads,
admin-script.js, site.webmanifest, etc.Closes #481
Test plan
themes/default//theme/css/goblog.cssthemes/default/tothemes/custom/, change something, settheme=custom— custom theme loads🤖 Generated with Claude Code