# 3. Customise the Source theme **Goal:** make the Source theme look like *your* blog — branding, navigation, typography, layout — without breaking the build. This tutorial covers the day-one customisations that 90% of users want. For the full helper reference, partial system, and asset pipeline details, read [`docs/THEME_DEV.md`](../THEME_DEV.md) afterwards. You should already have a Laurel site that builds and serves locally. If not, do [Tutorial 1 — Start a blog from scratch](./01-start-a-blog.md) first. --- ## The customisation surfaces, in order of effort | Surface | What it does | | ---------------------------------- | -------------------------------------------------- | | `[site]` / `[[navigation]]` | Title, logo, accent colour, nav links | | `[theme.custom]` | Theme-specific switches (Source reads ~20 keys) | | `content/images/` | Logo, favicon, OG fallback | | Theme partials (`themes/source/partials/`) | Header/footer markup, post cards, icons | | Theme `.hbs` layouts | Whole-page structure (`default.hbs`, `post.hbs`) | | Theme `assets/css/` | Styles | | `codeinjection_head` / per-post | Per-post script/style overrides | Reach for them in that order — most tweaks are a config change, not a code change. --- ## Step 1 — Set the brand basics in `laurel.toml` ```toml [site] title = "Daily Compiler" description = "Notes on language design, build tools, and runtime quirks." url = "https://daily-compiler.dev" locale = "en" timezone = "UTC" accent_color = "#005f73" # used by Source for links and accents logo = "/content/images/logo.svg" icon = "/content/images/favicon.png" cover_image = "/content/images/cover.jpg" twitter = "@dailycompiler" facebook = "dailycompiler" [[navigation]] label = "Home" url = "/" [[navigation]] label = "Archive" url = "/tag/archive/" [[navigation]] label = "About" url = "/about/" [[secondary_navigation]] label = "RSS" url = "/rss.xml" ``` Drop your logo, favicon, and cover image into `content/images/`. Anything under `content/images/` is copied to `dist/content/images/` and addressable as `/content/images/`. ## Step 2 — Use `[theme.custom]` for theme switches Ghost themes read theme-specific options from `@custom.*` in templates. Source has about 20 of them. Set them under `[theme.custom]`: ```toml [theme.custom] navigation_layout = "Logo on the left" # or "Logo in the middle", "Stacked" header_style = "Magazine" # or "Landing", "Highlight", "Off" header_text = "Reading and writing for the love of the craft." title_font = "Modern sans-serif" # or "Elegant serif" body_font = "Modern sans-serif" # or "Elegant serif" font_display = "swap" # or "optional" post_feed_style = "List" # or "Grid" show_featured_posts = true show_images_in_feed = true show_author = true show_publish_date = true show_post_metadata = true show_related_articles = true enable_drop_caps_on_posts = true background_image = true ``` The exact set is in Source's `package.json` `config.custom` block — that file is the source of truth for valid values. Mistyped keys are silently ignored (they just don't reach the template). `font_display = "swap"` is the Source default because it keeps text readable while web fonts load. Set `font_display = "optional"` only when avoiding late font swaps and preserving brand typography is more important than guaranteeing the custom font appears on slow or interrupted connections. ## Step 3 — Edit a partial to change a snippet Partials are the easiest entry into actual template editing. To change the footer: ```hbs {{!-- themes/source/partials/footer.hbs --}} ``` Edit, save, re-run `bunx laurel build`, refresh. Partials are loaded from `themes//partials/**` and addressable by their relative path without the extension, e.g. `{{> "footer"}}` or `{{> "components/header"}}`. ## Step 4 — Change a layout For structural changes (extra `` tags, a sidebar, a different post header), edit the layout `.hbs` files directly. The map for Source: | File | Renders | | ----------------- | ---------------------------------------- | | `default.hbs` | The wrapper for every page (`` shell) | | `index.hbs` | Home feed (paginated post list) | | `home.hbs` | Alias for index when `is:"home"` | | `post.hbs` | Individual post page | | `page.hbs` | Individual static page | | `tag.hbs` | `/tag//` | | `author.hbs` | `/author//` | | `error.hbs` | 404 (when present) | Inheritance uses `{{!< default}}` at the top of a layout file. The route table and full inheritance rules are in [`docs/THEME_DEV.md`](../THEME_DEV.md). ## Step 5 — Edit the CSS Source's CSS lives at `themes/source/assets/css/`. After editing, rebuild — `{{asset}}` recomputes the fingerprint so the browser pulls the new file: ```hbs ``` If Source ships pre-built CSS (`assets/built/screen.css`) and you'd rather work in the source files, run Source's own build step (`cd themes/source && yarn build`) — that pipeline is independent of Laurel. For one-off overrides, drop a `