Skip to main content

Technical Style Guide

This guide defines the technical standards, conventions, and deployment assumptions for the Literacy for Kids ecosystem.


Static-Site Architecture​

Every site in the ecosystem is a static Docusaurus v3 site deployed to GitHub Pages. No server-side rendering, no database, no user accounts, no login, no analytics.

This is a deliberate choice:

  • Zero infrastructure cost
  • No student data to protect
  • Anyone can fork and self-host
  • GitHub Pages provides free, reliable hosting for open-source projects

Do not introduce server-side code, edge functions, or backend services without an explicit discussion.


Repository Layout​

Hub (literacy_for_kids): Docusaurus at repo root

literacy_for_kids/
docs/ ← hub documentation (Markdown)
src/ ← React pages and components
static/ ← static assets (img/)
docusaurus.config.js
sidebars.js
package.json
.github/workflows/

Curriculum repos ({name}_literacy_for_kids): Docusaurus in /website

{curriculum}_literacy_for_kids/
website/
docs/ ← lesson content (Markdown)
src/ ← pages and components
static/ ← static assets
docusaurus.config.js
sidebars.js
package.json
.github/workflows/
README.md
LICENSE-CODE
LICENSE-CONTENT

Theme package (literacy_site_template): npm package only, no Docusaurus site

literacy_site_template/
src/
index.js ← Docusaurus plugin entry
css/custom.css ← shared CSS
data/ecosystemLinks.js ← single source of truth for all curriculum URLs
theme/ ← shared React components
package.json

GitHub Pages Deployment​

URL pattern​

Each site is served from its own custom (sub)domain:

https://{subdomain}.literacy-for-kids.com/

The hub uses https://www.literacy-for-kids.com/; each curriculum uses its topic subdomain (e.g. https://computer.literacy-for-kids.com/).

Required Docusaurus config​

url: 'https://{subdomain}.literacy-for-kids.com',
baseUrl: '/', // sites are served from the domain root
trailingSlash: true, // required for GitHub Pages static file routing

Why trailingSlash: true​

GitHub Pages serves static files. Without trailing slashes, navigating to /docs/intro returns a 404 because GitHub Pages looks for docs/intro.html. With trailingSlash: true, Docusaurus generates docs/intro/index.html, which GitHub Pages serves correctly at /docs/intro/.

Deployment workflow​

All sites deploy via GitHub Actions on push to main:

  1. actions/configure-pages — initialize Pages environment
  2. npm ci — install from lockfile
  3. npm run build — Docusaurus production build
  4. npm run validate:build (if present) — validate build output
  5. actions/upload-pages-artifact (path: build/ or ./website/build/)
  6. actions/deploy-pages

GitHub Pages source must be set to GitHub Actions in repository Settings › Pages.


Base Path Rules​

Every asset reference and internal link in the built output must use the base path. Docusaurus handles this automatically when baseUrl is set correctly. Do not hardcode paths.

Correct:

// In docusaurus.config.js
baseUrl: '/decision_literacy_for_kids/',

Incorrect:

baseUrl: '/', // root only — breaks project page deployment
baseUrl: '/docs/', // wrong path
baseUrl: '/decision-literacy/', // wrong separator

The validate:build script checks for root-relative paths that bypass the base path.


Package Manager​

Use npm with a lockfile (package-lock.json). Do not use yarn or pnpm unless a repo already uses them.

In CI, always use:

npm ci # for curriculum repos
npm ci --legacy-peer-deps # for the hub (React 19 + Docusaurus peer dep constraint)

Node Version​

Node 20 (LTS). Specified in:

  • package.json engines.node
  • GitHub Actions actions/setup-node with node-version: 20

Shared Theme Package​

The literacy-site-theme package (from literacy_site_template) is the single source of truth for:

  • All curriculum URLs and metadata (src/data/ecosystemLinks.js)
  • Shared CSS custom properties (src/css/custom.css)
  • Shared navigation and footer components

When adding a new curriculum: Update ecosystemLinks.js in literacy_site_template, bump the version, then update the literacy-site-theme dependency in every curriculum repo.

When a curriculum URL changes: Same process — update ecosystemLinks.js, bump version, update all repos.


Dependencies​

Keep the dependency list minimal. The core dependencies are:

  • @docusaurus/core and @docusaurus/preset-classic — the Docusaurus framework
  • react and react-dom — React
  • literacy-site-theme — the shared theme package

Do not add:

  • Analytics (Google Analytics, Plausible, etc.)
  • Login or auth packages
  • User data collection
  • Heavyweight UI frameworks (Material UI, Tailwind, etc.) — use the existing Docusaurus Infima CSS

For tooling, keep linting/formatting lightweight. A .editorconfig file is sufficient for cross-editor consistency. Do not add ESLint or Prettier unless the repo already uses them.


Build Validation​

Every repo should have npm run validate:build that checks the build output before deployment. See scripts/validate-build.mjs in the hub repo for the canonical implementation. Checks include:

  • Build directory and index.html exist
  • All referenced assets exist on disk
  • No root-relative paths that bypass the base path
  • No source-directory or localhost references
  • 404.html exists for SPA fallback

Formatting and Style​

.editorconfig applies across all repos:

  • 2-space indentation for JS, JSON, YAML, Markdown
  • LF line endings
  • UTF-8 encoding
  • Trim trailing whitespace
  • Final newline

JavaScript files use ES modules (import/export) for Docusaurus site code. The shared theme package uses CommonJS (require/module.exports) for compatibility with the createRequire pattern in Docusaurus configs.


Accessibility Technical Requirements​

  • HTML root element must have lang="en" (Docusaurus sets this automatically)
  • All images need alt text
  • Interactive elements must be keyboard-accessible
  • Navigation landmarks (<nav>, <main>, <footer>) must be present (Docusaurus provides these via Layout)
  • Do not use tabIndex > 0

See the Accessibility Notes doc for known issues.


What to Avoid​

PatternWhy to avoid
Hardcoded absolute URLs in sourceBreaks local development
Root-relative paths (/docs/...) without base pathBreaks GitHub Pages project-page routing
trailingSlash: falseCauses 404s on GitHub Pages
Inline <script> tags loading external resourcesPrivacy and CSP concerns
localStorage for user preferences that aren't clearedNot needed; keep it simple
fetch() calls to external APIsAdds latency and external dependencies
Server-side renderingBreaks static export
gh-pages branch deploymentUse GitHub Actions deployment instead