Project rules and context for Codex (and humans). Read this before working in the repo.
A static Astro 5 landing page for ManagedCode's open-source patronage initiative ("Mission"),
served at mission.managed-code.com. Companies become patrons; their monthly fee funds a team of
maintainers who keep the patrons' open-source dependencies healthy (real maintainer-hours + a written SLA) and
train juniors in the open. The page is a manifesto/demo. Audience: engineering managers & technical
founders (~born 1985–1990). Aiming for Awwwards-grade polish. All copy is English.
- Brand / masthead: lead with ManagedCode (the org). "Mission" is the initiative name, shown as a
small tag. Official logo lives at
public/managedcode-logo.svg(the< >code-bracket mark) and is rendered viasrc/components/Logo.astrowithfill="currentColor"(theme-aware). Do NOT reintroduce the old pixel-flame mark. - Concept: "Patrons of the digital commons" — Renaissance patronage × tasteful 8-bit pixel-craft, clean & editorial. Light + dark themes.
- Model: it's a subscription to a team of maintainers, not buying a developer. There is NO fixed
price — patrons fund a maintainer at a developer grade (Trainee / Junior / Mid ★ / Senior ≈ that
engineer's salary), each with maintainer-hours (~6/20/50/120/mo) + a response window (72/24/8/4 h). The only dollar
figure on the page is the launch funding goal: $32,768/mo, $8k committed (the $32,768 goal is a
2¹⁵ dev Easter egg — keep that exact power of two; committed is shown as $8k, deliberately not
$8,192, which reads as too-obviously-fake;
fundinginsite.ts, rendered byFunding.astro). Grades, windows and funding figures are illustrative (footer disclaimer says so) — keep that framing; don't reintroduce per-tier sticker prices. - Vocabulary (IMPORTANT — de-guilded 2026-06): the word "guild" is banned from user-facing copy.
The audience is CTOs / engineering managers; "guild" reads as fantasy-game cringe to them. Use "a funded
team of maintainers", "maintainer-hours", "we adopt your stack" instead. "Guild" may survive ONLY
as light easter-egg flavor in playful corners (console egg, konami, source comments) — never in nav,
headings, tiers, SLA, FAQ or value prop. The maintainers section anchor is
#maintainers(the component is stillMaintainers.astrointernally). The "Become a patron" CTAs all lead to the patron application form at#apply(Apply.astro), which POSTs JSON tosite.formEndpointand is inert until that endpoint is set — no mailto fallback by design. Theguild.projectslist insite.tsis curated to active repos; don't reintroduce abandoned ones (e.g.Database, last pushed 2023).
- All copy + real facts live in
src/data/site.ts— the single source of truth. Never hardcode copy in components; import fromsite.ts. The managedcode repo stats there are real (as of mid-2026) and conservative — don't inflate them. - Design tokens only. Use the CSS custom properties and utility classes in
src/styles/global.css(--bg/--fg/--accent/...,--font-display/-serif/-mono/-pixel,--step-*,--space-*,.wrap,.section,.kicker,.card,.btn,.chip,[data-reveal],.invert). Don't hardcode hex unless it matches a token. - Progressive enhancement. Scroll-reveal hidden states are gated on
:root.js(set by the inline script inBaseLayout.astro). The page must be fully visible and usable without JS (crawlers / fast first paint). Don't hide content behind JS-only reveals. - Reduced motion + test determinism. Every animation must have a
@media (prefers-reduced-motion: reduce)fallback. New animations must settle to a deterministic final state (the visual test helper disables animations and force-finishes the terminal typewriter / hides the scroll bar). - Accessibility is AA. Keep contrast ≥ 4.5:1 for text (the
--fg-fainttoken is tuned for this — re-check if you change it), decorative SVGsaria-hidden, semantic headings, focus-visible, labelled controls. - Astro compiler gotcha: inlining a
.map()that returns JSX adjacent to another element, or deeply nested.map-returning-JSX, can make the compiler emit an unterminated$$rendertemplate literal (esbuild then fails with a misleadingExpected ")"). Fix by precomputing a trusted HTML string in frontmatter and rendering withset:html— and style those nodes with:global(...)(set:html content doesn't get scoped-style attributes). See the hero headline/terminal inHero.astro.
npm install # deps (Node 20+; built on Node 25)
# Dev / build
npm run dev # astro dev → http://localhost:4321
npm run build # regenerates favicons, then astro build → dist/
npm run preview # serve dist/ (Playwright/Lighthouse use port 4333, see below)
# Assets (regenerate after changing the logo/brand)
npm run icons # scripts/generate-icons.mjs — favicons from public/managedcode-logo.svg (sharp)
npm run og # scripts/generate-og.mjs — public/og.png 1200×630 social card (playwright + real fonts)
# Static analysis (run before committing)
npm run check # astro check — TypeScript / .astro type-checking (must be 0 errors)
npm run lint # eslint . (astro + ts) npm run lint:fix
npm run format # prettier --write . npm run format:check
npm run validate # astro check && eslint .
# Tests (Playwright: functional + pixel visual regression)
npm test # build + serve on :4333 + run all tests (desktop + mobile)
npm run test:update # regenerate visual baselines after an intentional UI change
npm run test:ui # interactiveThe site targets green Core Web Vitals. CSS is inlined (build.inlineStylesheets: 'always') to remove the
render-blocking request. To measure locally, build, preview on :4333, then run Lighthouse against the
Playwright-bundled Chromium:
npm run build && npm run preview -- --host 127.0.0.1 --port 4333 &
CHROME_PATH="$(node -e "console.log(require('playwright').chromium.executablePath())")" \
npx lighthouse http://127.0.0.1:4333/ \
--only-categories=performance,accessibility,best-practices,seo \
--chrome-flags="--headless=new --no-sandbox" --quiet --viewLast local run: Performance 97 · Accessibility 100 · Best-Practices 100 · SEO 100 (TBT 0ms, CLS 0.002). FCP/LCP on the uncompressed local preview run ~2s; on production (CDN + Brotli + HTTP/2) expect ~1s and ~99–100 performance. Don't regress: no render-blocking resources, no layout shift, keep client JS tiny.
- The dev/test server runs on port 4333 (not Astro's 4321) and
reuseExistingServer: false, because other local Astro projects may hold 4321 — never test the wrong site. Config:playwright.config.ts. - 7-device matrix:
phone-sm(360),phone-md(iPhone 13),phone-lg(iPhone 14 Pro Max),tablet(iPad Mini),tablet-lg(iPad Pro 11),desktop(1440),desktop-xl(1920). Visual baselines are platform-suffixed (-darwinlocal,-linuxCI) undertests/__screenshots__/and committed — regenerating them produces ~49 images, so only runtest:updatefor intentional UI changes. tests/functional.spec.ts— behaviour/SEO/a11y.tests/visual.spec.ts—toHaveScreenshotpixel diffs (maxDiffPixelRatio: 0.02).tests/perf.spec.ts— cross-viewport speed test (FCP / DCL / JS-budget ≤150KB / no render-blocking CSS) on every project.tests/helpers.ts—prepareForVisual()makes frames deterministic (reveals shown, counters settled, terminal typewriter finished, animations disabled, and the JS-driven decorative chrome hidden — cursor, scroll bar, CRT, the generative<canvas>crest, the mascot, the sound toggle and the intro loader — so diffs track content, not sprites). The intro loader is alsonavigator.webdriver-gated, so it never runs under Playwright/Lighthouse.- After any intentional visual change:
npm run test:update, then a cleannpm testto confirm stability, and commit the new baselines yourself. For Linux baselines, use the manual Playwright workflow artifact or run the update inside the pinned Playwright container; CI must not commit back tomain. - CI:
.github/workflows/deploy.ymlruns the full Playwright matrix in the official Playwright container before build/deploy..github/workflows/playwright.ymlis manual-only for Linux baseline artifacts and never pushes.
.github/workflows/deploy.yml builds and publishes to GitHub Pages on every push to main
(Pages → Source must be "GitHub Actions"). public/CNAME = mission.managed-code.com, so once the DNS is
pointed the site serves at the custom domain (base /). The full Playwright matrix is part of this deploy
pipeline and gates publishing. The deploy job uses .github/scripts/deploy-pages.cjs instead of
actions/deploy-pages because the official action hard-caps status polling at 10 minutes and cancels queued
Pages deployments.
BaseLayout.astro emits full OG/Twitter/canonical + JSON-LD (Organization, WebSite, WebPage); index.astro
adds FAQPage + Service with per-grade Offers (no price — salary-grade model; availability + url). Keep
public/robots.txt (welcomes AI crawlers), public/llms.txt (answer-engine summary), and the sitemap
(@astrojs/sitemap, emits lastmod) in sync with site.ts. Meta description should stay ~150–160 chars.
src/
data/site.ts single source of truth — copy, real facts, tiers, faq, seo, brand
styles/global.css design system (tokens, utilities, themes, animations)
layouts/BaseLayout.astro head/SEO/JSON-LD, no-flash theme + `.js` PE flag, scroll bar + CRT
scripts/app.ts reveals, counters, theme, nav (focus-managed), terminal typewriter,
scroll-progress, konami (↑↑↓↓←→←→BA → CRT payoff)
components/ Logo, Header, Hero, Problem, Manifesto, HowItWorks, Maintainers, Sla, Tiers,
Join, Faq, FinalCta, Footer
pages/index.astro landing page pages/404.astro "never merged" story (noindex)
scripts/ generate-icons.mjs (sharp) · generate-og.mjs (playwright)
tests/ functional.spec.ts · visual.spec.ts · helpers.ts