diff --git a/apps/todo/20260130-181927/.npmrc b/apps/todo/20260130-181927/.npmrc
new file mode 100644
index 0000000..6c57d5c
--- /dev/null
+++ b/apps/todo/20260130-181927/.npmrc
@@ -0,0 +1 @@
+registry=https://npm.nose.space
diff --git a/apps/todo/20260130-181927/bun.lock b/apps/todo/20260130-181927/bun.lock
new file mode 100644
index 0000000..b136c8a
--- /dev/null
+++ b/apps/todo/20260130-181927/bun.lock
@@ -0,0 +1,43 @@
+{
+ "lockfileVersion": 1,
+ "configVersion": 1,
+ "workspaces": {
+ "": {
+ "name": "todo",
+ "dependencies": {
+ "@because/forge": "*",
+ "@because/howl": "*",
+ "@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/howl": ["@because/howl@0.0.2", "https://npm.nose.space/@because/howl/-/howl-0.0.2.tgz", { "dependencies": { "lucide-static": "^0.555.0" }, "peerDependencies": { "@because/forge": "*", "typescript": "^5" } }, "sha512-Z4okzEa282LKkBk9DQwEUU6FT+PeThfQ6iQAY41LIEjs8B2kfXRZnbWLs7tgpwCfYORxb0RO4Hr7KiyEqnfTvQ=="],
+
+ "@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=="],
+
+ "lucide-static": ["lucide-static@0.555.0", "https://npm.nose.space/lucide-static/-/lucide-static-0.555.0.tgz", {}, "sha512-FMMaYYsEYsUA6xlEzIMoKEV3oGnxIIvAN+AtLmYXvlTJptJTveJjVBQwvtA/zZLrD6KLEu89G95dQYlhivw5jQ=="],
+
+ "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/todo/20260130-181927/index.tsx b/apps/todo/20260130-181927/index.tsx
new file mode 100644
index 0000000..9b61e99
--- /dev/null
+++ b/apps/todo/20260130-181927/index.tsx
@@ -0,0 +1 @@
+export { default } from './src/server'
diff --git a/apps/todo/20260130-181927/package.json b/apps/todo/20260130-181927/package.json
new file mode 100644
index 0000000..4563ad6
--- /dev/null
+++ b/apps/todo/20260130-181927/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "todo",
+ "module": "index.tsx",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "toes": "bun run --watch index.tsx",
+ "start": "bun toes",
+ "dev": "bun run --hot index.tsx"
+ },
+ "toes": {
+ "tool": "TODO",
+ "icon": "✅"
+ },
+ "devDependencies": {
+ "@types/bun": "latest"
+ },
+ "peerDependencies": {
+ "typescript": "^5.9.2"
+ },
+ "dependencies": {
+ "@because/hype": "*",
+ "@because/forge": "*",
+ "@because/howl": "*"
+ }
+}
diff --git a/apps/todo/20260130-181927/pub/img/bite1.png b/apps/todo/20260130-181927/pub/img/bite1.png
new file mode 100644
index 0000000..f452c1e
Binary files /dev/null and b/apps/todo/20260130-181927/pub/img/bite1.png differ
diff --git a/apps/todo/20260130-181927/pub/img/bite2.png b/apps/todo/20260130-181927/pub/img/bite2.png
new file mode 100644
index 0000000..c075d53
Binary files /dev/null and b/apps/todo/20260130-181927/pub/img/bite2.png differ
diff --git a/apps/todo/20260130-181927/pub/img/burger.png b/apps/todo/20260130-181927/pub/img/burger.png
new file mode 100644
index 0000000..bc5e222
Binary files /dev/null and b/apps/todo/20260130-181927/pub/img/burger.png differ
diff --git a/apps/todo/20260130-181927/src/client/App.tsx b/apps/todo/20260130-181927/src/client/App.tsx
new file mode 100644
index 0000000..4cb5ef6
--- /dev/null
+++ b/apps/todo/20260130-181927/src/client/App.tsx
@@ -0,0 +1,36 @@
+import { render, useState } from 'hono/jsx/dom'
+import { define } from '@because/forge'
+
+const Wrapper = define({
+ margin: '0 auto',
+ marginTop: 50,
+ width: '50vw',
+ border: '1px solid black',
+ padding: 24,
+ textAlign: 'center'
+
+})
+
+export default function App() {
+ const [count, setCount] = useState(0)
+
+ try {
+ return (
+
+ It works!
+ Count: {count}
+
+
+
+
+
+
+ )
+ } catch (error) {
+ console.error('Render error:', error)
+ return <>
Error
{error instanceof Error ? error : new Error(String(error))}>
+ }
+}
+
+const root = document.getElementById('root')!
+render(, root)
diff --git a/apps/todo/20260130-181927/src/css/main.css b/apps/todo/20260130-181927/src/css/main.css
new file mode 100644
index 0000000..62bcd77
--- /dev/null
+++ b/apps/todo/20260130-181927/src/css/main.css
@@ -0,0 +1,40 @@
+section {
+ max-width: 500px;
+ margin: 0 auto;
+ text-align: center;
+ font-size: 200%;
+}
+
+h1 {
+ margin-top: 0;
+}
+
+.hype {
+ display: inline-block;
+ padding: 0.3rem 0.8rem;
+ background: linear-gradient(45deg,
+ #ff00ff 0%,
+ #00ffff 33%,
+ #ffff00 66%,
+ #ff00ff 100%);
+ background-size: 400% 400%;
+ animation: gradientShift 15s ease infinite;
+ color: black;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
+ font-weight: 700;
+ border-radius: 4px;
+}
+
+@keyframes gradientShift {
+ 0% {
+ background-position: 0% 50%;
+ }
+
+ 100% {
+ background-position: 100% 50%;
+ }
+}
+
+ul {
+ list-style-type: none;
+}
\ No newline at end of file
diff --git a/apps/todo/20260130-181927/src/pages/index.tsx b/apps/todo/20260130-181927/src/pages/index.tsx
new file mode 100644
index 0000000..126eeb5
--- /dev/null
+++ b/apps/todo/20260130-181927/src/pages/index.tsx
@@ -0,0 +1,31 @@
+import { $ } from 'bun'
+
+const GIT_HASH = process.env.RENDER_GIT_COMMIT?.slice(0, 7)
+ || await $`git rev-parse --short HEAD`.text().then(s => s.trim()).catch(() => 'unknown')
+
+export default () => <>
+
+
+ hype
+
+
+
+
+
+
+
+
+
+
+
+>
diff --git a/apps/todo/20260130-181927/src/server/index.tsx b/apps/todo/20260130-181927/src/server/index.tsx
new file mode 100644
index 0000000..c2b86f3
--- /dev/null
+++ b/apps/todo/20260130-181927/src/server/index.tsx
@@ -0,0 +1,422 @@
+import { Hype } from '@because/hype'
+import { createThemes, define, stylesToCSS } from '@because/forge'
+import { readFileSync, writeFileSync, existsSync } from 'fs'
+import { join } from 'path'
+
+const APPS_DIR = process.env.APPS_DIR!
+
+const app = new Hype({ prettyHTML: false })
+
+// Theme
+const theme = createThemes({
+ light: {
+ bg: '#ffffff',
+ text: '#1a1a1a',
+ textMuted: '#666666',
+ border: '#dddddd',
+ hover: '#f5f5f5',
+ surface: '#f8f8f8',
+ accent: '#0066cc',
+ done: '#888888',
+ error: '#d32f2f',
+ errorBg: '#ffebee',
+ success: '#2e7d32',
+ successBg: '#e8f5e9',
+ },
+ dark: {
+ bg: '#1a1a1a',
+ text: '#e5e5e5',
+ textMuted: '#999999',
+ border: '#404040',
+ hover: '#2a2a2a',
+ surface: '#252525',
+ accent: '#5c9eff',
+ done: '#666666',
+ error: '#ff6b6b',
+ errorBg: '#3d1f1f',
+ success: '#81c784',
+ successBg: '#1b3d1e',
+ },
+})
+
+// Styles
+const Container = define('TodoContainer', {
+ 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',
+ display: 'flex',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+})
+
+const Title = define('Title', {
+ margin: 0,
+ fontSize: '24px',
+ fontWeight: 'bold',
+})
+
+const AppName = define('AppName', {
+ color: theme('textMuted'),
+ fontSize: '14px',
+})
+
+const TodoList = define('TodoList', {
+ listStyle: 'none',
+ padding: 0,
+ margin: 0,
+})
+
+const TodoSection = define('TodoSection', {
+ marginBottom: '24px',
+})
+
+const SectionTitle = define('SectionTitle', {
+ fontSize: '16px',
+ fontWeight: 600,
+ color: theme('textMuted'),
+ marginBottom: '12px',
+ paddingBottom: '8px',
+ borderBottom: `1px solid ${theme('border')}`,
+})
+
+const TodoItemStyle = define('TodoItem', {
+ display: 'flex',
+ alignItems: 'flex-start',
+ padding: '8px 0',
+ gap: '10px',
+ selectors: {
+ '& input[type="checkbox"]': {
+ marginTop: '3px',
+ width: '18px',
+ height: '18px',
+ cursor: 'pointer',
+ },
+ '& label': {
+ flex: 1,
+ cursor: 'pointer',
+ lineHeight: '1.5',
+ },
+ },
+})
+
+const doneClass = 'todo-done'
+
+const Error = define('Error', {
+ color: theme('error'),
+ padding: '20px',
+ backgroundColor: theme('errorBg'),
+ borderRadius: '4px',
+ margin: '20px 0',
+})
+
+const successClass = 'msg-success'
+const errorClass = 'msg-error'
+
+const SaveButton = define('SaveButton', {
+ base: 'button',
+ backgroundColor: theme('accent'),
+ color: '#ffffff',
+ border: 'none',
+ padding: '8px 16px',
+ borderRadius: '4px',
+ cursor: 'pointer',
+ fontSize: '14px',
+ fontWeight: 500,
+ states: {
+ ':hover': {
+ opacity: 0.9,
+ },
+ ':disabled': {
+ opacity: 0.5,
+ cursor: 'not-allowed',
+ },
+ },
+})
+
+const AddForm = define('AddForm', {
+ display: 'flex',
+ gap: '10px',
+ marginBottom: '20px',
+})
+
+const AddInput = define('AddInput', {
+ base: 'input',
+ flex: 1,
+ padding: '8px 12px',
+ border: `1px solid ${theme('border')}`,
+ borderRadius: '4px',
+ fontSize: '14px',
+ backgroundColor: theme('bg'),
+ color: theme('text'),
+ states: {
+ ':focus': {
+ outline: 'none',
+ borderColor: theme('accent'),
+ },
+ },
+})
+
+const themeScript = `
+ (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');
+ });
+ })();
+`
+
+const resizeScript = `
+ (function() {
+ function sendHeight() {
+ var height = document.documentElement.scrollHeight;
+ window.parent.postMessage({ type: 'resize-iframe', height: height }, '*');
+ }
+ sendHeight();
+ new ResizeObserver(sendHeight).observe(document.body);
+ window.addEventListener('load', sendHeight);
+ })();
+`
+
+const baseStyles = `
+body {
+ background: ${theme('bg')};
+ margin: 0;
+}
+.${doneClass} {
+ color: ${theme('done')};
+ text-decoration: line-through;
+}
+.${successClass} {
+ padding: 12px 16px;
+ border-radius: 4px;
+ margin-bottom: 16px;
+ background-color: ${theme('successBg')};
+ color: ${theme('success')};
+}
+.${errorClass} {
+ padding: 12px 16px;
+ border-radius: 4px;
+ margin-bottom: 16px;
+ background-color: ${theme('errorBg')};
+ color: ${theme('error')};
+}
+`
+
+interface TodoEntry {
+ text: string
+ done: boolean
+}
+
+interface ParsedTodo {
+ title: string
+ items: TodoEntry[]
+}
+
+function parseTodoFile(content: string): ParsedTodo {
+ const lines = content.split('\n')
+ let title = 'TODO'
+ const items: TodoEntry[] = []
+
+ for (const line of lines) {
+ const trimmed = line.trim()
+ if (!trimmed) continue
+
+ if (trimmed.startsWith('# ')) {
+ title = trimmed.slice(2)
+ } else if (trimmed.startsWith('[x] ') || trimmed.startsWith('[X] ')) {
+ items.push({ text: trimmed.slice(4), done: true })
+ } else if (trimmed.startsWith('[ ] ')) {
+ items.push({ text: trimmed.slice(4), done: false })
+ }
+ }
+
+ return { title, items }
+}
+
+function serializeTodo(todo: ParsedTodo): string {
+ const lines = [`# ${todo.title}`]
+ for (const item of todo.items) {
+ lines.push(item.done ? `[x] ${item.text}` : `[ ] ${item.text}`)
+ }
+ return lines.join('\n') + '\n'
+}
+
+app.get('/styles.css', c => c.text(baseStyles + stylesToCSS(), 200, {
+ 'Content-Type': 'text/css; charset=utf-8',
+}))
+
+app.get('/', async c => {
+ const appName = c.req.query('app')
+ const message = c.req.query('message')
+ const messageType = c.req.query('type') as 'success' | 'error' | undefined
+
+ if (!appName) {
+ return c.html(
+
+
+
+
+ TODO
+
+
+
+
+
+
+ Select an app to view its TODO list
+
+
+
+ )
+ }
+
+ const todoPath = join(APPS_DIR, appName, 'current', 'TODO.txt')
+
+ let todo: ParsedTodo
+ if (existsSync(todoPath)) {
+ const content = readFileSync(todoPath, 'utf-8')
+ todo = parseTodoFile(content)
+ } else {
+ todo = { title: `${appName} TODO`, items: [] }
+ }
+
+ const pendingItems = todo.items.filter(i => !i.done)
+ const doneItems = todo.items.filter(i => i.done)
+
+ return c.html(
+
+
+
+
+ {todo.title}
+
+
+
+
+
+
+
+
{todo.title}
+
{appName}/TODO.txt
+
+
+
+ {message && (
+
+ {message}
+
+ )}
+
+
+
+ {todo.items.length > 0 && (
+
+
+ {pendingItems.length === 0 ? 'All done!' : `Pending (${pendingItems.length})`}
+
+
+ {todo.items.map((item, i) => (
+
+
+
+ ))}
+
+
+ )}
+
+ {todo.items.length === 0 && (
+
+ No todos yet
+ Add your first todo above!
+
+ )}
+
+
+
+ )
+})
+
+app.post('/toggle', async c => {
+ const form = await c.req.formData()
+ const appName = form.get('app') as string
+ const index = parseInt(form.get('index') as string, 10)
+
+ const todoPath = join(APPS_DIR, appName, 'current', 'TODO.txt')
+
+ let todo: ParsedTodo
+ if (existsSync(todoPath)) {
+ const content = readFileSync(todoPath, 'utf-8')
+ todo = parseTodoFile(content)
+ } else {
+ return c.redirect(`/?app=${appName}`)
+ }
+
+ if (index >= 0 && index < todo.items.length) {
+ todo.items[index].done = !todo.items[index].done
+ }
+
+ try {
+ writeFileSync(todoPath, serializeTodo(todo))
+ return c.redirect(`/?app=${appName}`)
+ } catch {
+ return c.redirect(`/?app=${appName}&message=${encodeURIComponent('Failed to save')}&type=error`)
+ }
+})
+
+app.post('/add', async c => {
+ const form = await c.req.formData()
+ const appName = form.get('app') as string
+ const text = (form.get('text') as string).trim()
+
+ if (!text) {
+ return c.redirect(`/?app=${appName}`)
+ }
+
+ const todoPath = join(APPS_DIR, appName, 'current', 'TODO.txt')
+
+ let todo: ParsedTodo
+ if (existsSync(todoPath)) {
+ const content = readFileSync(todoPath, 'utf-8')
+ todo = parseTodoFile(content)
+ } else {
+ todo = { title: `${appName} TODO`, items: [] }
+ }
+
+ todo.items.push({ text, done: false })
+
+ try {
+ writeFileSync(todoPath, serializeTodo(todo))
+ return c.redirect(`/?app=${appName}`)
+ } catch {
+ return c.redirect(`/?app=${appName}&message=${encodeURIComponent('Failed to add')}&type=error`)
+ }
+})
+
+export default app.defaults
diff --git a/apps/todo/20260130-181927/src/shared/types.ts b/apps/todo/20260130-181927/src/shared/types.ts
new file mode 100644
index 0000000..e69de29
diff --git a/apps/todo/20260130-181927/tsconfig.json b/apps/todo/20260130-181927/tsconfig.json
new file mode 100644
index 0000000..b16b513
--- /dev/null
+++ b/apps/todo/20260130-181927/tsconfig.json
@@ -0,0 +1,29 @@
+{
+ "compilerOptions": {
+ "lib": ["ESNext"],
+ "target": "ESNext",
+ "module": "Preserve",
+ "moduleDetection": "force",
+ "jsx": "react-jsx",
+ "jsxImportSource": "hono/jsx",
+ "allowJs": true,
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": true,
+ "verbatimModuleSyntax": true,
+ "noEmit": true,
+ "strict": true,
+ "skipLibCheck": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedIndexedAccess": true,
+ "noImplicitOverride": true,
+ "noUnusedLocals": false,
+ "noUnusedParameters": false,
+ "noPropertyAccessFromIndexSignature": false,
+ "baseUrl": ".",
+ "paths": {
+ "$*": ["src/server/*"],
+ "#*": ["src/client/*"],
+ "@*": ["src/shared/*"]
+ }
+ }
+}
diff --git a/apps/todo/current b/apps/todo/current
new file mode 120000
index 0000000..5da1387
--- /dev/null
+++ b/apps/todo/current
@@ -0,0 +1 @@
+20260130-181927
\ No newline at end of file