From f1050671dc593955b574aea92a860e2898a31fee Mon Sep 17 00:00:00 2001 From: MoFadel <101219769+MoFadel26@users.noreply.github.com> Date: Thu, 29 Oct 2026 19:38:47 +0300 Subject: [PATCH 01/13] chore: remove t3code orchestration prompt --- t3code-orchestration.md | 131 ---------------------------------------- 1 file changed, 131 deletions(-) delete mode 100644 t3code-orchestration.md diff --git a/t3code-orchestration.md b/t3code-orchestration.md deleted file mode 100644 index ae933d6..0000000 --- a/t3code-orchestration.md +++ /dev/null @@ -1,131 +0,0 @@ -# T3 Code Master Prompt — Go Real-Time Log Analytics Engine - -## Role -You are the orchestrator. Run **three agents in parallel**, each in its **own git worktree and branch**. Do not run tracks sequentially. Do not let agents edit files outside their track. - -## Model Assignment -| Thread | Model | -|---|---| -| Orchestrator (setup, PR review, merge) | Claude Opus 5 | -| Agent 1 — PostgreSQL Schema | Claude Sonnet 5 | -| Agent 2 — Go API + Worker Pool | Claude Opus 5 | -| Agent 3 — Docker + Kubernetes | Claude Sonnet 5 | - -Start each agent thread with its assigned model. - -## Environment -- Host: MacBook M1 Pro (`darwin/arm64`) -- Go 1.23+, PostgreSQL 16, Docker (buildx), Kubernetes (kind or k3d locally) -- Images must build for `linux/arm64` and `linux/amd64` - -## Repo Layout (contract shared by all agents) -``` -/db/ -> Agent 1 -/cmd/api/ -> Agent 2 -/internal/ -> Agent 2 -/deploy/docker/ -> Agent 3 -/deploy/k8s/ -> Agent 3 -``` - -## Shared Contracts (fixed before agents start) -- Log payload: - ```json - { "tenant_id": "uuid", "ts": "RFC3339Nano", "level": "string", "source": "string", "message": "string", "attrs": {} } - ``` -- API port: `8080`. Health: `GET /healthz` (liveness), `GET /readyz` (readiness). -- Env vars: `DATABASE_URL`, `WORKER_COUNT`, `QUEUE_SIZE`, `SHUTDOWN_TIMEOUT` (default `25s`). -- App must exit cleanly on `SIGTERM` within `SHUTDOWN_TIMEOUT`. - -## Worktree Setup (execute first, then launch all agents at once) -```bash -git checkout main && git pull -git worktree add ../logengine-schema -b feat/pg-schema -git worktree add ../logengine-api -b feat/go-api -git worktree add ../logengine-deploy -b feat/docker-k8s -``` - ---- - -## Agent 1 — PostgreSQL Schema -**Worktree:** `../logengine-schema` · **Branch:** `feat/pg-schema` · **Scope:** `/db/` only - -Tasks: -1. Create `logs` table with composite primary key `(tenant_id, ts, id)`. - - `tenant_id UUID NOT NULL`, `ts TIMESTAMPTZ NOT NULL`, `id BIGINT GENERATED ALWAYS AS IDENTITY` - - `level TEXT`, `source TEXT`, `message TEXT`, `attrs JSONB` -2. Range-partition by `ts` (daily). Add a function to create future partitions. -3. Indexes for **selection** and **projection**: - - Covering index: `(tenant_id, ts DESC) INCLUDE (level, source)` for index-only scans. - - `(tenant_id, level, ts DESC)` for level filters. - - GIN on `attrs` (`jsonb_path_ops`). - - BRIN on `ts` for large range scans. -4. Migrations in `/db/migrations` (golang-migrate format, up + down). -5. `/db/queries.sql` with sample tenant+time-range queries and their `EXPLAIN ANALYZE` expectations. -6. Seed script for 1M rows across 10 tenants. - -Done when: migrations apply and roll back cleanly; sample queries use index-only scans. - ---- - -## Agent 2 — Go REST API + Worker Pool -**Worktree:** `../logengine-api` · **Branch:** `feat/go-api` · **Scope:** `/cmd/api/`, `/internal/`, `go.mod` - -Tasks: -1. `POST /v1/logs` accepts a single object or array. Validate against the shared contract. -2. Push validated logs into a **buffered channel** (`QUEUE_SIZE`). - - Channel full → return `503` with `Retry-After`. Never block the handler. -3. **Worker pool** (`WORKER_COUNT` goroutines) consumes the channel, batches (size or time flush), writes with `pgx` `CopyFrom`. -4. **Graceful shutdown** on `SIGTERM`/`SIGINT` via `signal.NotifyContext`: - 1. Set readiness to failing (`/readyz` → 503). - 2. `http.Server.Shutdown(ctx)` — stop accepting requests. - 3. `close(channel)` — workers drain remaining items. - 4. `sync.WaitGroup` wait, bounded by `SHUTDOWN_TIMEOUT`. - 5. Flush final batches, close DB pool, exit 0. -5. Structured logging (`log/slog`), Prometheus metrics (queue depth, batch latency, dropped count). -6. Tests: unit tests for handler/backpressure, integration test with testcontainers Postgres, shutdown test proving zero loss of accepted logs. Run with `-race`. - -Done when: `go test -race ./...` passes; SIGTERM under load loses no accepted logs. - ---- - -## Agent 3 — Docker + Kubernetes -**Worktree:** `../logengine-deploy` · **Branch:** `feat/docker-k8s` · **Scope:** `/deploy/` only - -### Dockerfile (`/deploy/docker/Dockerfile`) -1. Stage 1: `golang:1.23-alpine`, `CGO_ENABLED=0`, use `--platform=$BUILDPLATFORM` with `TARGETOS/TARGETARCH` for cross-builds from M1. -2. Stage 2: `gcr.io/distroless/static:nonroot`. -3. **Signal propagation:** use exec-form `ENTRYPOINT ["/app/api"]` so the binary is PID 1 and receives `SIGTERM` directly. No shell wrapper. If a wrapper is ever needed, use `tini`. -4. `STOPSIGNAL SIGTERM`, non-root user, `EXPOSE 8080`. -5. `docker buildx build --platform linux/arm64,linux/amd64` command in a `Makefile`. - -### Kubernetes (`/deploy/k8s/`) -1. `Deployment` with **zero-downtime rolling update**: - - `strategy.rollingUpdate: maxUnavailable: 0, maxSurge: 1` - - `minReadySeconds: 5` - - `readinessProbe` on `/readyz`, `livenessProbe` on `/healthz`, `startupProbe` - - `lifecycle.preStop: sleep 5` (lets endpoints deregister before SIGTERM) - - `terminationGracePeriodSeconds: 30` (greater than `SHUTDOWN_TIMEOUT`) -2. **Shared network namespace:** add a sidecar (e.g. log/metrics forwarder) in the same pod reaching the API over `localhost:8080`. Document that pod containers share one network namespace. -3. `Service` (ClusterIP), `PodDisruptionBudget` (`minAvailable: 1`), `HorizontalPodAutoscaler`, `ConfigMap` + `Secret` for env vars. -4. Kustomize base + `overlays/local` for kind/k3d. - -Done when: `kubectl rollout restart` under load shows zero failed requests (verify with `hey` or `k6`). - ---- - -## Merge Plan (T3 Code PR flow) -1. Each agent commits on its branch and opens a PR to `main` through T3 Code's built-in PR feature. -2. Merge order: `feat/pg-schema` → `feat/go-api` → `feat/docker-k8s`. -3. Before each merge: rebase on `main`, run `go test -race ./...`, `docker buildx build`, `kubectl apply --dry-run=server`. -4. After all merges: run end-to-end test (kind cluster + Postgres + load test + rolling restart). -5. Remove worktrees: - ```bash - git worktree remove ../logengine-schema - git worktree remove ../logengine-api - git worktree remove ../logengine-deploy - ``` - -## Rules for All Agents -- Stay inside your scope. Contract changes require orchestrator approval. -- Small commits, conventional commit messages. -- Report blockers immediately; do not guess across tracks. From 1e2fce879f14d04d61b7a4e633667599459bd473 Mon Sep 17 00:00:00 2001 From: MoFadel <101219769+MoFadel26@users.noreply.github.com> Date: Thu, 29 Oct 2026 19:38:47 +0300 Subject: [PATCH 02/13] chore: remove DESIGN.md Drop the comments in the UI stylesheet that pointed at it. --- DESIGN.md | 548 ---------------------------------- internal/ui/assets/index.html | 8 +- 2 files changed, 4 insertions(+), 552 deletions(-) delete mode 100644 DESIGN.md diff --git a/DESIGN.md b/DESIGN.md deleted file mode 100644 index 88bcd11..0000000 --- a/DESIGN.md +++ /dev/null @@ -1,548 +0,0 @@ ---- -version: alpha -name: Linear-design-analysis -description: "A near-black product-focused marketing canvas built around #010102 (the deepest dark surface of any tool in this collection), light gray text (#f7f8f8), and the signature Linear lavender-blue (#5e6ad2) used as the single chromatic accent. The system reads as software-craft documentation: dense, technical, and quietly luxurious. Display type is set in the Linear custom sans (SF Pro Display fallback) at 500–700 with measured negative tracking. Cards live as charcoal panels (#0f1011) with hairline borders. The accent lavender appears on the brand mark, focus rings, and a few intentional CTAs — never decoratively. Page rhythm leans on product UI screenshots framed in dark panels rather than atmospheric color." - -colors: - primary: "#5e6ad2" - on-primary: "#ffffff" - primary-hover: "#828fff" - primary-focus: "#5e69d1" - ink: "#f7f8f8" - ink-muted: "#d0d6e0" - ink-subtle: "#8a8f98" - ink-tertiary: "#62666d" - canvas: "#010102" - surface-1: "#0f1011" - surface-2: "#141516" - surface-3: "#18191a" - surface-4: "#191a1b" - hairline: "#23252a" - hairline-strong: "#34343a" - hairline-tertiary: "#3e3e44" - inverse-canvas: "#ffffff" - inverse-surface-1: "#f5f6f6" - inverse-surface-2: "#f6f7f7" - inverse-ink: "#000000" - brand-secure: "#7a7fad" - semantic-success: "#27a644" - semantic-overlay: "#000000" - -typography: - display-xl: - fontFamily: Linear Display - fontSize: 80px - fontWeight: 600 - lineHeight: 1.05 - letterSpacing: -3.0px - display-lg: - fontFamily: Linear Display - fontSize: 56px - fontWeight: 600 - lineHeight: 1.10 - letterSpacing: -1.8px - display-md: - fontFamily: Linear Display - fontSize: 40px - fontWeight: 600 - lineHeight: 1.15 - letterSpacing: -1.0px - headline: - fontFamily: Linear Display - fontSize: 28px - fontWeight: 600 - lineHeight: 1.20 - letterSpacing: -0.6px - card-title: - fontFamily: Linear Display - fontSize: 22px - fontWeight: 500 - lineHeight: 1.25 - letterSpacing: -0.4px - subhead: - fontFamily: Linear Display - fontSize: 20px - fontWeight: 400 - lineHeight: 1.40 - letterSpacing: -0.2px - body-lg: - fontFamily: Linear Text - fontSize: 18px - fontWeight: 400 - lineHeight: 1.50 - letterSpacing: -0.1px - body: - fontFamily: Linear Text - fontSize: 16px - fontWeight: 400 - lineHeight: 1.50 - letterSpacing: -0.05px - body-sm: - fontFamily: Linear Text - fontSize: 14px - fontWeight: 400 - lineHeight: 1.50 - letterSpacing: 0 - caption: - fontFamily: Linear Text - fontSize: 12px - fontWeight: 400 - lineHeight: 1.40 - letterSpacing: 0 - button: - fontFamily: Linear Text - fontSize: 14px - fontWeight: 500 - lineHeight: 1.20 - letterSpacing: 0 - eyebrow: - fontFamily: Linear Text - fontSize: 13px - fontWeight: 500 - lineHeight: 1.30 - letterSpacing: 0.4px - mono: - fontFamily: Linear Mono - fontSize: 13px - fontWeight: 400 - lineHeight: 1.50 - letterSpacing: 0 - -rounded: - xs: 4px - sm: 6px - md: 8px - lg: 12px - xl: 16px - xxl: 24px - pill: 9999px - full: 9999px - -spacing: - xxs: 4px - xs: 8px - sm: 12px - md: 16px - lg: 24px - xl: 32px - xxl: 48px - section: 96px - -components: - button-primary: - backgroundColor: "{colors.primary}" - textColor: "{colors.on-primary}" - typography: "{typography.button}" - rounded: "{rounded.md}" - padding: 8px 14px - button-primary-pressed: - backgroundColor: "{colors.primary-focus}" - textColor: "{colors.on-primary}" - typography: "{typography.button}" - rounded: "{rounded.md}" - button-primary-hover: - backgroundColor: "{colors.primary-hover}" - textColor: "{colors.on-primary}" - typography: "{typography.button}" - rounded: "{rounded.md}" - button-secondary: - backgroundColor: "{colors.surface-1}" - textColor: "{colors.ink}" - typography: "{typography.button}" - rounded: "{rounded.md}" - padding: 8px 14px - button-tertiary: - backgroundColor: "{colors.canvas}" - textColor: "{colors.ink}" - typography: "{typography.button}" - rounded: "{rounded.md}" - padding: 8px 14px - button-inverse: - backgroundColor: "{colors.inverse-canvas}" - textColor: "{colors.inverse-ink}" - typography: "{typography.button}" - rounded: "{rounded.md}" - padding: 8px 14px - pricing-card: - backgroundColor: "{colors.surface-1}" - textColor: "{colors.ink}" - typography: "{typography.body}" - rounded: "{rounded.lg}" - padding: 24px - pricing-card-featured: - backgroundColor: "{colors.surface-2}" - textColor: "{colors.ink}" - typography: "{typography.body}" - rounded: "{rounded.lg}" - padding: 24px - feature-card: - backgroundColor: "{colors.surface-1}" - textColor: "{colors.ink}" - typography: "{typography.body}" - rounded: "{rounded.lg}" - padding: 24px - product-screenshot-card: - backgroundColor: "{colors.surface-1}" - textColor: "{colors.ink}" - typography: "{typography.body}" - rounded: "{rounded.xl}" - padding: 24px - testimonial-card: - backgroundColor: "{colors.surface-1}" - textColor: "{colors.ink}" - typography: "{typography.body-lg}" - rounded: "{rounded.lg}" - padding: 32px - customer-logo-tile: - backgroundColor: "{colors.canvas}" - textColor: "{colors.ink-subtle}" - typography: "{typography.caption}" - rounded: "{rounded.xs}" - padding: 16px - text-input: - backgroundColor: "{colors.surface-1}" - textColor: "{colors.ink}" - typography: "{typography.body}" - rounded: "{rounded.md}" - padding: 8px 12px - text-input-focused: - backgroundColor: "{colors.surface-1}" - textColor: "{colors.ink}" - typography: "{typography.body}" - rounded: "{rounded.md}" - padding: 8px 12px - pricing-tab-default: - backgroundColor: "{colors.canvas}" - textColor: "{colors.ink-subtle}" - typography: "{typography.button}" - rounded: "{rounded.pill}" - padding: 6px 14px - pricing-tab-selected: - backgroundColor: "{colors.surface-2}" - textColor: "{colors.ink}" - typography: "{typography.button}" - rounded: "{rounded.pill}" - padding: 6px 14px - cta-banner: - backgroundColor: "{colors.surface-1}" - textColor: "{colors.ink}" - typography: "{typography.headline}" - rounded: "{rounded.lg}" - padding: 48px - changelog-row: - backgroundColor: "{colors.canvas}" - textColor: "{colors.ink}" - typography: "{typography.body}" - rounded: "{rounded.xs}" - padding: 24px 0 - status-badge: - backgroundColor: "{colors.surface-2}" - textColor: "{colors.ink-muted}" - typography: "{typography.caption}" - rounded: "{rounded.pill}" - padding: 2px 8px - top-nav: - backgroundColor: "{colors.canvas}" - textColor: "{colors.ink}" - typography: "{typography.body-sm}" - rounded: "{rounded.xs}" - height: 56px - footer: - backgroundColor: "{colors.canvas}" - textColor: "{colors.ink-subtle}" - typography: "{typography.caption}" - rounded: "{rounded.xs}" - padding: 64px 32px ---- - -## Overview - -Linear's marketing canvas is the deepest dark surface in this collection — `{colors.canvas}` is #010102, essentially pure black with a faint blue tint. On top sits a four-step surface ladder (`{colors.surface-1}` through `{colors.surface-4}`) for cards, panels, and lifted tiles, with hairline borders running from `{colors.hairline}` (#23252a) up through `{colors.hairline-strong}` and `{colors.hairline-tertiary}`. Light gray text (`{colors.ink}` #f7f8f8) carries the body and headlines. - -The single chromatic accent is **Linear lavender-blue** `{colors.primary}` (#5e6ad2) — used on the brand mark, focus rings, and the primary CTA button. A lighter hover state (`{colors.primary-hover}` #828fff) and a focus-tinted variant (`{colors.primary-focus}` #5e69d1) extend the same hue. Linear avoids saturated greens, oranges, reds, etc. on the marketing canvas — the only semantic color is `{colors.semantic-success}` (#27a644) for status pills and the rare success indicator. - -Display type runs Linear's custom sans (with `SF Pro Display` fallback) at weight 500–700 with negative letter-spacing scaling from -3.0px at 80px down to 0 at body. The body family is Linear's text cut, and a Linear Mono is reserved for code snippets in product screenshots. - -The page rhythm is **dense product screenshots** — Linear's marketing leads with high-fidelity captures of the product UI (issue list, project view, dashboard) framed in `{colors.surface-1}` panels with `{rounded.xl}` 16px corners. The chrome is intentionally minimal so the app screenshots can do the heavy lifting. - -**Key Characteristics:** -- **Dark-canvas marketing system** — `{colors.canvas}` (#010102) is the deepest dark in this collection. -- **Lavender-blue brand accent** (`{colors.primary}` #5e6ad2) — used scarcely on brand mark, focus, and the primary CTA. -- Four-step surface ladder (canvas → surface-1 → surface-2 → surface-3 → surface-4) carries hierarchy without shadow. -- Display tracking pulls aggressively negative (-3.0px at 80px); body holds at -0.05px. -- Cards use `{rounded.lg}` 12px corners with 1px hairline borders — never pill, rarely 16px. -- **Product UI screenshots** dominate the page. The marketing chrome is a dark frame for the app. -- No second chromatic color. No atmospheric gradients. No spotlight cards. - -## Colors - -> Source pages: linear.app (home), /intake, /pricing, /contact/sales, /build. - -### Brand & Accent -- **Lavender-Blue** ({colors.primary}): The signature Linear accent — primary CTA, brand mark, link emphasis. -- **Lavender Hover** ({colors.primary-hover}): Lighter lavender (#828fff) — hovered state of the primary CTA. -- **Lavender Focus** ({colors.primary-focus}): Focus-ring tint (#5e69d1) — focused inputs, focused buttons. -- **Brand Secure** ({colors.brand-secure}): Muted lavender-gray (#7a7fad) — used in "Linear Security" surfaces. - -### Surface -- **Canvas** ({colors.canvas}): Default page background — #010102, near-pure black with a faint blue tint. -- **Surface 1** ({colors.surface-1}): One step above canvas — feature cards, pricing cards, product screenshot panels. -- **Surface 2** ({colors.surface-2}): Two steps above — featured pricing card, hovered cards. -- **Surface 3** ({colors.surface-3}): Three steps above — line-tertiary backgrounds, sub-nav. -- **Surface 4** ({colors.surface-4}): Four steps above — bg-level-3, deepest lifted surface. -- **Hairline** ({colors.hairline}): 1px borders on cards and dividers. -- **Hairline Strong** ({colors.hairline-strong}): Stronger 1px borders — input focus rings. -- **Hairline Tertiary** ({colors.hairline-tertiary}): Tertiary borders for nested surfaces. -- **Inverse Canvas** ({colors.inverse-canvas}): Pure white — surface of the inverse pill CTA on a small set of section openers. -- **Inverse Surface 1** ({colors.inverse-surface-1}): One step above inverse canvas. -- **Inverse Surface 2** ({colors.inverse-surface-2}): Two steps above inverse canvas. - -### Text -- **Ink** ({colors.ink}): All headlines and emphasized body type — light gray #f7f8f8. -- **Ink Muted** ({colors.ink-muted}): Secondary type at #d0d6e0 — meta info on hero panels. -- **Ink Subtle** ({colors.ink-subtle}): Tertiary type at #8a8f98 — deselected pricing tabs, footer columns. -- **Ink Tertiary** ({colors.ink-tertiary}): Quaternary at #62666d — disabled, footnotes. - -### Semantic -- **Success Green** ({colors.semantic-success}): Status pills, success indicators. The only semantic color on marketing. -- **Overlay** ({colors.semantic-overlay}): Pure black overlay scrim for modals. - -## Typography - -### Font Family - -- **Linear Display** — Linear's custom display sans; fallback `SF Pro Display, -apple-system, system-ui, Segoe UI, Roboto`. Carries display-xl through subhead. -- **Linear Text** — Linear's custom text sans (a slightly different cut tuned for body sizes); same fallback stack. Carries body sizes, button labels, captions. -- **Linear Mono** — Linear's custom mono; fallback `ui-monospace, SF Mono, Menlo`. Used for code snippets in product screenshots and for status / ID tokens. - -The marketing surface treats Display and Text as one continuous voice; the family change is silent. - -### Hierarchy - -| Token | Size | Weight | Line Height | Letter Spacing | Use | -|---|---|---|---|---|---| -| `{typography.display-xl}` | 80px | 600 | 1.05 | -3.0px | Largest hero headline | -| `{typography.display-lg}` | 56px | 600 | 1.10 | -1.8px | Section opener headlines | -| `{typography.display-md}` | 40px | 600 | 1.15 | -1.0px | Sub-section headlines | -| `{typography.headline}` | 28px | 600 | 1.20 | -0.6px | Pricing tier titles, CTA banner heading | -| `{typography.card-title}` | 22px | 500 | 1.25 | -0.4px | Feature card title | -| `{typography.subhead}` | 20px | 400 | 1.40 | -0.2px | Lead body, intro paragraphs | -| `{typography.body-lg}` | 18px | 400 | 1.50 | -0.1px | Hero subhead, lead paragraphs | -| `{typography.body}` | 16px | 400 | 1.50 | -0.05px | Default body | -| `{typography.body-sm}` | 14px | 400 | 1.50 | 0 | Card body, footer columns | -| `{typography.caption}` | 12px | 400 | 1.40 | 0 | Captions, meta, status | -| `{typography.button}` | 14px | 500 | 1.20 | 0 | All button labels | -| `{typography.eyebrow}` | 13px | 500 | 1.30 | 0.4px | Section eyebrow (slight positive tracking) | -| `{typography.mono}` | 13px | 400 | 1.50 | 0 | Linear Mono for code in product screenshots | - -### Principles - -- **Aggressive negative tracking on display** (-3.0px at 80px ≈ 4% of size). -- **Single voice from display to body.** Display-xl at 600 → body at 400 — same family, narrower weights. -- **Eyebrow uses positive tracking** (+0.4px) — contrast against the negative-tracked display marks the eyebrow as taxonomy. -- **Mono only in code contexts.** Linear Mono lives inside product screenshots — not on marketing chrome. - -### Note on Font Substitutes - -Linear's custom typeface isn't publicly distributed; the documented fallback `SF Pro Display, -apple-system, system-ui` is the recommended substitute on macOS. For cross-platform implementation, **Inter** at weight 500 / 600 / 700 is the closest free substitute. **Geist Sans** is also viable. For mono, **JetBrains Mono** or **Geist Mono** at weight 400 closely approximates Linear Mono. - -## Layout - -### Spacing System - -- **Base unit**: 4px. -- **Tokens (front matter)**: `{spacing.xxs}` 4px · `{spacing.xs}` 8px · `{spacing.sm}` 12px · `{spacing.md}` 16px · `{spacing.lg}` 24px · `{spacing.xl}` 32px · `{spacing.xxl}` 48px · `{spacing.section}` 96px. -- Card interior padding: `{spacing.lg}` 24px on feature/pricing cards; `{spacing.xl}` 32px on testimonial cards; `{spacing.xxl}` 48px on CTA banners. -- Pill button padding: 8px vertical · 14px horizontal — Linear's compact button spec. -- Form input padding: 8px vertical · 12px horizontal. - -### Grid & Container - -- Max content width sits around 1280px. -- Card grids are 3-up at desktop, 2-up at tablet, 1-up at mobile. -- Pricing tier grid is 3-up; comparison strip below shows checkmarks per tier. -- Product screenshot panels span full content width — they're the protagonist. - -### Whitespace Philosophy - -The dark canvas IS the whitespace. Sections separate by lift onto surface-1 panels, not by gaps in white. Within a panel, generous `{spacing.lg}` 24px gaps between content blocks; `{spacing.section}` 96px between sections. - -## Elevation & Depth - -| Level | Treatment | Use | -|---|---|---| -| 0 (flat) | No shadow, no border | Default for body type, hero text, footer | -| 1 (charcoal lift) | `{colors.surface-1}` background on canvas, 1px `{colors.hairline}` | Default cards, product panels | -| 2 (surface-2 lift) | `{colors.surface-2}` background, 1px `{colors.hairline-strong}` | Featured pricing card, hovered cards | -| 3 (surface-3 lift) | `{colors.surface-3}` background | Sub-nav, dropdown menus | -| 4 (focus ring) | 2px `{colors.primary-focus}` outline at 50% opacity | Focused input, focused button | - -Linear's depth is carried by surface ladder + hairline borders. The brand resists drop shadows on dark almost entirely. - -### Decorative Depth - -- **Product UI screenshots** dominate as decorative depth. -- **No atmospheric gradients, no spotlight cards.** -- **Subtle white edge highlight** on the top edge of lifted panels — gives the dark surface a faint "pixel rendered" feel. - -## Shapes - -### Border Radius Scale - -| Token | Value | Use | -|---|---|---| -| `{rounded.xs}` | 4px | Small chips, status badges | -| `{rounded.sm}` | 6px | Inline tags | -| `{rounded.md}` | 8px | All buttons, form inputs | -| `{rounded.lg}` | 12px | Pricing cards, feature cards, testimonial cards | -| `{rounded.xl}` | 16px | Product screenshot panels | -| `{rounded.xxl}` | 24px | Oversized CTA banners (rare) | -| `{rounded.pill}` | 9999px | Pricing tab toggles, status pills | -| `{rounded.full}` | 9999px | Avatar circles | - -### Photography & Illustration Geometry - -- Product UI screenshots dominate; they sit in `{rounded.xl}` 16px tiles with `{spacing.lg}` 24px outer padding. -- Customer logo tiles render at small sizes (~24px logo height) on `{colors.canvas}` with no border. -- Avatar circles in testimonial cards use `{rounded.full}` at 32–40px sizes. - -## Components - -### Buttons - -**`button-primary`** — Lavender CTA. The default primary CTA across all pages. -- Background `{colors.primary}`, text `{colors.on-primary}`, type `{typography.button}`, padding 8px 14px, rounded `{rounded.md}`. -- Pressed state lives in `button-primary-pressed` (background shifts to `{colors.primary-focus}`). -- Hover state lives in `button-primary-hover` (background shifts to `{colors.primary-hover}` lighter lavender). - -**`button-secondary`** — Charcoal button. Used for secondary CTAs ("Sign in", "Read changelog"). -- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.button}`, padding 8px 14px, rounded `{rounded.md}`. 1px `{colors.hairline}` border. - -**`button-tertiary`** — Plain text button. -- Background `{colors.canvas}`, text `{colors.ink}`, type `{typography.button}`, rounded `{rounded.md}`, padding 8px 14px. - -**`button-inverse`** — White-on-dark inverse CTA. -- Background `{colors.inverse-canvas}`, text `{colors.inverse-ink}`, type `{typography.button}`, rounded `{rounded.md}`, padding 8px 14px. - -### Pricing Tabs - -**`pricing-tab-default`** + **`pricing-tab-selected`** — Pill-toggle on `/pricing`. -- Default: `{colors.canvas}` background, `{colors.ink-subtle}` text, rounded `{rounded.pill}`, padding 6px 14px. -- Selected: `{colors.surface-2}` background, `{colors.ink}` text — selected = surface lift. - -### Cards & Containers - -**`pricing-card`** — Each tier on `/pricing`. -- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.lg}`, padding 24px. 1px `{colors.hairline}` border. - -**`pricing-card-featured`** — Recommended tier — surface lift to surface-2. -- Background `{colors.surface-2}`, otherwise identical structure. - -**`feature-card`** — Generic feature highlight tile. -- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.lg}`, padding 24px. - -**`product-screenshot-card`** — The dominant card type — frames a high-fidelity Linear app UI screenshot. -- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.xl}`, padding 24px. - -**`testimonial-card`** — Customer quote with avatar + name + role. -- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body-lg}`, rounded `{rounded.lg}`, padding 32px. - -**`customer-logo-tile`** — Small tile in the customer marquee. -- Background `{colors.canvas}`, text `{colors.ink-subtle}`, type `{typography.caption}`, rounded `{rounded.xs}`, padding 16px. - -**`cta-banner`** — Closing CTA panel near page bottom. -- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.headline}`, rounded `{rounded.lg}`, padding 48px. - -### Inputs & Forms - -**`text-input`** + **`text-input-focused`** — Form fields on `/contact/sales` and signup overlays. -- Background `{colors.surface-1}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.md}`, padding 8px 12px. -- Focused state retains the same surface; the focus ring is a 2px `{colors.primary-focus}` outline at 50% opacity. - -### Status & Build Page - -**`changelog-row`** — Each row in `/build` (changelog page) listing version, date, and changes. -- Background `{colors.canvas}`, text `{colors.ink}`, type `{typography.body}`, rounded `{rounded.xs}`, padding 24px 0. 1px `{colors.hairline}` bottom rule. - -**`status-badge`** — Small status pill. -- Background `{colors.surface-2}`, text `{colors.ink-muted}`, type `{typography.caption}`, rounded `{rounded.pill}`, padding 2px 8px. - -### Navigation - -**`top-nav`** — Sticky dark bar with the Linear wordmark left, primary nav links centered, and a `button-secondary` ("Sign in") + `button-primary` ("Get started") pair right. -- Background `{colors.canvas}`, text `{colors.ink}`, type `{typography.body-sm}`, height 56px. - -### Footer - -**`footer`** — Dense link grid on `{colors.canvas}` with the Linear wordmark left. -- Background `{colors.canvas}`, text `{colors.ink-subtle}`, type `{typography.caption}`, padding 64px 32px. - -## Do's and Don'ts - -### Do - -- Reserve `{colors.canvas}` (#010102) as the system's anchor surface — the faint blue tint is intentional. -- Use `{colors.primary}` lavender ONLY for: brand mark, primary CTA, focus ring, link emphasis. -- Use the four-step surface ladder for hierarchy. Avoid skipping levels. -- Pair display weight 600 with body weight 400 — Linear resists 700+ display weights. -- Apply negative letter-spacing aggressively on display. -- Use product UI screenshots as the protagonist of every section. -- Compose CTAs as `{rounded.md}` 8px corners. - -### Don't - -- Don't ship a light-mode marketing page. -- Don't use lavender as a section background or card fill. -- Don't introduce a second chromatic accent (orange, pink, green for marketing). -- Don't add atmospheric gradients or spotlight cards. -- Don't pill-round CTAs. -- Don't use `#000000` true black as the canvas. -- Don't combine multiple bright accents in product screenshot mockups. - -## Responsive Behavior - -### Breakpoints - -| Name | Width | Key Changes | -|---|---|---| -| Desktop-XL | 1440px | Default desktop layout | -| Desktop | 1280px | Card grid 3-up maintained | -| Tablet | 1024px | Card grid 3-up → 2-up | -| Mobile-Lg | 768px | Pricing comparison becomes accordion; nav hamburger | -| Mobile | 480px | Single-column; display-xl scales 80px → ~36px | - -### Touch Targets - -- CTAs hold ≥40px tap height across viewports. -- Pricing tab pills hold ≥36px tap height; touch viewports grow to ≥44px. -- Form inputs hold ≥44px tap target on touch. - -### Collapsing Strategy - -- **Top nav**: links collapse to hamburger below 768px. -- **Card grids**: 3-up → 2-up at 1024px → 1-up below 768px. -- **Pricing comparison**: per-tier accordion below 768px. -- **Display type**: `{typography.display-xl}` 80px scales toward `{typography.display-md}` 40px on mobile. - -### Image Behavior - -- Product UI screenshots maintain aspect ratio and never crop. -- Customer logos in the marquee may collapse from 6-up to 3-up below 768px. - -## Iteration Guide - -1. Focus on ONE component at a time and reference it by its `components:` token name. -2. When introducing a section, decide first which surface lift it lives on. -3. Default body to `{typography.body}` at weight 400. -4. Run `npx @google/design.md lint DESIGN.md` after edits. -5. Add new variants as separate component entries. -6. Treat lavender as scarce: brand mark, primary CTA, focus, link emphasis. -7. Lead every section with a product UI screenshot. - -## Known Gaps - -- The four-step surface ladder values are extracted directly from Linear's `--color-bg-level-3`, `--color-line-tint`, etc. CSS variables; they are Linear's canonical surface spec. -- Form-field error and validation styling is not visible on the inspected pages. -- Light mode is not documented because the marketing site does not ship a light theme. -- Linear's actual product UI uses a richer color-tag palette (red, orange, yellow, green, blue, purple) for issue priorities and project labels — those colors live in the in-product surfaces shown in mockups. -- The custom display, text, and mono families are proprietary; an open-source substitute is acceptable. diff --git a/internal/ui/assets/index.html b/internal/ui/assets/index.html index 1c95a86..df2cda7 100644 --- a/internal/ui/assets/index.html +++ b/internal/ui/assets/index.html @@ -8,7 +8,7 @@