# Apache Magpie — Website
Landing page and documentation hub for [Apache Magpie](https://github.com/apache/magpie), an AI assistant that helps open-source maintainers handle the repetitive parts of running a project — triage, mentoring, drafting fixes, and security-report handling — so they can focus on the work that needs a human.
> Status: **Apache Top-Level Project**. Project source lives at [apache/magpie](https://github.com/apache/magpie); this repo holds the public website.
## Stack
| Layer | Tool |
|---|---|
| Framework | [Astro 7](https://astro.build) (static output) |
| UI | React 19 + [Tailwind CSS 4](https://tailwindcss.com) |
| Interaction | React state, native controls and CSS transitions; reduced-motion support |
| Icons | [lucide-react](https://lucide.dev) + inline SVG for brand marks |
| Docs | Astro content collections, markdown synced from [apache/magpie/docs](https://github.com/apache/magpie/tree/main/docs) |
Zero runtime dependency on closed-source design tooling. All components are owned in-tree.
## Local development
```bash
npm install
npm run sync-docs # fetch markdown and generate tools data from apache/magpie
npm run dev # http://localhost:4321
```
Always start the dev server with `npm run dev` — it runs `scripts/dev.sh`, which sets `ASTRO_TELEMETRY_DISABLED=1` before launching `astro dev`. Without that, Astro tries to write to its telemetry config dir (e.g. `~/Library/Preferences/astro`) and the dev server fails to start in sandboxed environments. Pass extra flags through, e.g. `npm run dev -- --port 3000`.
The `prebuild` hook runs `sync-docs` automatically, so `npm run build` always pulls a fresh copy of docs before generating the static site.
### Available commands
| Command | Purpose |
|---|---|
| `npm run dev` | Dev server with HMR (telemetry disabled via `scripts/dev.sh`) |
| `npm run sync-docs` | Clone `apache/magpie` (sparse, `docs/` + `images/`) into `src/content/docs/` and `public/docs-assets/`, and generate `src/data/tools.json` |
| `npm run build` | Static build to `dist/` (runs sync-docs first) |
| `npm run preview` | Serve the built site locally |
| `npm run astro` | Astro CLI passthrough |
| `npm run check:fast` | Knip, authored CSS audit, type checking, unit and negative checker tests |
| `npm run test:browser` | Force-build, HTML/link/asset/route audit, responsive/a11y/interaction tests |
| `npm run check` | Complete blocking gate |
| `npm run hooks:verify` | Prove Git dispatches both installed hooks and rejects a failing probe |
Install local hooks with prek 0.3.6 or newer:
```bash
prek install --overwrite --git-dir "$(git rev-parse --git-common-dir)" --hook-type pre-commit --hook-type pre-push
npm run hooks:verify
```
Pre-commit runs hygiene and the fast gate; pre-push runs the complete gate.
A global `core.hooksPath` must forward to this repository's hooks. The verification
command exercises the effective path in a temporary repository and fails when
dispatch is missing; it never stages, stashes, commits or pushes this project.
See [the consistency contract](docs/designs/2026-09-26-ui-quality-contract.md)
for exact assertions, fixtures and boundaries.
### Environment variables (optional)
| Var | Default | Purpose |
|---|---|---|
| `MAGPIE_DOCS_REPO` | `https://github.com/apache/magpie.git` | Source repo for markdown |
| `MAGPIE_DOCS_BRANCH` | `main` | Branch to sync from |
## Project structure
```
website/
├── scripts/
│ └── sync-docs.sh # sparse-clone docs/ + images/ from source repo
├── src/
│ ├── components/
│ │ ├── landing/ # LP + SiteHeader/SiteFooter
│ │ ├── docs/ # tree + search dialog
│ │ └── stories/ # illustrative trend + interactive data charts
│ ├── content/
│ │ └── docs/ # synced markdown (gitignored)
│ ├── content.config.ts # docs collection schema
│ ├── layouts/
│ │ ├── BaseLayout.astro
│ │ └── DocsLayout.astro
│ ├── lib/utils.ts # deployment base-path helper
│ ├── pages/
│ │ ├── index.astro # /
│ │ └── docs/
│ │ ├── index.astro # /docs
│ │ └── [...slug].astro # /docs/<any>
│ └── styles/ # spacing, shared chrome, page layouts, dark tokens
├── tests/browser/ # discovered routes, interactions, broken fixtures
├── public/ # static assets (logos, favicons, /docs-assets)
└── astro.config.mjs
```
## Docs pipeline
The website is decoupled from the docs source. The markdown lives in [apache/magpie/docs](https://github.com/apache/magpie/tree/main/docs); this repo fetches it at build time and renders it through Astro content collections.
```
apache/magpie/docs/*.md
│
▼ scripts/sync-docs.sh (sparse clone)
src/content/docs/*.md
│
▼ Astro content collection
dist/docs/**/*.html (one static page per markdown file)
```
Image references inside markdown (`../../images/foo.png`) are rewritten to `/docs-assets/foo.png` during sync so they resolve against `public/docs-assets/`.
## CI
The existing Build and Deploy workflow runs the hygiene and static gates, then
fresh-build browser checks and the development preview tests. Production builds
and publication depend on those checks. PR source-annotation previews and their
Astro/Jekyll adapter tests remain part of the upstream workflow.
## Deployment
The site is published by **ASF infrastructure**, not GitHub Pages. On every push to `main`, CI builds the static site and force-pushes `dist/` (an orphan, single-commit history) to the **`publish`** branch. The root [`.asf.yaml`](./.asf.yaml) — carried into that branch — tells ASF infra to serve it:
```yaml
publish:
whoami: publish
```
ASF infra serves the `publish` branch at the project's inferred hostname — `magpie-site` → **[magpie.apache.org](https://magpie.apache.org/)** (served at the apex root). The hostname must **not** be set explicitly via a `hostname:` field; asfyaml forbids naming your own `$project.apache.org` ("it has to be inferred to prevent abuse"), and doing so stops the site from publishing.
The site is built with `base: '/'` so all links and assets resolve against the apex domain. Set `SITE_BASE` / `SITE_URL` to preview under a subpath (e.g. GitHub Pages).
> One-time infra setup (outside this repo): for a brand-new project, ASF Infra may still need to provision DNS/TLS for `magpie.apache.org` before the inferred hostname resolves.
### Previewing a pull request
A committer can publish a live preview of any open pull request by commenting:
/show-preview
The **Publish PR previews** workflow runs on a 15-minute schedule and then
tracks the PR's head commit — each new push is picked up on the next run —
though GitHub may delay a scheduled run when it is busy. It appears at
`https://magpie-pr<N>.staged.apache.org/`, and like the production site, ASF
staging takes a few minutes to propagate after each publish. A maintainer who
does not want to wait can dispatch the **Publish PR previews** workflow
manually with the PR number.
Previews are retired when the PR closes: the site is replaced with a notice
rather than disappearing, because deleting the branch does not unstage the
site — the branch is only deleted (as a separate, later step) once the notice
is live.
To turn a preview off before the PR closes, delete the `/show-preview`
comment (and, if the preview was started by manual dispatch, also delete the
bot's arming comment); the next scheduled run retires it.
## Agent-assisted contribution (apache-magpie)
This repo adopts the [`apache/magpie`](https://github.com/apache/magpie)
framework through its plugin marketplace, making its maintainer-facing agent
skills available in harnesses such as Claude Code. Nothing from the framework
is vendored or snapshotted here.
The committed [`.apache-magpie.lock`](.apache-magpie.lock) records the
project's floor: a minimum Magpie version and the plugins every contributor
gets — `magpie-setup`, `magpie-utilities`, `magpie-agent-guard` and
`magpie-vetted-ops`. The committed `.claude/settings.json` is derived from it,
so when you open and trust this repo in Claude Code it offers the
`apache-magpie` marketplace and those plugins; there is no install step. The
floor is a minimum, not a pin: a newer Magpie is fine, and an older one is
brought up to it by any skill's pre-flight.
Other families (`repo-health`, `release-management`, …) are not part of the
floor; install the ones you need for yourself:
/plugin install magpie-repo-health@apache-magpie
Configure Magpie for yourself with `/magpie-setup:setup config` (personal
files go in the gitignored `.apache-magpie-local/`) and check a checkout with
`/magpie-setup:setup verify`.
The project's configuration and any modifications to framework workflows live
in [`.apache-magpie-overrides/`](.apache-magpie-overrides/) (committed) —
never edit the installed plugins. Framework changes go via PR to
[`apache/magpie`](https://github.com/apache/magpie).
## License
[Apache License 2.0](./LICENSE).