From 39006ca5b63f0d4d3278c954da32495dee280cf7 Mon Sep 17 00:00:00 2001 From: jlightner Date: Mon, 30 Mar 2026 06:54:11 +0000 Subject: [PATCH] feat: redesign technique page - meta stats, video filenames, monospace signal chains --- frontend/src/App.css | 36 +++++++++++++++++++++++++--- frontend/src/api/public-client.ts | 1 + frontend/src/pages/TechniquePage.tsx | 36 +++++++++++++++++++++++++--- 3 files changed, 67 insertions(+), 6 deletions(-) diff --git a/frontend/src/App.css b/frontend/src/App.css index 31a9815..f6bfec9 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -1243,6 +1243,12 @@ body { text-decoration: underline; } +.technique-header__stats { + font-size: 0.8125rem; + color: var(--color-text-secondary); + margin-top: 0.5rem; +} + /* ── Technique prose / sections ───────────────────────────────────────────── */ .technique-summary { @@ -1329,6 +1335,16 @@ body { font-variant-numeric: tabular-nums; } +.technique-moment__source { + font-size: 0.75rem; + color: var(--color-text-muted); + font-family: "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace; + max-width: 20rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + .technique-moment__summary { font-size: 0.8125rem; color: var(--color-text-secondary); @@ -1361,11 +1377,25 @@ body { margin-bottom: 0.5rem; } -.technique-chain__steps { - padding-left: 1.25rem; +.technique-chain__flow { + font-family: "SF Mono", "Fira Code", "Fira Mono", "Roboto Mono", monospace; font-size: 0.875rem; - line-height: 1.6; + line-height: 1.8; color: var(--color-text-primary); + background: var(--color-bg-transcript); + padding: 0.75rem 1rem; + border-radius: 0.375rem; + display: flex; + flex-wrap: wrap; + align-items: center; +} + +.technique-chain__arrow { + color: var(--color-accent); +} + +.technique-chain__step { + display: inline; } /* ── Plugins ──────────────────────────────────────────────────────────────── */ diff --git a/frontend/src/api/public-client.ts b/frontend/src/api/public-client.ts index e540fc8..5616870 100644 --- a/frontend/src/api/public-client.ts +++ b/frontend/src/api/public-client.ts @@ -34,6 +34,7 @@ export interface KeyMomentSummary { end_time: number; content_type: string; plugins: string[] | null; + video_filename: string; } export interface CreatorInfo { diff --git a/frontend/src/pages/TechniquePage.tsx b/frontend/src/pages/TechniquePage.tsx index a1bd890..36a259d 100644 --- a/frontend/src/pages/TechniquePage.tsx +++ b/frontend/src/pages/TechniquePage.tsx @@ -138,6 +138,22 @@ export default function TechniquePage() { )} + {/* Meta stats line */} +
+ {(() => { + const sourceCount = new Set( + technique.key_moments + .map((km) => km.video_filename) + .filter(Boolean), + ).size; + const momentCount = technique.key_moments.length; + const updated = new Date(technique.updated_at).toLocaleDateString( + "en-US", + { year: "numeric", month: "short", day: "numeric" }, + ); + return `Compiled from ${sourceCount} source${sourceCount !== 1 ? "s" : ""} · ${momentCount} key moment${momentCount !== 1 ? "s" : ""} · Last updated ${updated}`; + })()} +
{/* Summary */} @@ -179,6 +195,11 @@ export default function TechniquePage() {
  • {km.title} + {km.video_filename && ( + + {km.video_filename} + + )} {formatTime(km.start_time)} – {formatTime(km.end_time)} @@ -211,11 +232,20 @@ export default function TechniquePage() {

    {chainName}

    {steps.length > 0 && ( -
      +
      {steps.map((step, j) => ( -
    1. {String(step)}
    2. + + {j > 0 && ( + + {" → "} + + )} + + {String(step)} + + ))} -
    +
    )}
    );