feat: vertical helix with projects bound to strands
Reshape the landing so each project anchors to a slot on one of the two
helix strands. Strand A = Projects (durable, in-production), strand B =
Innovations (experiments, prototypes). Cards alternate L/R based on the
strand's instantaneous position at the slot — strand identity is shown
by colour + badge, not by side.
Schema
- ALTER projects ADD strand TEXT NOT NULL DEFAULT 'A' CHECK ('A','B').
Generated as drizzle/0001_*.sql.
Component
- New VerticalHelix.svelte replaces Helix.svelte on the landing.
- Slot Y = 120 + i * 240; period = 480, so each strand is at an extreme
at every slot. Node sits at the strand's actual x; card hugs that side.
- Pulsing node halos and animated gradient stops give "alive" feeling
without moving the strand geometry — projects stay anchored.
- prefers-reduced-motion disables the pulse.
- <760px: SVG hides, cards stack full-width.
Authoring
- /projects/new form gets a Project / Innovation radio picker.
- Seed adds an "DNA Scout" example on strand B so the helix renders with
both strands populated on first boot.
Landing
- Hero shrinks (60vh, no helix backdrop) and gains a strand legend.
- Top 12 projects bind to the helix; "See all N →" appears if there's
more.
- Posts band becomes compact (3 most recent), below the helix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,7 @@ const projects = [
|
||||
'- Used at Waterschap Brabantse Delta for plant simulation and live control'
|
||||
].join('\n'),
|
||||
cover_url: null,
|
||||
strand: 'A',
|
||||
status: 'published'
|
||||
},
|
||||
{
|
||||
@@ -52,7 +53,7 @@ const projects = [
|
||||
'## Stack',
|
||||
'',
|
||||
'- **SvelteKit 2** + **Svelte 5** + TypeScript',
|
||||
'- **Tailwind v4** (CSS-first design tokens)',
|
||||
'- **Tailwind v3** + CSS-first design tokens',
|
||||
'- **SQLite** + **Drizzle ORM** — single-file, easy to back up',
|
||||
'- **Gitea OAuth** for authoring',
|
||||
'- Pure SVG + CSS for the helix animation — no WebGL',
|
||||
@@ -62,6 +63,34 @@ const projects = [
|
||||
'Innovations were scattered: Gitea repos here, Grafana dashboards there, slide decks elsewhere. HELIX is the strand they share.'
|
||||
].join('\n'),
|
||||
cover_url: null,
|
||||
strand: 'A',
|
||||
status: 'published'
|
||||
},
|
||||
{
|
||||
id: 'prj_dna_scout',
|
||||
slug: 'dna-scout',
|
||||
title: 'DNA Scout',
|
||||
summary:
|
||||
'Experimental anomaly-detection prototype that fingerprints reactor telemetry. R&D scout, not yet plant-ready.',
|
||||
body_md: [
|
||||
'# DNA Scout',
|
||||
'',
|
||||
"An experimental innovation: build short \"fingerprints\" of reactor telemetry to spot anomalies before the operator does. Think of it as a sequence read on the plant's metabolism.",
|
||||
'',
|
||||
'## Status',
|
||||
'',
|
||||
"Prototype. Runs on bench data from one reactor at the WBD test site. Not production-ready — accuracy on overflow events is still 60-something percent.",
|
||||
'',
|
||||
'## Idea',
|
||||
'',
|
||||
'- Slide a 5-minute window across all telemetry channels',
|
||||
'- Hash each window into a compact descriptor',
|
||||
'- Cluster descriptors → anomalies fall outside the dense clusters',
|
||||
'',
|
||||
'Belongs on strand B (Innovation) — it might never ship, and that\'s fine. If it does, it graduates to a Project.'
|
||||
].join('\n'),
|
||||
cover_url: null,
|
||||
strand: 'B',
|
||||
status: 'published'
|
||||
}
|
||||
];
|
||||
@@ -113,9 +142,9 @@ const posts = [
|
||||
|
||||
const insertProject = db.prepare(`
|
||||
INSERT OR IGNORE INTO projects
|
||||
(id, slug, title, summary, body_md, cover_url, author_id, status, created_at, updated_at)
|
||||
(id, slug, title, summary, body_md, cover_url, strand, author_id, status, created_at, updated_at)
|
||||
VALUES
|
||||
(@id, @slug, @title, @summary, @body_md, @cover_url, NULL, @status, ${now}, ${now})
|
||||
(@id, @slug, @title, @summary, @body_md, @cover_url, @strand, NULL, @status, ${now}, ${now})
|
||||
`);
|
||||
const insertLink = db.prepare(`
|
||||
INSERT OR IGNORE INTO project_links
|
||||
|
||||
Reference in New Issue
Block a user