#!/usr/bin/env node /** * Seeds the database with a couple of example projects + posts so the landing * page has something to render on first boot. Safe to re-run — uses INSERT OR * IGNORE semantics via fixed IDs. * * node scripts/seed.js */ import Database from 'better-sqlite3'; const url = process.env.DATABASE_URL ?? './helix.db'; const db = new Database(url); db.pragma('foreign_keys = ON'); const now = Math.floor(Date.now() / 1000); const projects = [ { id: 'prj_evolv', slug: 'evolv', title: 'EVOLV', summary: 'ISA-88 Node-RED nodes for wastewater treatment plant automation. The flagship R&D stack.', body_md: [ '# EVOLV', '', 'EVOLV is a Node-RED custom-nodes package implementing the **ISA-88 (S88)** batch-control standard for wastewater treatment plants.', '', 'Each node follows a three-layer architecture: Node-RED wrapper → adapter → pure domain logic. Configuration is JSON-driven; measurement series flow through a chainable container; outputs are normalised for InfluxDB and Grafana.', '', '## Highlights', '', '- Reactors, settlers, pumping stations, valves, rotating machines, machine groups', '- Physics-checked: hydraulics, mass balance, biology, rotating-equipment envelopes', '- Telemetry-first: every state surfaces on Ports 0/1/2 with declared output manifests', '- Used at Waterschap Brabantse Delta for plant simulation and live control' ].join('\n'), cover_url: null, strand: 'A', status: 'published' }, { id: 'prj_helix', slug: 'helix', title: 'R&D-lab', summary: 'This very site — the R&D lab of Waterschap Brabantse Delta. Projects, innovations, and every strand between.', body_md: [ '# R&D-lab', '', 'The R&D-lab is the showcase platform of Waterschap Brabantse Delta. It collects projects, innovations, and updates from across the team in one place — with deep links to the actual repos, dashboards, and demos.', '', '## Stack', '', '- **SvelteKit 2** + **Svelte 5** + TypeScript', '- **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', '', '## Why?', '', 'Innovations were scattered: Gitea repos here, Grafana dashboards there, slide decks elsewhere. R&D-lab 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' } ]; const links = [ { id: 'lnk_evolv_repo', project_id: 'prj_evolv', kind: 'gitea', label: 'gitea.wbd-rd.nl/RnD/EVOLV', url: 'https://gitea.wbd-rd.nl/RnD/EVOLV', position: 0 }, { id: 'lnk_helix_repo', project_id: 'prj_helix', kind: 'gitea', label: 'gitea.wbd-rd.nl/RnD/helix', url: 'https://gitea.wbd-rd.nl/RnD/helix', position: 0 } ]; const posts = [ { id: 'pst_welcome', slug: 'welcome-to-rd-lab', title: 'Welcome to R&D-lab', summary: 'Why this site exists and how to contribute.', body_md: [ '# Welcome to R&D-lab', '', 'R&D-lab is the home of R&D output at Waterschap Brabantse Delta. If you have a project, a dashboard, or a one-off experiment worth showing — it belongs here.', '', '## How to post', '', 'Sign in with your Gitea account (top-right). Then:', '', '- **Projects** are durable showcases. Title, summary, markdown body, links to repos / dashboards / demos.', '- **Posts** are updates, write-ups, notes. Anything blog-shaped.', '', 'Both render with full markdown and can link to live dashboards. Iframe embeds are gated by an allowlist in `src/lib/config.ts`.', '', "Don't see your dashboard host in the allowlist? Add it in a PR — one line." ].join('\n'), published_at: now } ]; const insertProject = db.prepare(` INSERT OR IGNORE INTO projects (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, @strand, NULL, @status, ${now}, ${now}) `); const insertLink = db.prepare(` INSERT OR IGNORE INTO project_links (id, project_id, kind, label, url, position) VALUES (@id, @project_id, @kind, @label, @url, @position) `); const insertPost = db.prepare(` INSERT OR IGNORE INTO posts (id, slug, title, summary, body_md, author_id, published_at, created_at, updated_at) VALUES (@id, @slug, @title, @summary, @body_md, NULL, @published_at, ${now}, ${now}) `); const tx = db.transaction(() => { for (const p of projects) insertProject.run(p); for (const l of links) insertLink.run(l); for (const p of posts) insertPost.run(p); }); tx(); console.log(`[helix] seeded ${projects.length} projects, ${links.length} links, ${posts.length} posts → ${url}`); db.close();