The token redesign couldn't touch static rasters/config — these were still the
old claw mark + old coral. Regenerate favicon (icon.svg + icon.png) and PWA
icons (192/512) as the node-mesh glyph; manifest theme_color #f96565→#ff6f61,
background #121212→#08080a; refresh the description/tagline.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The frontend is documented as a single image whose AUTH_MODE env var
selects local vs Clerk auth per deployment (docs/clerk.md). But the root
layout and /login read AUTH_MODE during render with no request-time
signal, so Next 16 statically prerendered them at build time in the
build host's mode (local). The deployed image then served the local
login form forever, ignoring AUTH_MODE=clerk at runtime — ClerkProvider
and <SignIn/> never appeared.
Add `await connection()` (the v16 way to read env at request time) in
the layout's IdentityProvider and in /login so both render per-request
and honor the runtime AUTH_MODE.
Also add a root .dockerignore: the repo had none, so every image build
shipped the 67GB Rust target/ dir as build context.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
Replace the hand-rolled @theme color block with a real shadcn init shape:
bare :root (light) + .dark (dark) tokens mapped to --color-* via
@theme inline, plus the missing semantic/chart/radius tokens. --accent
is now neutral (#262626) to match WorkClaw; the ~16 coral-via-accent
usages migrate to the dedicated `coral` brand token so they stay coral.
Adds cn() (clsx + tailwind-merge) and components.json so future
`npx shadcn add` works. Clawmates-specific tokens (coral brand,
marketing palette, measured shadows, motion, layout, type scale) are
preserved verbatim in a separate @theme block. Root <html> gains `dark`
(app/login read .dark; marketing stays light via explicit colors).
We do NOT add shadcn's Button/Card/etc. — they'd conflict with the
existing measured-to-WorkClaw components.
Verified value-preserving: typecheck/lint/86 unit/31 E2E all green, and
all 6 visual baselines pass with no diff. Compiled + live CSS confirm
bg-accent→#262626 (neutral), text-coral→#f96565, chart tokens present.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The <body> carried Tailwind's `antialiased` (-webkit-font-smoothing:
antialiased), which inherits through the whole tree and renders every
chat/message/UI text thinner & lighter than WorkClaw. WorkClaw leaves the
browser default (`auto`), giving the crisper/heavier weight. Removed the
class — body is now just `min-h-full`; computed -webkit-font-smoothing is
`auto`. The font itself was always 14px/400 Geist; only the smoothing
differed. Global rendering change → regenerated all 7 visual baselines;
full suite (37) green.
Co-Authored-By: Claude Fable 5 <[email protected]>
Full-depth rename per the approved plan; the 'claw' product vocabulary
(claws, /claws routes, clawId, Claw Chat) stays — it is now the brand.
- Display brand: Clawmates (manifest, titles, hero, login/rail logo
'clawmates'); default host app.clawmates.work; registry
ghcr.io/clawmates
- Crates tc-* -> cm-* (16 crates + all imports); binaries
clawmates-server/broker/bundler; images clawmates/*; env prefix
CLAWMATES_* (+ CM_TEST_DATABASE_URL / CM_LIVE_LLM); config
clawmates.toml; helm chart deploy/helm/clawmates with clawmates-*
resources; db names clawmates*; sockets /run/clawmates; cookie
cm_session; kind cluster clawmates-test; seccomp node profile
clawmates-agent-profile.json
- All 9 Playwright brand assertions updated in lockstep; historical
spec document left untouched as the only remaining 'TeamClaw'
- Local env migrated: dev pg clawmates-dev-pg/clawmates_dev, shared
test server clawmates-test-pg, kind cluster recreated with image +
profile, compose images rebuilt under clawmates/*
Verified end to end: 161 Rust + 68 frontend tests, 29 Playwright
journeys, 4 live kind tests, helm/install/LOC/placeholder gates, and
the clean-room install rehearsal serving the clawmates login page from
a signed bundle of the rebuilt images.
Co-Authored-By: Claude Fable 5 <[email protected]>
- src/lib/auth/bearer.ts is the single identity dispatch for both
server-side token consumers (RSC apiFetch and the /api proxy route):
local -> httpOnly tc_session cookie; clerk -> Clerk getToken() session
JWT. The Clerk SDK is imported lazily, so the air-gapped/local path
never loads it
- Runtime env (AUTH_MODE / CLERK_PUBLISHABLE_KEY / CLERK_SECRET_KEY),
deliberately NOT build-time NEXT_PUBLIC_*: the same standalone image
serves both deployment targets
- Conditional <ClerkProvider> in the root layout (publishableKey passed
at render from runtime env); /login renders Clerk's <SignIn /> in
clerk mode and the local form otherwise; proxy.ts middleware delegates
to clerkMiddleware() only when active
- Helm: frontend deployment injects the Clerk keys from a Secret when
auth.mode=clerk
- mode.ts unit-tested (default local, exact-match clerk, loud failure
without the publishable key); the local path stays proven by all 29
journeys; the Clerk branch is thin delegation to the SDK, exercised in
deployment smoke per docs/clerk.md
157 Rust + 68 frontend tests + 29 Playwright journeys.
Co-Authored-By: Claude Fable 5 <[email protected]>
- PWA (§16): hand-rolled 60-line service worker (network-first pages with
offline fallback, cache-first hashed statics, /api NEVER touched — SSE
and approvals stay live), app manifest with §2 identity, stdlib-
generated coral claw icons, prod-only registration. E2E asserts
manifest, real PNG icons, an ACTIVATED service worker, and the /api
bypass. (Serwist was tried and dropped: its webpack plugin fights
Next 16's Turbopack builds; sixty lines we own beat a plugin we fight.)
- Route motion (§3): (workspace) template re-mounts per navigation with a
quiet fade-rise, zeroed under prefers-reduced-motion. The a11y sweep
now settles running animations before scanning — axe was reading
mid-fade opacity as contrast failures
- OAuth browser flow vs REAL dex: the e2e harness boots dexidp/dex with
static client + password; the journey drives the actual dex login form
from /api/apps/oauth/start through the callback 303 and asserts the
app reads connected (closing the P4 deferral honestly)
- release.yml: tag-triggered — builds all four images + postgres, saves
tarballs, assembles the SIGNED air-gapped bundle (compose, config,
migrations, seccomp profile, installer, bundler binary), derives the
public key via the new Could not find command "pubkey". subcommand (tested), verifies
the bundle customer-style with the public half only, attaches tarball
+ public key to the GitHub release
153 Rust + 63 frontend tests + 29 Playwright journeys.
Co-Authored-By: Claude Fable 5 <[email protected]>