Skip to content

Latest commit

 

History

History
177 lines (141 loc) · 8.94 KB

File metadata and controls

177 lines (141 loc) · 8.94 KB

AGENTS.md

Instructions for coding agents working in this repository, per the agents.md convention. Agents read the nearest AGENTS.md in the directory tree, so a package in a monorepo can add its own.

This file is hand-written and is never generated. The public agent routing document — the one served at /AGENTS.md for external developers and their agents — is public/AGENTS.md, generated by scripts/agents.mjs. Do not edit that one by hand; your changes will be overwritten on the next commit that mentions agents.md.

Setup commands

  • This app runs on Next.js 16 — its APIs and conventions may differ from older Next versions in your training data.
  • Install deps: npm install
  • Start dev server: npm run dev
  • Build: npm run build
  • Install git hooks (once per clone): ./githooks/install.sh

Generated files — do not edit

These are written by scripts/llms.mjs and scripts/agents.mjs:

  • public/llms.txt
  • public/llms-full.txt
  • public/AGENTS.md

To change their contents, edit the source instead:

  • A page's title or description → that route's export const metadata in its page.tsx. This is the same metadata Next uses for SEO, so there is one source of truth rather than two.
  • Ordering, sections, network reference, routing rules, freshnessllms.config.mjs.
  • Hand-written prose inside llms-full.txt → edit between the <!-- LLMS_EXTRAS_START --> and <!-- LLMS_EXTRAS_END --> markers directly in public/llms-full.txt. That region is preserved verbatim across regenerations; everything outside it is not.

Check whether they are current: npm run llms -- --check

Regenerating

Include llms.txt or agents.md in your commit message and the post-commit hook regenerates and creates one follow-up commit:

git commit -m "feat: add snapshots page; updates llms.txt"

Adding, deleting, or renaming a page.tsx triggers it automatically. To opt out of a single commit, use SKIP_DOCS_HOOK=1 or put [skip-docs] in the message.

Code style

  • TypeScript strict mode
  • Follow the existing formatter config; do not reformat unrelated files
  • Icons: there is no icon library; icons are hand-authored inline SVGs, with the commonly reused ones centralized in app/components/ui/icons.tsx. When adding or touching an icon that toggles between two states based on props/state (e.g. copy → check, menu → close) — not just shown/hidden — consider animating the transition with morphicons instead of an instant swap: <MorphIcon icon={condition ? A : B} /> from morphicons/react, fed path data on a shared 24x24 grid (fitIcon() first if the source art isn't already on that grid). See CLIPBOARD_MORPH_ICON/CHECK_MORPH_ICON in app/components/ui/icons.tsx and their use in app/demos/b20/components/CopyPromptButton.tsx, app/internal-explorer/components/CopyButton.tsx, and app/vibenet/components/CopyableValue.tsx.

Testing

Two separate suites, for two separate purposes — don't mix their files.

  • Unit/component/contract tests — Vitest. *.test.ts(x), colocated next to the code they cover (e.g. app/snapshots/networks.contract.test.ts, deploy.config.test.mjs). Run with npm test. Fast, no browser, no build — this is where logic, data transforms, and contract/matrix assertions live. Blocking CI job (test).

  • End-to-end journeys — Playwright. e2e/*.spec.ts. Run with npm run test:e2e, which builds the app and drives it in a real browser against that production build. Non-blocking CI job (e2e (non-blocking), continue-on-error: true) — failures are visible but don't block merges while this suite is still young. vitest.config.mts excludes e2e/** from Vitest's default test glob so the two runners never pick up each other's files.

    When to add an e2e test: only for surfaces that are stable — established pages/journeys not expected to change shape week to week (e.g. the home page, core nav, Snapshots, Upgrades). Do not add e2e coverage for a new demo or anything still being iterated on (e.g. work under app/vibenet/demos/) — the UI will keep shifting under the test faster than the test catches real regressions, making it pure maintenance overhead. Add a smoke test once a demo's surface has settled, not before.

  • Run the llms-kit suite (generation scripts under scripts/, unrelated to the app tests above): node --test tests/

  • Include liveness checks against the deployed site: LLMS_LIVE=1 node --test tests/

Analytics

This app uses Vercel Web Analytics. Two things must stay in place:

  1. Page views — render <Analytics /> from @vercel/analytics/next in app/layout.tsx. Removing it stops all analytics (page views and events).

  2. Custom events — typed helpers in app/analytics/events.ts emit only when a component calls them. When you refactor or rewrite a wired surface, carry the track() call over. Current wiring:

    Helper Call site
    trackNavClick(label) app/components/AppShell.tsxNavRow <Link onClick>
    trackSnapshotNetworkSelect(network) app/snapshots/SnapshotsClient.tsx — network button onClick
    trackSnapshotPresetSelect(name) app/snapshots/SnapshotsClient.tsxselectPreset()
    trackSnapshotCommandCopy(network, preset) app/snapshots/SnapshotsClient.tsxInlineCommand onCopy
    trackFaucetRequest(token, status) app/vibenet/faucet/page.tsxrunDrip()
    trackAccountAction(name) app/vibenet/demos/account/AccountDemo.tsx — feature tiles (transact, sponsorship, batched calls, gas-in-token, modify owners)
    trackB20ModuleSelect(module) app/vibenet/demos/b20/B20Demo.tsx — module navigation
    trackB20Action(module, action, status) app/vibenet/demos/b20/B20Demo.tsx — B20 broadcasts
    trackB20PromptCopy(module, prompt) app/vibenet/demos/b20/components/CopyPromptButton.tsx — copy AI prompt
    trackExplorerChainSelect(chain) app/internal-explorer/components/ChainToggle.tsx — chain toggle
    trackExplorerActiveBlockJump(chain, jump) app/internal-explorer/components/ActiveBlockButton.tsx — zeronet latest/previous active block

    Add a helper (and a row here) for a new key journey; remove the helper if you remove its surface. Confirm the wiring with grep -rn "analytics/events" app. Custom events collect on Vercel deployments only (not local npm run dev); Vercel auto-discovers event names.

Deployment targets (internal vs external)

This one repo builds two deployables from the same source:

  • external — the public site on Vercel (npm run build / npm run dev). The default target.
  • internal — a separate internal deployment (npm run build:internal / npm run dev:internal, which set NEXT_PUBLIC_DEPLOY_TARGET=internal).

Which sections ship to which target is declared in deploy.config.mjs — the SURFACES map (section → { routePrefixes, apiPrefixes, targets }). A section absent from the map ships everywhere — the map is an exception list, so an internal-only page with no entry will fail open and publish. A disabled surface is unreachable in that build (routes + API 404, dropped from nav/sitemap/llms); its client chunks may still be emitted, so treat this as a reachability guarantee, not secrecy. Internal Explorer (/internal-explorer) and Benchmark are internal-only today, and the public-build-excludes-internal CI job enforces their absence from the public build — extend that job's path list when you add another internal-only surface.

When you add or change an environment-specific section:

  1. Add/edit its deploy.config.mjs entry. That alone makes middleware 404 its routes (disabledRoutePrefixes()) and drops it from the generated llms/agents artifacts (llms.config.mjs uses disabledRouteGlobs()).
  2. Gate the per-section surfaces that aren't automatic: the nav entry (app/internal-explorer/flag.tsapp/navigation.ts), a layout notFound() backstop, and the API routes (app/api/internal-explorer/guard.ts pattern). Use surfaceEnabled(...). A section with no API routes of its own needs no guard and no apiPrefixes entry — Benchmark is the example: its browser code calls the report API directly via NEXT_PUBLIC_BENCHMARK_API_BASE_URL.
  3. Select the target only via the build/dev script, never a hand-set env var. The internal image sets it in its Dockerfile (npm run build:internal).
  4. Regenerate the agent index with the external (default) target so the committed public artifacts never leak an internal-only section: npm run llms && npm run agents.

The matrix logic is covered by deploy.config.test.mjs.

Pull requests

  • Keep the generated-file commit separate from your own work — the hook already does this for you. Do not squash it away; it is what makes the generated diff reviewable.