78 lines
1.7 KiB
TypeScript
78 lines
1.7 KiB
TypeScript
import { readFile } from "node:fs/promises";
|
|
import { join } from "node:path";
|
|
|
|
export interface NavItem {
|
|
id: string;
|
|
label: string;
|
|
href: string;
|
|
active?: boolean;
|
|
detail: string;
|
|
}
|
|
|
|
export interface Feature {
|
|
slug: string;
|
|
label: string;
|
|
href: string;
|
|
detail: string;
|
|
prose: () => Promise<string>;
|
|
}
|
|
|
|
const ROOT = import.meta.dir;
|
|
|
|
const DEFINITIONS: Feature[] = [
|
|
];
|
|
|
|
export const FEATURES: Feature[] = DEFINITIONS.map((feature) => ({ ...feature, prose: (prose = feature.prose) => prose() }));
|
|
|
|
export const NAV: NavItem[] = [
|
|
{ id: "home", label: "Home", href: "/", detail: "Porter discography powered by muddle" },
|
|
...DEFINITIONS.map((feature) => ({
|
|
id: feature.slug,
|
|
label: feature.label,
|
|
href: feature.href,
|
|
detail: feature.detail,
|
|
active: false,
|
|
})),
|
|
];
|
|
|
|
export function navFor(slug?: string): NavItem[] {
|
|
return NAV.map((item) => ({
|
|
...item,
|
|
active: slug ? item.id === slug : item.id === "home",
|
|
}));
|
|
}
|
|
|
|
export interface IntroTopic {
|
|
id: string;
|
|
label: string;
|
|
note: string;
|
|
tint: string;
|
|
}
|
|
|
|
export const INTRO: IntroTopic[] = [
|
|
{
|
|
id: "scaffold",
|
|
label: "Scaffold",
|
|
note: "Every variable is compiled ahead of time so the page ships with zero runtime javascript.",
|
|
tint: "violet",
|
|
},
|
|
{
|
|
id: "relations",
|
|
label: "Relations",
|
|
note: "Anchors like @introtopic record geometry and computed styles so stylesheets can reason about other elements.",
|
|
tint: "rose",
|
|
},
|
|
{
|
|
id: "predict",
|
|
label: "Prediction",
|
|
note: "Prerender measures this panel and ships the numbers, so the first click already animates smoothly.",
|
|
tint: "sky",
|
|
},
|
|
{
|
|
id: "momentum",
|
|
label: "Momentum",
|
|
note: "The whole greeting is server-rendered and hydrates instantly thanks to pre-computed wait.",
|
|
tint: "amber",
|
|
},
|
|
];
|
|
|