Brings in USWDS 3.x as SCSS rather than reimplementing design system components
astro-gov-starter — Astro Starter Template
By ctrimm
An Astro starter template for government service websites, with USWDS design system, accessibility defaults, bilingual routing, and CI quality gates built in.
Explore the design
Compare the page layouts and mobile experience. Open any screenshot for a closer look.
Actual screenshot captured by the server browser.
All pages & views 3
Screenshots show visual appearance; interactive behavior may differ.
What stands out
A quick read of the recorded project description.
Includes the required USA Banner and USA Identifier components on every page by default
Organizes skip navigation, landmarks, and focus management according to Section 508 / WCAG 2.1 AA
Bilingual routing for English (/) and Spanish (/es/), with one page file serving both languages
Pagefind static search, indexing dist/ after build and searching by language according to html lang
CI quality gates cover TypeScript, HTML, axe-core, Lighthouse, links, plain language, and USWDS compliance
Template Details
This is an Astro starter template for government public service websites; the repository is MIT licensed. The template brings the U.S. federal government design system USWDS 3.x directly in as SCSS rather than reimplementing component styles, and by default places the two required components, USA Banner and USA Identifier, on every page.
For accessibility, the template organizes page structure according to Section 508 / WCAG 2.1 AA, including skip navigation, landmark regions, and focus management; CI runs axe-core and Lighthouse checks. At the content level, it provides three Zod-typed content collections—Services, Announcements, and FAQs—with MDX support, and includes bilingual routing for English (/) and Spanish (/es/), so a single route file per page serves both languages. Site search uses Pagefind, indexing dist/ after build to generate a static index, searching by language according to each page's html lang, with no third-party requests.
The repository includes several local scripts: init-agency.mjs for one-time configuration of agency name, domain, and USA Identifier link; plain-language.mjs enforcing a Flesch-Kincaid average grade level ≤ 8 as a readability threshold; and compliance-check.mjs checking whether build output includes the banner, identifier, and skip navigation. Output is a pure static site, deployable to GitHub Pages, Cloud.gov Pages, Netlify, Vercel, or object storage.
Limitations to note: the contact form and eligibility screening pages are only accessibility scaffolds and by default submit to no backend; you must connect a service such as Formspree or API Gateway yourself. The README notes that GitHub Pages does not support custom HTTP response headers, so the security headers in public/_headers are ignored on that platform; you need to deploy to a host that supports response headers or set them at a fronting CDN. Search is only available in the production build after pnpm build; the development server has no index. The Astro version number and Node version requirements appearing in the README are the repository's own statements, and this introduction does not use them to judge production readiness.
Is it right for your project?
Use Cases
- Teams that need to build a government public service portal according to USWDS specifications
- Agency sites that need to provide both English and Spanish pages
- Projects that want static output deployed to GitHub Pages, Cloud.gov Pages, or object storage
- Sites that need continuous checks for accessibility, readability, and USWDS compliance in CI
Suitable For
- Front-end developers familiar with Astro and content collections who want to start from an existing scaffold
- Government project teams that need USWDS as the design foundation and want to avoid maintaining component styles themselves
- Site maintainers with bilingual or multilingual content needs who require per-language search
- Organizations that want to enforce accessibility and plain-language thresholds in the build process
Getting started & customization
Use these recorded setup notes alongside the repository instructions for your chosen version.
- 1
After running pnpm install, execute node scripts/init-agency.mjs to configure the agency name, domain, and USA Identifier link
- 2
The contact form and /apply/* screening pages do not submit by default; connect a backend service according to the TODO (M3) comments in the code
- 3
Search is only available in the production build after pnpm build; the development server has no index
- 4
GitHub Pages does not support custom response headers; the security headers in public/_headers require a host that supports response headers or a fronting CDN
- 5
Adding a language requires updating LOCALES in astro.config.mjs, the types and translation mappings in src/i18n/utils.ts, and the copy objects on each page
License & source material
Usage conditions & limitations
Free to use · keep license noticeThis entry covers the free version in the public repository under the MIT license; the free scope is that version's code and does not mean external services or third-party assets are free.
Must comply with when using
- You may use, modify, commercialize, and distribute this version's code for free.
- When distributing copies or substantial portions of the code, retain the original author's copyright notice and the full MIT license notice.
- The code is provided as is; warranties and limitations of liability are governed by the original license and applicable law.
Additional costs & items to verify
- Using this template requires Node.js 22.12 or later and pnpm 10 as the package manager.
- The contact form and eligibility screening pages are only accessibility scaffolds and by default submit no data to any backend; before launch you must connect a form service or backend yourself.
- Site search is only available in the production build after running pnpm build; the development server has no search index.
- When deployed to GitHub Pages, the security response headers in public/_headers are ignored; use a host that supports custom response headers or set them at a fronting CDN.
- The code is MIT licensed, but the seed content is separately licensed under CC0; the two licenses have different scopes and must be followed separately.
- The README mentions the Formspree form service; real submissions require configuring a service endpoint, and its usage quotas and fees must be checked separately.
- Demo images, fonts, icons, and other third-party assets must be checked against their respective licenses; the code's MIT license alone is not sufficient to judge them.
- External services such as domain, hosting, database, payment, or AI may incur separate charges.
View Original Text Basis
Permission is hereby granted, free of charge
Original License Text
Requires **Node.js 22.12 or newer** and **pnpm 10**.
Original README
The contact form (`/contact/`) and eligibility screeners (`/apply/*`) are **accessible scaffolding only** — they do not submit anywhere out of the box.
Original README
Search only works on a **production build** (`pnpm build && pnpm preview`); the dev server has no index.
Original README
GitHub Pages does **not** support custom HTTP response > headers, so the headers in `public/_headers` (clickjacking protection via > `frame-ancestors`, `X-Frame-Options`, HSTS, etc.) are silently ignored on > GitHub Pages.
Original README
https://github.com/ctrimm/astro-gov-starter/blob/main/LICENSEhttps://github.com/ctrimm/astro-gov-starter/blob/main/README.mdSeed content: CC0 — no rights reserved, free to adapt for any agency.
Original README
Compiled by DeepSeek based on repository license and README ·2026-10-03. Results only cover the materials read; dependencies, images, fonts, and subsequent term changes are subject to their respective original texts.
Project checks & description sources
Template Information
- Source platforms
- Astro Themes
- Documentation and maintenance reference score
- More documented · 87 / 100
- Technologies
- Astro
- Website type
- Starter
How this score is calculated
Our heuristic uses license records (up to 30), a demo link (12), a preview (10), stars (15), recorded maintenance (15), description completeness (8), feature records (5) and classification data (5). It is not a code, security or performance test, or a Google score. A link does not establish tested functionality.
What to verify for this project
- Repository update recorded
- 2026-08-23
- Screenshot last checked
- 2026-10-03
A demo link is listed. Check it with your own content and viewport sizes; its presence does not confirm that forms, authentication or payments work.
The catalog identifies Astro as the primary stack. Check the actual dependency manifest and lockfile for versions and hosting requirements. These notes use recorded metadata, not a code audit or a deployment test.
Use a selection guide →How this description was prepared
AI-assisted description based on catalog records and repository material. Repository authors are not automatically the reviewers of this description.
Review declaration: [email protected] · 2026-10-04
Inspect the recorded source material
SHA-256: 581f8b2660c995439e507137bd95de78fbde6c4adb08e43f16b205763090bfba
2026-10-03T13:43:38.409Z
Source file / repository# astro-gov-starter
> A production-ready [Astro 7](https://astro.build) starter template for government service websites.
[](https://github.com/ctrimm/astro-gov-starter/actions/workflows/ci.yml)
[](https://designsystem.digital.gov/)
[](./LICENSE)
[](https://github.com/ctrimm/astro-gov-starter/releases/latest)
**USWDS-native · Section 508 / WCAG 2.1 AA · i18n (en + es) · Zero client JS · Deploy anywhere**
---
<img width="2619" height="2157" alt="pretty_snap_2026_3_18_6_15" src="https://github.com/user-attachments/assets/f7c5085c-6fe2-4aac-9f37-a3eda91f597d" />
---
## Use this template
Requires **Node.js 22.12 or newer** and **pnpm 10**.
Click **"Use this template"** on GitHub to create your own repository, then run the setup wizard:
```bash
pnpm install
node scripts/init-agency.mjs # configure your agency name, domain, and identifier links
pnpm dev
```
Your site will be at `http://localhost:4321`.
### Pick a release
Every release line targets one major Astro version. Start from the newest line
for the Astro version you want to build on:
| Starter release | Astro | Node | Notes |
|---|---|---|---|
| [`v3.x`](https://github.com/ctrimm/astro-gov-starter/releases/latest) | Astro 7 | ≥ 22.12 | **Current** — bilingual seed content, translatable collections |
| [`v2.x`](https://github.com/ctrimm/astro-gov-starter/releases/tag/v2.1.0) | Astro 7 | ≥ 22.12 | Superseded by v3.x; English-only seed content |
| [`v1.x`](https://github.com/ctrimm/astro-gov-starter/releases/tag/v1.0.0) | Astro 6 | ≥ 18.17.1 | Maintenance only |
Two lines target Astro 7 because v3.0.0 made a breaking change of its own — see
[Upgrading from 2.x](./CHANGELOG.md#upgrading-from-2x). New projects should start
from `v3.x`.
```bash
# start from a specific release instead of the default branch
git clone --branch v3.0.0 --depth 1 https://github.com/ctrimm/astro-gov-starter.git
```
See [CHANGELOG.md](./CHANGELOG.md) for what changed in each release, and
[RELEASING.md](./RELEASING.md) for how releases are cut.
---
## What's included
| Category | Details |
|---|---|
| **Design system** | [USWDS 3.x](https://designsystem.digital.gov/) via SCSS — no reimplementation |
| **Accessibility** | Section 508 / WCAG 2.1 AA — skip nav, landmarks, focus management |
| **Required components** | USA Banner + USA Identifier on every page |
| **Component library** | 20 thin Astro wrappers for USWDS patterns |
| **i18n** | English (`/`) and Spanish (`/es/`) — one route file per page serves both locales |
| **Search** | [Pagefind](https://pagefind.app/) static search at `/search/` — self-hosted, language-aware |
| **Content collections** | Services, announcements, FAQs — Zod-typed, MDX-ready |
| **CI quality gates** | TypeScript, HTML, axe-core, Lighthouse, links, plain language, USWDS compliance |
| **Output** | Static — deploys to GitHub Pages, Cloud.gov Pages, Netlify, Vercel, S3 |
---
## Quick start (from template)
1. Click **Use this template** → **Create a new repository**
2. Clone your new repo and install:
```bash
git clone https://github.com/YOUR-ORG/YOUR-REPO.git
cd YOUR-REPO
pnpm install
```
3. Run the agency setup wizard:
```bash
node scripts/init-agency.mjs
```
This updates `src/config/site.ts` with your agency name, domain, and the
seven required [USA Identifier](https://designsystem.digital.gov/components/identifier/) links.
4. Replace seed content in `src/content/` with your programs and FAQs.
5. `pnpm dev` — live preview at `http://localhost:4321`
6. `pnpm build` — production build in `dist/`
---
## Configuration
All agency-specific settings live in one file:
```ts
// src/config/site.ts
export const siteConfig = {
name: 'Department of Human Services',
shortName: 'DHS',
domain: 'dhs.state.gov',
description: 'Programs and services for eligible residents.',
locale: 'en-US',
// Required links for the USA Identifier footer component
links: {
about: '/about/',
accessibility: '/accessibility/',
foia: 'https://www.foia.gov/',
noFear: 'https://www.eeoc.gov/no-fear-act-data',
oig: 'https://www.oversight.gov/',
privacy: '/privacy/',
budget: '/',
usagov: 'https://www.usa.gov/',
},
} as const;
```
---
## Project structure
```
src/
├── config/site.ts # Agency name, domain, identifier links ← edit this first
├── content/ # Markdown content (services, faqs, announcements)
├── components/uswds/ # 20 USWDS pattern wrappers (Alert, Accordion, Hero, …)
├── i18n/ # Translation strings (en, es) + useTranslations helper
├── layouts/ # BaseLayout, ServiceLayout, ApplyLayout
├── pages/
│ ├── [...lang]/ # One route file per page serves BOTH / and /es/
│ │ ├── index.astro # (locale comes from getStaticPaths via localeStaticPaths())
│ │ ├── services/ # services index + [slug] detail pages
│ │ ├── apply/[program].astro
│ │ └── search.astro # Pagefind-powered site search
│ ├── 404.astro
│ └── internal/components.astro # Dev-only component preview (not linked publicly)
└── styles/
├── uswds-theme.scss # USWDS entry point (settings + full import)
└── globals.css # Tailwind utilities + custom CSS
scripts/
├── init-agency.mjs # One-time agency setup wizard
├── setup-uswds.mjs # Copies USWDS assets to public/uswds/
├── plain-language.mjs # Flesch-Kincaid readability gate (avg grade ≤ 8)
├── compliance-check.mjs # USWDS compliance check on built HTML
└── check.sh # Runs all local quality gates
```
---
## USWDS component library
All 20 components live in `src/components/uswds/`. Preview them at `/internal/components/` during local dev.
| Component | USWDS pattern |
|---|---|
| `Alert` / `SiteAlert` | [Alert](https://designsystem.digital.gov/components/alert/) |
| `Accordion` / `AccordionItem` | [Accordion](https://designsystem.digital.gov/components/accordion/) |
| `Breadcrumb` | [Breadcrumb](https://designsystem.digital.gov/components/breadcrumb/) |
| `CallToAction` | [Banner section pattern](https://designsystem.digital.gov/patterns/) |
| `Footer` | [Footer](https://designsystem.digital.gov/components/footer/) |
| `Header` | [Header](https://designsystem.digital.gov/components/header/) |
| `Hero` | [Hero](https://designsystem.digital.gov/components/hero/) |
| `Pagination` | [Pagination](https://designsystem.digital.gov/components/pagination/) |
| `ProcessList` / `ProcessListItem` | [Process list](https://designsystem.digital.gov/components/process-list/) |
| `Search` | [Search](https://designsystem.digital.gov/components/search/) |
| `ServiceCard` | [Card](https://designsystem.digital.gov/components/card/) |
| `SideNav` | [Side navigation](https://designsystem.digital.gov/components/side-navigation/) |
| `StepIndicator` | [Step indicator](https://designsystem.digital.gov/components/step-indicator/) |
| `SummaryBox` | [Summary box](https://designsystem.digital.gov/components/summary-box/) |
| `Tag` | [Tag](https://designsystem.digital.gov/components/tag/) |
| `USABanner` | [Banner](https://designsystem.digital.gov/components/banner/) |
| `USAIdentifier` | [Identifier](https://designsystem.digital.gov/components/identifier/) |
---
## Quality gates
Run all checks locally before pushing:
```bash
bash scripts/check.sh # TypeScript + build + HTML + plain language + compliance
bash scripts/check.sh --verbose # same, with per-file output
```
| Gate | Tool | Threshold |
|---|---|---|
| TypeScript | `astro check` | 0 errors |
| HTML | `html-validate` | 0 errors |
| Accessibility | `@axe-core/cli` (CI only) | 0 violations |
| Lighthouse | `@lhci/cli` (CI only) | perf ≥ 90, a11y = 100, BP ≥ 90, SEO ≥ 90 |
| Links | `linkinator` (CI only) | 0 broken internal links |
| Plain language | `scripts/plain-language.mjs` | avg Flesch-Kincaid grade ≤ 8 |
| USWDS compliance | `scripts/compliance-check.mjs` | banner + identifier + skip nav present |
---
## Deploy
### GitHub Pages (included)
Push to `main`. The workflow in `.github/workflows/deploy-pages.yml` deploys automatically.
Enable Pages: **Settings → Pages → Source: GitHub Actions**.
> **⚠️ Security headers:** GitHub Pages does **not** support custom HTTP response
> headers, so the headers in `public/_headers` (clickjacking protection via
> `frame-ancestors`, `X-Frame-Options`, HSTS, etc.) are silently ignored on
> GitHub Pages. They only take effect on Netlify or Cloudflare Pages. If you need
> these protections — and production government sites should have them — deploy
> to a host that supports response headers, or put a CDN/reverse proxy (e.g.
> CloudFront) in front of Pages and set the headers there.
### Cloud.gov Pages
```yaml
# federalist.json
{
"build": {
"command": "pnpm install && pnpm build",
"destination": "dist"
}
}
```
### Netlify / Vercel
Both auto-detect Astro. Set **build command** to `pnpm build` and **publish directory** to `dist`.
### Any static host (S3, CloudFront, Azure Blob)
```bash
pnpm build # outputs to dist/
```
Upload the contents of `dist/` to your bucket or CDN origin.
---
## Search
Site search is powered by [Pagefind](https://pagefind.app/). The `pnpm build`
script indexes `dist/` after the Astro build and writes the index to
`dist/pagefind/`. Results are served at `/search/` (English) and `/es/search/`
(Spanish) — Pagefind splits the index by each page's `<html lang>`, so each
locale searches its own content.
- Search only works on a **production build** (`pnpm build && pnpm preview`);
the dev server has no index.
- The CSP includes `'wasm-unsafe-eval'` because Pagefind runs its index as
same-origin WebAssembly (this does **not** allow JavaScript `eval()`).
- No third-party requests: the index and UI are self-hosted static files.
---
## Forms
The contact form (`/contact/`) and eligibility screeners (`/apply/*`) are
**accessible scaffolding only** — they do not submit anywhere out of the box.
Before launch, wire the `action` attributes to your backend of choice
(Formspree, API Gateway + Lambda, your agency's form service, etc.). Look for
the `TODO (M3)` comments in `src/pages/[...lang]/contact.astro` and
`src/pages/[...lang]/apply/[program].astro`.
---
## Adding a new language
The template ships with English (`/`) and Spanish (`/es/`). Every page lives
once in `src/pages/[...lang]/` and renders for each locale returned by
`localeStaticPaths()`, so there is no page tree to mirror. To add another
language (e.g. French):
1. Add `fr: 'fr-FR'` to `LOCALES` in `astro.config.mjs`
2. In `src/i18n/utils.ts`: add `'fr'` to the `Locale` type and `locales`
array, add a `fr` entry to `localeMeta` (native label + og:locale), and
register `fr.json` in the `translations` map
(create `src/i18n/fr.json` by copying `en.json` and translating)
3. Add a `fr` entry to each page's `copy` object in
`src/pages/[...lang]/*.astro` — TypeScript will point you at every one
4. Translate the content collections (see below)
That's it — the header's language selector, hreflang tags, and og:locale
meta tags all read from `locales`/`localeMeta`, so they update automatically
(the header even switches from a simple toggle link to the USWDS dropdown
once there are 3+ locales).
### Translating content
Collection entries are translated by adding a **locale subdirectory** beside
the default-locale files, so translators edit real Markdown instead of strings
crammed into frontmatter:
```
src/content/services/snap.mdx # English (default locale)
src/content/services/es/snap.mdx # Spanish
src/content/services/fr/snap.mdx # French
```
Both files describe the same service, share the URL slug `snap`, and translate
everything — `title`, `summary`, `eligibility`, `keyFacts`, and the body prose.
Keep `applySlug`, `order`, and `related` identical across a set, since those are
identifiers rather than copy.
**Translations are optional.** A page renders the requested locale's file when
one exists and falls back to the default locale otherwise, so a partial
translation ships fine and a missing file never breaks the build. The lookup
lives in `entriesForLocale()` in `src/utils/content.ts`.
The plain-language gate scores each file with a formula built for the language
it is written in — Flesch-Kincaid for English, Fórmula de Crawford for Spanish —
because running an English readability formula over Spanish would fail plain
translations for having longer words. Add a formula there when you add a
language, or its files will be scored as English.
---
## Compliance
See [COMPLIANCE.md](./COMPLIANCE.md) for Section 508, WCAG 2.1 AA, 21st Century IDEA Act,
and USWDS version details.
---
## Contributing
See [CONTRIBUTING.md](./CONTRIBUTING.md).
## License
Code: [MIT](./LICENSE)
Seed content: CC0 — no rights reserved, free to adapt for any agency.
Explore similar templates
Compare previews and descriptions within the same stack and category.

astrowind
AstroWind is a free, open-source Astro starter theme using Astro and Tailwind CSS, released under the MIT license.
Astro · Blog
accessible-astro-starter
An accessibility-focused Astro 6 starter template with WCAG 2.2 AA practices, Tailwind CSS 4, TypeScript, Prettier, ESLint, form validation, blog and portfolio examples, and preference toggles for dark mode, high contrast, and reduced motion.
Astro · Blog

astro-erudite
astro-erudite is an opinionated, unstyled static blog template built with Astro and native CSS, with no UI or CSS framework and minimal dependencies.
Astro · Portfolio

astro-shopify
A lightweight Shopify headless ecommerce starter template built with Astro and Svelte, integrating the Shopify Storefront API for product and inventory data, with built-in cart state management and basic add-to-cart and checkout flow.
Astro · E-commerce

brutal
Brutal is a neobrutalism Astro starter theme from ElianCodes, derived from the author's personal site and generalized. It includes a Markdown blog collection, build-time RSS and sitemap, image optimization, Tailwind CSS styling, and Biome checks, with no JavaScript by default.
Astro · Starter

qwind
Qwind is a free and open-source website template built on Qwik and Tailwind CSS, featuring directory-based routing via QwikCity, a Markdown blog, dark mode, and static deployment configuration.
Astro · Tool Site
