diff --git a/apps/versions/20260130-000000/.npmrc b/apps/versions/20260130-000000/.npmrc new file mode 100644 index 0000000..6c57d5c --- /dev/null +++ b/apps/versions/20260130-000000/.npmrc @@ -0,0 +1 @@ +registry=https://npm.nose.space diff --git a/apps/versions/20260130-000000/bun.lock b/apps/versions/20260130-000000/bun.lock new file mode 100644 index 0000000..f4df990 --- /dev/null +++ b/apps/versions/20260130-000000/bun.lock @@ -0,0 +1,38 @@ +{ + "lockfileVersion": 1, + "configVersion": 1, + "workspaces": { + "": { + "name": "versions", + "dependencies": { + "@because/forge": "*", + "@because/hype": "*", + }, + "devDependencies": { + "@types/bun": "latest", + }, + "peerDependencies": { + "typescript": "^5.9.2", + }, + }, + }, + "packages": { + "@because/forge": ["@because/forge@0.0.1", "https://npm.nose.space/@because/forge/-/forge-0.0.1.tgz", { "peerDependencies": { "typescript": "^5" } }, "sha512-QS5CK51gcWma91i4uECWe4HPJeNHcE+Af4SQHOcfEovyzOEa7VOTAjei+jIWr2i+abGWqQCEC9wIuFgPgyr2Bg=="], + + "@because/hype": ["@because/hype@0.0.1", "https://npm.nose.space/@because/hype/-/hype-0.0.1.tgz", { "dependencies": { "hono": "^4.10.4", "kleur": "^4.1.5" }, "peerDependencies": { "typescript": "^5" } }, "sha512-i92DNUXJOwt3J8dN1x8sh7i86blelcTCk8XDpwD839Ic8oe710lkDSVXJ7xYZb/i8YtzGhRg+L6eXDhaRiU2Pw=="], + + "@types/bun": ["@types/bun@1.3.8", "https://npm.nose.space/@types/bun/-/bun-1.3.8.tgz", { "dependencies": { "bun-types": "1.3.8" } }, "sha512-3LvWJ2q5GerAXYxO2mffLTqOzEu5qnhEAlh48Vnu8WQfnmSwbgagjGZV6BoHKJztENYEDn6QmVd949W4uESRJA=="], + + "@types/node": ["@types/node@25.1.0", "https://npm.nose.space/@types/node/-/node-25.1.0.tgz", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-t7frlewr6+cbx+9Ohpl0NOTKXZNV9xHRmNOvql47BFJKcEG1CxtxlPEEe+gR9uhVWM4DwhnvTF110mIL4yP9RA=="], + + "bun-types": ["bun-types@1.3.8", "https://npm.nose.space/bun-types/-/bun-types-1.3.8.tgz", { "dependencies": { "@types/node": "*" } }, "sha512-fL99nxdOWvV4LqjmC+8Q9kW3M4QTtTR1eePs94v5ctGqU8OeceWrSUaRw3JYb7tU3FkMIAjkueehrHPPPGKi5Q=="], + + "hono": ["hono@4.11.7", "https://npm.nose.space/hono/-/hono-4.11.7.tgz", {}, "sha512-l7qMiNee7t82bH3SeyUCt9UF15EVmaBvsppY2zQtrbIhl/yzBTny+YUxsVjSjQ6gaqaeVtZmGocom8TzBlA4Yw=="], + + "kleur": ["kleur@4.1.5", "https://npm.nose.space/kleur/-/kleur-4.1.5.tgz", {}, "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ=="], + + "typescript": ["typescript@5.9.3", "https://npm.nose.space/typescript/-/typescript-5.9.3.tgz", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], + + "undici-types": ["undici-types@7.16.0", "https://npm.nose.space/undici-types/-/undici-types-7.16.0.tgz", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], + } +} diff --git a/apps/versions/20260130-000000/index.tsx b/apps/versions/20260130-000000/index.tsx new file mode 100644 index 0000000..5173856 --- /dev/null +++ b/apps/versions/20260130-000000/index.tsx @@ -0,0 +1,252 @@ +import { Hype } from '@because/hype' +import { createThemes, define, stylesToCSS } from '@because/forge' +import { readdir, readlink, stat } from 'fs/promises' +import { join } from 'path' +import type { Child } from 'hono/jsx' + +const APPS_DIR = process.env.APPS_DIR! + +const app = new Hype({ prettyHTML: false }) + +const theme = createThemes({ + light: { + bg: '#ffffff', + text: '#1a1a1a', + textMuted: '#666666', + border: '#dddddd', + borderSubtle: '#eeeeee', + borderStrong: '#333333', + hover: '#f5f5f5', + link: '#0066cc', + error: '#d32f2f', + errorBg: '#ffebee', + accent: '#2e7d32', + accentBg: '#e8f5e9', + }, + dark: { + bg: '#1a1a1a', + text: '#e5e5e5', + textMuted: '#999999', + border: '#404040', + borderSubtle: '#333333', + borderStrong: '#555555', + hover: '#2a2a2a', + link: '#5c9eff', + error: '#ff6b6b', + errorBg: '#3d1f1f', + accent: '#81c784', + accentBg: '#1b3d1f', + }, +}) + +const Container = define('Container', { + fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif', + padding: '20px', + maxWidth: '800px', + margin: '0 auto', + color: theme('text'), +}) + +const Header = define('Header', { + marginBottom: '20px', + paddingBottom: '10px', + borderBottom: `2px solid ${theme('borderStrong')}`, +}) + +const Title = define('Title', { + margin: 0, + fontSize: '24px', + fontWeight: 'bold', +}) + +const Subtitle = define('Subtitle', { + color: theme('textMuted'), + fontSize: '18px', + marginTop: '5px', +}) + +const VersionList = define('VersionList', { + listStyle: 'none', + padding: 0, + margin: '20px 0', + border: `1px solid ${theme('border')}`, + borderRadius: '4px', + overflow: 'hidden', +}) + +const VersionItem = define('VersionItem', { + padding: '12px 15px', + borderBottom: `1px solid ${theme('borderSubtle')}`, + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + states: { + ':last-child': { + borderBottom: 'none', + }, + ':hover': { + backgroundColor: theme('hover'), + }, + }, +}) + +const VersionLink = define('VersionLink', { + base: 'a', + textDecoration: 'none', + color: theme('link'), + fontFamily: 'monospace', + fontSize: '15px', + states: { + ':hover': { + textDecoration: 'underline', + }, + }, +}) + +const Badge = define('Badge', { + fontSize: '12px', + padding: '2px 8px', + borderRadius: '4px', + backgroundColor: theme('accentBg'), + color: theme('accent'), + fontWeight: 'bold', +}) + +const ErrorBox = define('ErrorBox', { + color: theme('error'), + padding: '20px', + backgroundColor: theme('errorBg'), + borderRadius: '4px', + margin: '20px 0', +}) + +const initScript = ` +(function() { + var theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; + document.body.setAttribute('data-theme', theme); + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function(e) { + document.body.setAttribute('data-theme', e.matches ? 'dark' : 'light'); + }); + function sendHeight() { + var container = document.querySelector('.Container'); + if (!container) return; + var rect = container.getBoundingClientRect(); + window.parent.postMessage({ type: 'resize-iframe', height: rect.bottom + 20 }, '*'); + } + sendHeight(); + setTimeout(sendHeight, 50); + new ResizeObserver(sendHeight).observe(document.body); +})(); +` + +const baseStyles = ` +body { + background: ${theme('bg')}; + margin: 0; +} +` + +interface LayoutProps { + title: string + subtitle?: string + children: Child +} + +function Layout({ title, subtitle, children }: LayoutProps) { + return ( + +
+ + +