Target repository: weiyentan/opencode-gateway
Target frontend: vanilla HTML/CSS/JavaScript, no framework or bundler.
This is the deterministic implementation companion to PRD #348. The production source of truth remains the target repository. Do not copy the throwaway prototype into production.
Inspect and modify the existing frontend presentation layer:
frontend/index.html: shell, navigation, tab containers, table markup.frontend/style.css: design tokens, layout, responsive rules, state styling.frontend/app.js: tab navigation and render functions, especially session rendering and status classes.frontend/tests/test_pure_functions.js: existing Node-based helper tests.
Preserve API contracts, data fetching, auto-refresh, date ranges, session detail, agent-run detail, and all existing tabs.
- Overall direction: restrained Refined Glass.
- Navigation: top navigation; remove the persistent desktop sidebar.
- Typography: one system UI family everywhere. Use
system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif. Do not load Inter, JetBrains Mono, Fira Code, or a decorative serif font for the redesigned surface. - Numbers: use
font-variant-numeric: tabular-numsandfont-feature-settings: "tnum" 1on numeric, token, duration, message, and cost values. - Table: Balanced Quiet Rows.
- Status: Badge Only, compact outlined badge in the status column.
- Responsive: Responsive Hybrid.
Use CSS custom properties as the stable interface. Values may be tuned by small amounts only when required for contrast or existing conventions.
:root {
--bg-deep: #08111f;
--bg-mid: #0d1326;
--text-primary: #e8ecf4;
--text-secondary: #9ca5bf;
--text-muted: #808aa8;
--surface-panel: rgba(255, 255, 255, 0.08);
--surface-panel-hover: rgba(255, 255, 255, 0.105);
--surface-table: rgba(255, 255, 255, 0.025);
--border-subtle: rgba(255, 255, 255, 0.10);
--border-strong: rgba(255, 255, 255, 0.16);
--accent-indigo: #7c8cff;
--accent-indigo-light: #a5b4fc;
--status-healthy: #4ade80;
--status-stale: #fbbf24;
--status-unknown: #94a3b8;
--status-error: #f87171;
--radius-panel: 12px;
--radius-control: 8px;
--font-system: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}The existing token names may be retained if that avoids churn, but their rendered behavior must match this contract.
- Keep the sticky header and live/database indicators.
- Put Overview, Sessions, Agent Runs, and Clients / Projects into a horizontal top navigation.
- Active navigation uses an indigo underline or border and a restrained surface tint.
- Do not render a 160px or 200px persistent left sidebar on desktop.
- Main content should use available horizontal space. Do not constrain the Sessions table to the old sidebar-plus-panel geometry.
- Panel corners should be approximately 12px, not 22px.
- Background aurora may remain as a low-opacity decorative layer, but must not create visible color casts over table rows.
- Keep columns: Client, Session Title, First Message, Last Message, Duration, Messages, Tokens, Cost, Status at desktop widths.
- Use comfortable balanced padding: approximately
10px 12pxfor body cells and10px 12pxfor headers. - Use a flexible title column; secondary metadata is muted but readable.
- Use stable numeric alignment with tabular numerals. Right-align cost and numeric fields where existing semantics permit.
- Use neutral row surfaces. A row must not change color because its session is active.
- Hover may use only a subtle neutral surface change, approximately
rgba(255,255,255,0.025). - Keyboard focus must use a visible indigo outline or inset ring.
- Status must be a compact outlined badge, approximately
2px 8pxpadding,8pxradius,0.72remtext, with text plus border. Filled status pills are not required.
Do not retain these treatments on session rows or active badges:
.session-row[data-active="true"] { /* no green background wash or glow */ }
.session-row[data-active="true"] td:first-child { /* no green rail or shadow */ }
.badge-active { /* no pulse animation */ }
.badge-running { /* no pulse animation */ }Specifically remove or neutralize:
- Green radial active-row backgrounds.
- Green left borders on active rows.
- Green active-row box shadows.
- Cyan horizontal borders or stripes between active rows.
- Animated active/running badges.
- Any rule that makes every row marked active appear visually glowing.
The semantic status text must remain available even when color is unavailable.
Use existing breakpoint conventions unless a browser check proves a better threshold:
- Above
1024px: complete Balanced Quiet Rows table and top navigation. 761pxthrough1024px: hide or condense low-priority columns while retaining client, title, recent activity, cost, and status.760pxand below: use readable stacked session rows. Preserve title, status, client, last activity, duration, messages, tokens, and cost in a clear vertical/grid structure.- At all widths, top navigation remains reachable and session data is not clipped into unreadable text.
- Keep WCAG AA contrast for primary and secondary text.
- Do not use color as the only status or focus cue.
- Preserve
:focus-visibleindicators. - Under
prefers-reduced-motion: reduce, disable aurora drift, live pulse, badge pulse, and nonessential transitions. - Session row readability and status distinction must not depend on animation.
- No new frontend framework.
- No bundler or build pipeline.
- No backend/API/schema changes.
- No production prototype picker or variant switcher.
- Keep existing data and rendering behavior intact.
- Prefer the existing CSS custom-property and semantic data-attribute patterns.
- Sessions tab renders with top navigation and no persistent sidebar.
- All required desktop columns remain visible and readable.
- Active rows have no green wash, green rail, glow, cyan stripe, or pulse.
- Status is visible as text in a compact outlined badge.
- One system font family is used throughout the redesigned surface.
- Numeric values use tabular numerals and align consistently.
- Hover is neutral; keyboard focus is visible.
- Desktop, tablet, and mobile layouts satisfy the responsive contract.
- Reduced-motion preference removes decorative animation.
- Existing Node tests pass.
- Existing auto-refresh, tab switching, session detail, and agent-run detail behavior remain intact.