Skip to content

Unify apex + web on one shared @agent-paste/ui design system#454

Merged
isuttell merged 9 commits into
mainfrom
claude/quizzical-bohr-cccdcc
Jun 9, 2026
Merged

Unify apex + web on one shared @agent-paste/ui design system#454
isuttell merged 9 commits into
mainfrom
claude/quizzical-bohr-cccdcc

Conversation

@isuttell

@isuttell isuttell commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Make the marketing site (apps/apex, agent-paste.sh) and the dashboard (apps/web, app.agent-paste.sh) render one shared design system so a look change is a one-file edit and the two surfaces cannot drift. This is a large branch (5 feature commits, ~173 files, +4666/-5665) that ends a long-standing split where apex was hand-written semantic CSS and web was Tailwind with its own copies of the primitives.

Changes

  1. @agent-paste/ui shared package + apex rebuild — new package of shared React primitives + a single globals.css generated from @agent-paste/brand. apex rebuilt from hono/jsx string-rendering into a Vite + React static SSG: zero client React, one vanilla enhancement script, static CSP with a build-time pre-paint theme-init. Deleted the brand-tokens parity test (parity is now structural).
  2. Real primitives moved inButton, Card, Badge, Table, cn moved from apps/web/src into packages/ui/src; ~38 web import sites repointed; emptied originals deleted. One copy, both apps.
  3. apex onto Tailwind — apex converted from 1,411 lines of semantic CSS to Tailwind on the shared components; base/sections/home/home-foot.css deleted. Net -1063 lines.
  4. One theme-driven scale — full type/leading/tracking/easing scale registered in the brand @theme; ~520 arbitrary brackets converted to named utilities (710 → 189, rest are logged structural literals); all spacing snapped to the integer scale. Fixed the dropped shared-component utilities ("missing padding") bug in both apps (each must @source packages/ui/src). Cross-surface theme sync via a cookie on .agent-paste.sh. Env-correct preview links (apex bakes app/api/mcp URLs from AGENT_PASTE_ENV). apex CSP theme-init hash derived on the fly (node:crypto in Workers).
  5. Unified header + bug fixes — one shared theme-toggle source (class, system/dark/light SVG icons, cycle, aria); apex's framework-free script and web's React toggle render the identical button and write the same cookie (apex gained the "system" state). Fixed Copy URL button wrap (whitespace-nowrap) and the dashboard section-label/rule overlap (SectionLabel action slot).

Plus chore(lint): biome now ignores nested .wrangler/.turbo (a build artifact was tripping the format gate).

Risk: MEDIUM

  • Areas touched: packages/ui, packages/brand, apps/apex, apps/web (styling/components only); apex build pipeline + CSP; deploy.mjs apex env passthrough; biome ignore config.
  • Security: apex CSP theme-init hash is now derived from the script at module load (was hand-pinned); no relaxation of the policy. No auth/token/secret changes.
  • Performance: apex ships less (static SSG, zero client React beyond one enhancement script). web bundle unchanged in shape.
  • Breaking: none to public contracts. Internal-only refactor; no API/db/schema change.

Test plan

  • pnpm verify (lint, typecheck, test, openapi:check, db:check, knip, dupes, format) green
  • pnpm test:coverage green (lines 91.46%, above the 88/82/88/88 floors)
  • both apps build; apex prerenders all routes
  • deployed to preview; theme sync verified bidirectional (apex ↔ web); preview links resolve to preview subdomains; Copy URL + section-label overlap fixed

Issue: AP-276

Summary by CodeRabbit

  • New Features
    • Added redesigned marketing site pages: Home, About, How It Works, Pricing, Docs index & pages, and Legal.
  • UI/Design Updates
    • New unified design system, refreshed wordmark, vermilion accent, and self‑hosted variable fonts for faster, consistent typography.
  • Bug Fixes & Improvements
    • Improved theme persistence via cross‑surface cookie and stricter, hash‑based security policy for inline theme init; assorted UI/styling refinements across the dashboard.

isuttell and others added 7 commits June 8, 2026 14:34
… as Vite SSG

Add @agent-paste/ui: shared React primitives + a single globals.css generated from @agent-paste/brand. Migrate web to import it and delete the brand-tokens parity test (parity is now structural). Rebuild apex from hono/jsx string-rendering into a plain Vite + React app prerendered to static HTML: zero client React, one vanilla enhancement script (client.ts), a static CSP with a build-time sha256-pinned pre-paint theme-init. Per-env builds gate /pricing on BILLING_ENABLED; a thin worker shim (server.ts) serves redirects, headers, and text assets while HTML/CSS/JS/fonts go through the ASSETS binding. Wire deploy.mjs, deploy-pr-preview.mjs, and turbo.json for the new build. Split the old index.test.ts into render/server/security-headers/entry-server suites; ledger-exclude browser-only client.ts from coverage and render every doc slug.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ibrary)

The prior refactor claimed Button/Card/Badge/Table/cn were shared but only
Prose ever landed in the package; web kept its own copies and apex hand-wrote
CSS. Move the actual primitives into @agent-paste/ui so both apps render ONE
copy and cannot drift.

- Move Button, Card, Badge, Table, cn from apps/web/src into packages/ui/src
- Export them from the package barrel; add clsx + tailwind-merge deps
- Repoint all web import sites (~38 files) to @agent-paste/ui; delete the
  emptied originals
- Cross-package Tailwind content scan verified: package-only utilities
  (accent-dim, live-pulse) appear in web's built CSS through the pnpm symlink

apex conversion to Tailwind + shared components follows next.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ibrary

Unify apex + web on ONE styling system. apex was hand-written semantic CSS
(1,411 lines across base/sections/home/home-foot.css); web was Tailwind. Now
both render the SAME @agent-paste/ui components in Tailwind utilities and cannot
drift.

- Promote Wordmark into @agent-paste/ui; web Topbar/index + apex chrome render it
- Convert apex chrome, Shell, and all pages (Home/About/HowItWorks/Pricing/Legal/
  Docs) from semantic classes to inline Tailwind utilities, token-driven colors
- Delete base/sections/home/home-foot.css; apex.css keeps only the marketing-only
  effects that can't be inline utilities (scroll-reveal, live-pulse dot, gesture)
- Move the shared `.code` inline-code chip into brand globalsCss() (Prose is
  shared) so both surfaces match; regenerate ui/styles.css
- render.test.tsx: assert hrefs/structure, not class strings (test the rule, not
  the presentation) — drop vestigial content/docs-layout/head-link/docs-inline-link
  class hooks from markup
- Drop now-unused deps: @agent-paste/brand from apex, clsx/tailwind-merge from web
- Bump react/react-dom to ^19.2.7 (latest), @types to match; single React copy

Net -1063 lines. verify + per-package coverage green; apex prerenders 18 routes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-component utilities; sync theme across surfaces

Unify apex + web on the shared @agent-paste/ui design system and kill the
arbitrary-value soup in the DOM. Everything type/spacing/color/motion is now a
theme utility; structural layout literals stay (and are the only brackets left).

Scale + de-bracket
- Register the full type/leading/tracking/easing scale in the brand @theme block
  (driven from TYPE/EASE_OUT), so named utilities exist for every size, line
  height, tracking step, and the ease-out curve.
- Convert ~520 arbitrary type/leading/tracking/easing brackets to named utilities
  across apex, web, and packages/ui (710 -> 189 brackets; the rest are logged
  structural literals).
- Snap ALL spacing utilities to the integer scale {0,1,2,3,4,5,6,8,10,12,16,20,
  24,32}: no .5 half-steps, no off-rhythm integers.

Single styling authority
- Add shared <ButtonAnchor> + buttonClasses() so link CTAs and button CTAs share
  one definition; replace 5 divergent inline accent-fill anchor copies.
- Add apex marketing primitives (PageHeader/Eyebrow/SectionHeading/ProseBlock/
  RailLink + shared comparison-table classes); 6 marketing pages compose them
  instead of re-declaring the same header/section markup inline.
- apex docs carry accent splashes (section ticks, eyebrow dot, card hover, code
  chip) through the shared system; footer stays multi-column on named utilities.

Fix dropped shared-component utilities (the "missing padding" bug)
- Both apex.css and web globals.css now @source packages/ui/src. Tailwind only
  emits utilities it sees used in scanned files, so utilities unique to shared
  components (Card p-5, the lg button h-[40px]/px-4) were silently dropped and
  rendered unstyled (Cards flush against the rule, buttons with no height).

Cross-surface theme sync
- Persist the theme in a cookie scoped to the registrable parent (.agent-paste.sh)
  so apex (marketing) and web (app) share one preference; localStorage can't cross
  subdomains. Shared helpers in @agent-paste/brand, re-exported via @agent-paste/ui.
- apex inline pre-paint script + toggle and web theme-provider all read/write the
  shared agp_theme cookie. Verified bidirectional on preview.
- Derive the apex CSP theme-init hash on the fly from THEME_INIT_JS (node:crypto
  works in Workers under nodejs_compat), removing the hand-pinned hash + its
  byte-stability re-pin chore.

Env-correct preview links
- apex bakes app/api/mcp base URLs at build from AGENT_PASTE_ENV, so the preview
  build links to preview, not production. deploy.mjs now passes AGENT_PASTE_ENV
  into the apex build.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…utton wrap + section-label overlap

Make the marketing (apex) and dashboard (web) headers read as one product
by sharing the static look while each app keeps its own dynamic driver.

- New @agent-paste/ui/themeToggle: one source for the header toggle's class,
  icon set (system/dark/light SVGs), cycle order, and aria copy. apex's
  framework-free client.ts script and web's React <ThemeToggle> both render the
  identical button + glyph and write the same agp_theme cookie, so the two
  toggles cannot drift. apex's toggle gains the "system" state it lacked.
- apex header toggle is now the shared icon-only square button (was a bordered
  "Theme" chip); web is unchanged in behavior but re-skinned from the shared
  source instead of lucide icons + bespoke classes.

Bug fixes (both via the shared primitives, so every call site is fixed at once):
- buttonClasses: add whitespace-nowrap so fixed-height small buttons (e.g.
  "Copy URL") never wrap and overflow their height.
- SectionLabel: add an `action` slot so a trailing link sits past the hairline
  rule instead of overlapping it; dashboard Recent/Activity headers use it
  (kills the "ALL ARTIFACTS" / rule overlap).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…-cccdcc

# Conflicts:
#	apps/web/src/components/claim/ClaimSuccessPanel.tsx
The format check ignored only root-level .wrangler/.turbo (e.g. `!.wrangler`),
not nested ones, so a build artifact like apps/web/.wrangler/deploy/config.json
tripped `biome format` and failed the local gate + pre-push hook. Mirror the
recursive `!dist` + `!**/dist` pattern already used for dist.

Issue: AP-276
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@isuttell, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 20 minutes and 54 seconds. Learn how PR review limits work.

To continue reviewing without waiting, purchase usage credits in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 44f578b7-2b9f-47c3-9b4d-36d142b9ddcb

📥 Commits

Reviewing files that changed from the base of the PR and between d2439f7 and 37b76d2.

📒 Files selected for processing (4)
  • apps/apex/src/pages/PricingPage.tsx
  • packages/ui/src/components/Button.tsx
  • packages/ui/src/components/ButtonAnchor.tsx
  • scripts/deploy-pr-preview.mjs
📝 Walkthrough

Walkthrough

The PR adds a shared UI/brand package, switches Apex to prerendered SSR output with a new server entry, and migrates the web app to shared components, shared theme cookies, and tokenized styling.

Changes

Shared design system rollout

Layer / File(s) Summary
Brand and UI package foundation
packages/brand/*, packages/ui/*
Brand tokens, theme-cookie helpers, shared UI primitives, and generated CSS are added or updated for both apps.
Apex content and page surfaces
apps/apex/src/app/*, apps/apex/src/pages/*, apps/apex/src/routes.tsx, apps/apex/src/docs/*
Apex marketing pages, route metadata, docs rendering, and shared chrome are rebuilt around the new page/component model.
Apex build, server, and deployment
apps/apex/src/server.ts, apps/apex/scripts/prerender.mjs, apps/apex/package.json, apps/apex/wrangler.jsonc, scripts/deploy*.mjs
Apex now prerenders static output, serves through a new worker entry, and deploys with the updated build/runtime paths and security headers.
Web app shared UI migration
apps/web/src/*, apps/web/test/*, apps/web/package.json, apps/web/src/styles/globals.css
The web app switches to shared UI imports, cookie-based theme persistence, and the new tokenized Tailwind classes across components, routes, and tests.
Docs and workspace tooling updates
docs/*, biome.json, knip.json, turbo.json, vitest.shared.config.ts
Documentation and workspace tooling are updated to reflect the shared package layout and new coverage/build inputs.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~90+ minutes

Possibly related issues

  • zaks-io/agent-paste#362 — This PR implements the shared design-system unification across brand tokens, Apex, and web, which matches the issue’s reported scope.

Possibly related PRs

Poem

🐰 I hop through tokens, neat and bright,
New pages bloom in shared moonlight.
Cookie crumbs and CSS sprites,
Build the burrow, web feels right.
Apex prunes, the UI sings—
Vermilion carrots, shiny things.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/quizzical-bohr-cccdcc

Comment thread apps/apex/src/render.test.tsx Fixed
Comment thread packages/ui/src/components/Prose.tsx Fixed
Comment thread packages/ui/src/components/Prose.tsx Fixed
…assertion

CodeQL flagged two regexes on this branch:

- packages/ui Prose PROSE_PATTERN was polynomial ("Polynomial regular expression
  used on uncontrolled data"): the naive [^\]]+ / [^)]+ classes let the engine
  backtrack quadratically on adversarial input like "[" + "[\\".repeat(n)
  (measured ~2s at 50k chars). Exclude each capture's OWN opening delimiter
  ([^\][] and [^()]) so the alternatives are unambiguous and the match is linear
  (~0.2ms at 50k). Tokenization of valid prose is byte-identical. Prose is shared
  shipping code in @agent-paste/ui, so this is a real fix, not a suppression.
  Add deterministic tests: inner-pair-wins on nested brackets + no over-match on
  an adversarial bracket run (no wall-clock assertion, so it can't flake).

- apps/apex render.test.tsx counted inline scripts with /<script>/g; CodeQL's
  "bad HTML filtering regexp" rule wants case-insensitivity. Use /<script>/gi —
  the count is over our own rendered SSG output, but the i flag is strictly safer
  and clears the alert.

Issue: AP-276
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/apex/src/copy.ts`:
- Around line 1-14: The prerendered URLs in apps/apex/src/copy.ts are determined
by process.env.AGENT_PASTE_ENV (ENV) but deploy-pr-preview.mjs does not pass
AGENT_PASTE_ENV into the apex build, so preview builds bake production links;
update the apex build invocation in deploy-pr-preview.mjs to pass
AGENT_PASTE_ENV: "preview" (or call/reuse apexBuildEnv()) via the env option you
give to spawnCommand so the child process sees AGENT_PASTE_ENV and
apps/apex/src/copy.ts will produce preview URLs (look for spawnCommand and
apexBuildEnv references to implement the change).

In `@apps/apex/src/pages/PricingPage.tsx`:
- Around line 38-56: The Pro plan uses a different fallback for its amount
(proPrice?.amount ?? "") than the Free plan (freePrice?.amount ?? "$0"), causing
an empty price display; update the Pro rendering to use a consistent fallback
(e.g., proPrice?.amount ?? "$0" or a shared placeholder like "Contact us") or
centralize price formatting into a helper used by both freePrice and proPrice
(referencing PLANS.free.name, PLANS.pro.name, freePrice, proPrice in the
PricingPage component) so the price span always shows a sensible default rather
than an empty string.

In `@apps/web/src/components/chrome/command-palette/CommandPaletteSearch.tsx`:
- Line 40: The input padding change from pl-[34px] to pl-8 reduces the gap
between the Search icon (left-3, size={16}) and the input text to ~4px; confirm
against the design and either (A) restore the explicit padding-left value (e.g.,
pl-[34px]) on the input in CommandPaletteSearch or (B) adjust the icon
positioning/size (the Search icon usage with left-3 and size={16}) so the right
edge sits ~28px and yields the intended ~6px gap—pick one approach and update
the input className or icon container accordingly so the spacing matches design.

In `@packages/brand/src/index.ts`:
- Around line 144-534: globalsCss() is too large and should be split into
focused helpers for readability and testability; create small functions like
themeVarsCss(), themeDefinitionsCss(), baseStylesCss(), and keyframesCss() that
return the corresponding CSS blocks (reusing fontFaceCss() for the font faces),
move the root + [data-theme="dark"/light] variable declarations into
themeVarsCss(), move the `@theme` block into themeDefinitionsCss(), move the
element/base rules into baseStylesCss(), and move all `@keyframes` and small
utility classes into keyframesCss(), then make globalsCss() assemble them in
order (keeping the initial `@import "tailwindcss";` and `${fontFaceCss()}`
calls) so callers of globalsCss() see the exact same output but the
implementation is modular and testable.

In `@packages/ui/src/components/Button.tsx`:
- Around line 13-40: The Button component currently uses forwardRef
(forwardRef<HTMLButtonElement, Props>) — update it to the React 19 ref-as-prop
pattern by removing forwardRef and accepting a ref prop directly on the Props
interface (e.g., ref?: React.Ref<HTMLButtonElement>), update the function
signature for Button to take props including ref (instead of the forwarded ref
parameter), and pass that ref into the underlying <button> element; retain
existing props like variant, size, loading, disabled, type and keep using
buttonClasses and data-loading/aria-busy behavior unchanged.

In `@packages/ui/src/components/Prose.tsx`:
- Around line 15-23: The regex in PROSE_PATTERN used by parseProse is vulnerable
to catastrophic backtracking; update PROSE_PATTERN to a non-backtracking-safe
form (e.g., make the quantified groups non-greedy so they cannot cause
exponential backtracking: change ([^\]]+) to ([^\]]+?) and ([^)]+) to ([^)]+?)
and `([^`]+)` to `([^`]+?)`), and add a defensive input length check at the
start of parseProse to bail out or truncate overly long inputs before running
the regex to further mitigate ReDoS risk.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: ce2bae97-5abf-4eba-9a84-ccab85690384

📥 Commits

Reviewing files that changed from the base of the PR and between 99bc295 and 7910c98.

⛔ Files ignored due to path filters (10)
  • apps/apex/public/fonts/BricolageGrotesque-Variable.woff2 is excluded by !**/*.woff2
  • apps/apex/public/fonts/CabinetGrotesk-Variable.woff2 is excluded by !**/*.woff2
  • apps/apex/public/fonts/IBMPlexMono-Medium.woff2 is excluded by !**/*.woff2
  • apps/apex/public/fonts/IBMPlexMono-Regular.woff2 is excluded by !**/*.woff2
  • apps/apex/public/fonts/SplineSansMono-Variable.woff2 is excluded by !**/*.woff2
  • apps/apex/public/fonts/Switzer-Variable.woff2 is excluded by !**/*.woff2
  • apps/web/public/fonts/CabinetGrotesk-Variable.woff2 is excluded by !**/*.woff2
  • apps/web/public/fonts/SplineSansMono-Variable.woff2 is excluded by !**/*.woff2
  • apps/web/public/fonts/Switzer-Variable.woff2 is excluded by !**/*.woff2
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (164)
  • apps/apex/package.json
  • apps/apex/scripts/prerender.mjs
  • apps/apex/src/agents.ts
  • apps/apex/src/app/Shell.tsx
  • apps/apex/src/app/chrome.tsx
  • apps/apex/src/app/scripts.ts
  • apps/apex/src/build/text-assets.ts
  • apps/apex/src/client.ts
  • apps/apex/src/components/SourceRepository.tsx
  • apps/apex/src/components/about.tsx
  • apps/apex/src/components/chrome.tsx
  • apps/apex/src/components/docs.tsx
  • apps/apex/src/components/home.tsx
  • apps/apex/src/components/how-it-works.tsx
  • apps/apex/src/components/legal.tsx
  • apps/apex/src/components/marketing.tsx
  • apps/apex/src/components/pricing.tsx
  • apps/apex/src/components/source-repository.tsx
  • apps/apex/src/copy.ts
  • apps/apex/src/docs/markdown.ts
  • apps/apex/src/docs/pages/artifact-model.ts
  • apps/apex/src/docs/pages/billing.ts
  • apps/apex/src/docs/pages/cli.ts
  • apps/apex/src/docs/pages/dashboard.ts
  • apps/apex/src/docs/pages/ephemeral.ts
  • apps/apex/src/docs/pages/getting-started.ts
  • apps/apex/src/docs/pages/limits.ts
  • apps/apex/src/docs/pages/mcp.ts
  • apps/apex/src/docs/pages/rest-api.ts
  • apps/apex/src/docs/pages/safety.ts
  • apps/apex/src/docs/pages/sharing.ts
  • apps/apex/src/docs/registry.ts
  • apps/apex/src/entry-server.test.ts
  • apps/apex/src/entry-server.tsx
  • apps/apex/src/home-styles.ts
  • apps/apex/src/index.test.ts
  • apps/apex/src/index.ts
  • apps/apex/src/legal-privacy.ts
  • apps/apex/src/legal-terms.ts
  • apps/apex/src/legal.ts
  • apps/apex/src/llms.ts
  • apps/apex/src/meta.ts
  • apps/apex/src/pages/AboutPage.tsx
  • apps/apex/src/pages/DocsIndexPage.tsx
  • apps/apex/src/pages/DocsPageView.tsx
  • apps/apex/src/pages/HomePage.tsx
  • apps/apex/src/pages/HowItWorksPage.tsx
  • apps/apex/src/pages/LegalPage.tsx
  • apps/apex/src/pages/PricingPage.tsx
  • apps/apex/src/plan-tiers.test.ts
  • apps/apex/src/pricing.ts
  • apps/apex/src/render.test.tsx
  • apps/apex/src/routes.ts
  • apps/apex/src/routes.tsx
  • apps/apex/src/security-headers.test.ts
  • apps/apex/src/security-headers.ts
  • apps/apex/src/server.test.ts
  • apps/apex/src/server.ts
  • apps/apex/src/styles.ts
  • apps/apex/src/styles/apex.css
  • apps/apex/tsconfig.json
  • apps/apex/vite.config.ts
  • apps/apex/vitest.config.ts
  • apps/apex/wrangler.jsonc
  • apps/web/README.md
  • apps/web/package.json
  • apps/web/src/components/access-links/AccessLinkLockdownToggle.tsx
  • apps/web/src/components/access-links/AccessLinksTable.tsx
  • apps/web/src/components/access-links/CreateAccessLinkPanel.tsx
  • apps/web/src/components/access-links/MintedUrlReveal.tsx
  • apps/web/src/components/admin/AbuseTriageGuide.tsx
  • apps/web/src/components/admin/LockdownForm.tsx
  • apps/web/src/components/admin/LockdownList.tsx
  • apps/web/src/components/admin/OperatorEventsPanel.tsx
  • apps/web/src/components/billing/BillingHero.tsx
  • apps/web/src/components/billing/BillingNote.tsx
  • apps/web/src/components/billing/InvoiceTable.tsx
  • apps/web/src/components/billing/PlanPanel.tsx
  • apps/web/src/components/billing/SubscriptionPanel.tsx
  • apps/web/src/components/chrome/NavigationProgress.tsx
  • apps/web/src/components/chrome/Sidebar.tsx
  • apps/web/src/components/chrome/SignOutForm.tsx
  • apps/web/src/components/chrome/ThemeToggle.tsx
  • apps/web/src/components/chrome/Topbar.tsx
  • apps/web/src/components/chrome/Wordmark.tsx
  • apps/web/src/components/chrome/command-palette/CommandPaletteDialogView.tsx
  • apps/web/src/components/chrome/command-palette/CommandPaletteOption.tsx
  • apps/web/src/components/chrome/command-palette/CommandPaletteResults.tsx
  • apps/web/src/components/chrome/command-palette/CommandPaletteSearch.tsx
  • apps/web/src/components/chrome/command-palette/CommandPaletteTrigger.tsx
  • apps/web/src/components/claim/ClaimGuestGate.tsx
  • apps/web/src/components/claim/ClaimSuccessPanel.tsx
  • apps/web/src/components/dashboard/FirstRunKeyCard.tsx
  • apps/web/src/components/dashboard/RecentArtifacts.tsx
  • apps/web/src/components/dashboard/RecentAudit.tsx
  • apps/web/src/components/dashboard/UsagePolicyCard.tsx
  • apps/web/src/components/keys/KeyCreateForm.tsx
  • apps/web/src/components/keys/KeysTable.tsx
  • apps/web/src/components/keys/NewKeySecretCard.tsx
  • apps/web/src/components/settings/SettingsForm.tsx
  • apps/web/src/components/theme-provider.tsx
  • apps/web/src/components/ui/Button.tsx
  • apps/web/src/components/ui/DataTable.tsx
  • apps/web/src/components/ui/EmptyState.tsx
  • apps/web/src/components/ui/ErrorBanner.tsx
  • apps/web/src/components/ui/HeroStat.tsx
  • apps/web/src/components/ui/Identifier.tsx
  • apps/web/src/components/ui/Input.tsx
  • apps/web/src/components/ui/PageHeader.tsx
  • apps/web/src/components/ui/RevokedActionPlaceholder.tsx
  • apps/web/src/components/ui/StatBand.tsx
  • apps/web/src/components/ui/StateBadge.tsx
  • apps/web/src/components/ui/ToastList.tsx
  • apps/web/src/lib/artifact-status.ts
  • apps/web/src/lib/revocable-entity-state.ts
  • apps/web/src/routes/__root.tsx
  • apps/web/src/routes/_authed.artifacts.$artifactId.tsx
  • apps/web/src/routes/_authed.artifacts.index.tsx
  • apps/web/src/routes/_authed.audit.tsx
  • apps/web/src/routes/_authed.claim.tsx
  • apps/web/src/routes/_authed.keys.tsx
  • apps/web/src/routes/_authed.settings.tsx
  • apps/web/src/routes/_authed.tsx
  • apps/web/src/routes/al.$publicId.tsx
  • apps/web/src/routes/healthz.tsx
  • apps/web/src/routes/index.tsx
  • apps/web/src/styles/globals.css
  • apps/web/test/brand-tokens-parity.test.ts
  • apps/web/test/chrome.test.tsx
  • apps/web/test/theme-provider.test.tsx
  • apps/web/test/ui-primitives.test.tsx
  • biome.json
  • docs/development.md
  • docs/marketing-brand-guide.md
  • docs/ops/status/coverage.md
  • docs/specs/style-guide.md
  • knip.json
  • packages/brand/README.md
  • packages/brand/src/index.test.ts
  • packages/brand/src/index.ts
  • packages/brand/src/theme-cookie.test.ts
  • packages/brand/src/theme-cookie.ts
  • packages/brand/src/tokens.ts
  • packages/ui/README.md
  • packages/ui/package.json
  • packages/ui/src/components/Badge.tsx
  • packages/ui/src/components/Button.tsx
  • packages/ui/src/components/ButtonAnchor.tsx
  • packages/ui/src/components/Card.tsx
  • packages/ui/src/components/Prose.tsx
  • packages/ui/src/components/Table.tsx
  • packages/ui/src/components/Wordmark.tsx
  • packages/ui/src/components/buttonClasses.ts
  • packages/ui/src/components/themeToggle.ts
  • packages/ui/src/index.ts
  • packages/ui/src/lib/cn.ts
  • packages/ui/src/styles/globals.css
  • packages/ui/test/globals-css.test.ts
  • packages/ui/test/prose.test.ts
  • packages/ui/tsconfig.json
  • scripts/deploy-pr-preview.mjs
  • scripts/deploy.mjs
  • turbo.json
  • vitest.shared.config.ts
💤 Files with no reviewable changes (17)
  • apps/apex/src/components/pricing.tsx
  • apps/apex/src/components/legal.tsx
  • apps/apex/src/home-styles.ts
  • apps/apex/src/components/source-repository.tsx
  • apps/apex/src/components/how-it-works.tsx
  • apps/apex/src/styles.ts
  • apps/apex/src/components/docs.tsx
  • apps/web/src/components/chrome/Wordmark.tsx
  • apps/web/test/brand-tokens-parity.test.ts
  • apps/apex/src/index.test.ts
  • apps/apex/src/components/home.tsx
  • apps/apex/src/legal.ts
  • apps/apex/src/components/about.tsx
  • apps/web/src/components/ui/Button.tsx
  • apps/apex/src/index.ts
  • apps/apex/src/components/chrome.tsx
  • apps/apex/src/routes.ts

Comment thread apps/apex/src/copy.ts
Comment thread apps/apex/src/pages/PricingPage.tsx
Comment thread packages/brand/src/index.ts
Comment thread packages/ui/src/components/Button.tsx Outdated
Comment thread packages/ui/src/components/Prose.tsx Outdated
Comment thread packages/ui/test/prose.test.ts
…prop; pricing fallback

Address CodeRabbit review on #454:

- deploy-pr-preview.mjs: the apex prerender build ran with only BILLING_ENABLED,
  so AGENT_PASTE_ENV was unset and copy.ts baked PRODUCTION cross-app URLs into
  every per-PR preview's HTML. Pass AGENT_PASTE_ENV=preview (the standing-preview
  deploy.mjs path already did this; the PR-preview path was missed). [Major]
- Button + ButtonAnchor: drop forwardRef for React 19's ref-as-prop. These are
  new components and the repo bans unnecessary legacy patterns; no call site
  passed a ref, so this is API-compatible. [Nitpick, per coding guidelines]
- PricingPage: the Pro price fell back to "" (rendering a bare "/ mo") while Free
  fell back to "$0"; use "—" for both missing-price fallbacks. Real prices are
  unaffected. [Minor]

Issue: AP-276
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@isuttell isuttell merged commit 8e92733 into main Jun 9, 2026
9 checks passed
@isuttell isuttell deleted the claude/quizzical-bohr-cccdcc branch June 9, 2026 02:29
@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown

agent-paste PR preview resources were cleaned up. The shared Preview GitHub Environment is retained for future preview deploys.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants