Migrating From Wagtail To Astro (6): Theme And Feature Polish
· 14 min read · Views --
Last updated on

Migrating From Wagtail To Astro (6): Theme And Feature Polish

Author: Alex Xiang


Migrating From Wagtail To Astro (6): Theme And Feature Polish

This is the sixth article in the Wagtail-to-Astro series. It covers the site polish done after migration: dark mode, site search, breadcrumbs, text contrast and accessibility, ICP record display, and footer information.

Dark Mode

Implementation Idea

  • Use CSS variables for light and dark themes. Define background, text, border, card, and related colors under :root and html.dark.
  • Put a theme toggle button in the Header. Clicking it adds or removes the dark class on <html>.
  • Persist the choice with localStorage, for example zicode-theme: dark | light. On page load, read the saved value first; if there is no saved choice, follow prefers-color-scheme: dark.

Details To Watch

  • Route all colors through CSS variables as much as possible. Avoid hard-coded colors, so theme switching only changes variables.
  • Images, borders, and shadows may need adjustment in dark mode to preserve contrast and readability.

Example variables:

:root {
  --bg: #ffffff;
  --text: #0f172a;
  --muted: #64748b;
}
html.dark {
  --bg: #0f172a;
  --text: #f1f5f9;
  --muted: #94a3b8;
}

The toggle can run document.documentElement.classList.toggle('dark', isDark) and then write isDark to localStorage, so the next page load applies the same theme before the user sees the page.

  • Generate a search index at build time. It can include each post’s title, description, slug, category, and tags, and expose them through JSON such as /search-index.json.
  • Put a search entry in the Header, either an icon or Ctrl/Cmd+K. When opened, the dialog fetches the JSON, filters it in memory, and shows post titles and links.

Experience Details

  • Add input debounce, highlighted results, keyboard navigation, and Esc to close if needed.
  • This approach does not depend on a third-party service, so it works well for a pure static site.

The index can be generated in Astro with src/pages/search-index.json.ts: call getCollection('blog') at build time, serialize title, description, slug, tags, and related fields, and let the frontend fetch that route.

  • Breadcrumbs: Above the main content, show something like “Home > Posts > Category/Column > Current post”. A component can receive items: { label, href? }[]; the current page has no href.
  • Top navigation: Keep entries such as Home, Categories, Columns, Posts, and About, matching the previous information architecture so existing readers do not feel lost.

Contrast And Accessibility

  • Text and background: Use colors with enough contrast for body text, headings, and secondary text. For example, #0f172a and #475569 on light backgrounds, #f1f5f9 and #94a3b8 on dark backgrounds.
  • Links and buttons: Default, hover, and focus states should be visibly different. Do not remove focus rings.
  • Images: Hero images and article images should have useful alt text when possible. Decorative images can use alt="".
  • In dark mode, cards, navigation, footer, and tag pills should use the same variable system so the whole site stays readable and consistent.
  • Show the ICP record number in the Footer and link it to the official MIIT site, such as https://beian.miit.gov.cn/, when the site is hosted in mainland China.
  • Keep copyright and site description in the footer, using a style consistent with the rest of the site.

Series Summary

This six-part series covers the full path from migration motivation and technology choice, through migration phases, adding new posts, and deployment, to data sync scripts and theme polish. It can serve as a reference for moving a traditional CMS site to a static site. If you are considering a similar migration, the steps can be trimmed or extended based on your own site.

Suggested order: finish content migration and deployment first, corresponding to parts 1 through 4, then add sync scripts and theme features, corresponding to parts 5 and 6. That way, even if automation is not complete yet, the manually imported content can serve readers first, and the workflow can be improved later.

Series: Part 1: Why migrate and how I chose · Part 2: The main phases · Part 3: Adding new posts · Part 4: Deployment · Part 5: Data sync and scripting · Part 6: Theme and feature polish