From 664861a0fb49eab183137e8c3c189975dda6c08d Mon Sep 17 00:00:00 2001
From: Chris Wanstrath <2+defunkt@users.noreply.github.com>
Date: Fri, 30 Jan 2026 15:24:39 -0800
Subject: [PATCH] code app
---
apps/code/.npmrc | 1 +
apps/code/bun.lock | 43 +++++
apps/code/index.tsx | 1 +
apps/code/package.json | 25 +++
apps/code/src/pages/index.tsx | 1 +
apps/code/src/server/index.tsx | 327 +++++++++++++++++++++++++++++++++
apps/code/tsconfig.json | 29 +++
7 files changed, 427 insertions(+)
create mode 100644 apps/code/.npmrc
create mode 100644 apps/code/bun.lock
create mode 100644 apps/code/index.tsx
create mode 100644 apps/code/package.json
create mode 100644 apps/code/src/pages/index.tsx
create mode 100644 apps/code/src/server/index.tsx
create mode 100644 apps/code/tsconfig.json
diff --git a/apps/code/.npmrc b/apps/code/.npmrc
new file mode 100644
index 0000000..6c57d5c
--- /dev/null
+++ b/apps/code/.npmrc
@@ -0,0 +1 @@
+registry=https://npm.nose.space
diff --git a/apps/code/bun.lock b/apps/code/bun.lock
new file mode 100644
index 0000000..fbb9f3f
--- /dev/null
+++ b/apps/code/bun.lock
@@ -0,0 +1,43 @@
+{
+ "lockfileVersion": 1,
+ "configVersion": 1,
+ "workspaces": {
+ "": {
+ "name": "code",
+ "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/code/index.tsx b/apps/code/index.tsx
new file mode 100644
index 0000000..9b61e99
--- /dev/null
+++ b/apps/code/index.tsx
@@ -0,0 +1 @@
+export { default } from './src/server'
diff --git a/apps/code/package.json b/apps/code/package.json
new file mode 100644
index 0000000..0c83129
--- /dev/null
+++ b/apps/code/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "code",
+ "module": "index.tsx",
+ "type": "module",
+ "private": true,
+ "scripts": {
+ "toes": "bun run --watch index.tsx",
+ "start": "bun toes",
+ "dev": "bun run --hot index.tsx"
+ },
+ "toes": {
+ "icon": "🖥️"
+ },
+ "devDependencies": {
+ "@types/bun": "latest"
+ },
+ "peerDependencies": {
+ "typescript": "^5.9.2"
+ },
+ "dependencies": {
+ "@because/hype": "*",
+ "@because/forge": "*",
+ "@because/howl": "*"
+ }
+}
diff --git a/apps/code/src/pages/index.tsx b/apps/code/src/pages/index.tsx
new file mode 100644
index 0000000..1bf47e3
--- /dev/null
+++ b/apps/code/src/pages/index.tsx
@@ -0,0 +1 @@
+export default () =>
code
diff --git a/apps/code/src/server/index.tsx b/apps/code/src/server/index.tsx
new file mode 100644
index 0000000..79bb312
--- /dev/null
+++ b/apps/code/src/server/index.tsx
@@ -0,0 +1,327 @@
+import { Hype } from '@because/hype'
+import { define, stylesToCSS } from '@because/forge'
+import { readdir, stat } from 'fs/promises'
+import { readFileSync } from 'fs'
+import { join, extname, basename } from 'path'
+
+const APPS_DIR = process.env.APPS_DIR!
+
+const app = new Hype({ prettyHTML: false })
+
+// Styles
+const Container = define('CodeBrowserContainer', {
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
+ padding: '20px',
+ maxWidth: '1200px',
+ margin: '0 auto',
+})
+
+const Header = define('Header', {
+ marginBottom: '20px',
+ paddingBottom: '10px',
+ borderBottom: '2px solid #333',
+})
+
+const Title = define('Title', {
+ margin: 0,
+ fontSize: '24px',
+ fontWeight: 'bold',
+})
+
+const AppName = define('AppName', {
+ color: '#666',
+ fontSize: '18px',
+ marginTop: '5px',
+})
+
+const FileList = define('FileList', {
+ listStyle: 'none',
+ padding: 0,
+ margin: '20px 0',
+ border: '1px solid #ddd',
+ borderRadius: '4px',
+ overflow: 'hidden',
+})
+
+const FileItem = define('FileItem', {
+ padding: '10px 15px',
+ borderBottom: '1px solid #eee',
+ states: {
+ ':last-child': {
+ borderBottom: 'none',
+ },
+ ':hover': {
+ backgroundColor: '#f5f5f5',
+ },
+ }
+})
+
+const FileLink = define('FileLink', {
+ base: 'a',
+ textDecoration: 'none',
+ color: '#0066cc',
+ display: 'flex',
+ alignItems: 'center',
+ gap: '8px',
+ states: {
+ ':hover': {
+ textDecoration: 'underline',
+ },
+ }
+})
+
+const CodeBlock = define('CodeBlock', {
+ margin: '20px 0',
+ border: '1px solid #ddd',
+ borderRadius: '4px',
+ overflow: 'auto',
+ selectors: {
+ '& pre': {
+ margin: 0,
+ padding: '15px',
+ overflow: 'auto',
+ whiteSpace: 'pre',
+ },
+ '& pre code': {
+ whiteSpace: 'pre',
+ fontFamily: 'monospace',
+ },
+ },
+})
+
+const CodeHeader = define('CodeHeader', {
+ padding: '10px 15px',
+ backgroundColor: '#f5f5f5',
+ borderBottom: '1px solid #ddd',
+ fontWeight: 'bold',
+ fontSize: '14px',
+})
+
+const Error = define('Error', {
+ color: '#d32f2f',
+ padding: '20px',
+ backgroundColor: '#ffebee',
+ borderRadius: '4px',
+ margin: '20px 0',
+})
+
+const BackLink = define('BackLink', {
+ base: 'a',
+ textDecoration: 'none',
+ color: '#0066cc',
+ display: 'inline-flex',
+ alignItems: 'center',
+ gap: '5px',
+ marginBottom: '15px',
+ states: {
+ ':hover': {
+ textDecoration: 'underline',
+ },
+ },
+})
+
+app.get('/styles.css', c => c.text(stylesToCSS(), 200, {
+ 'Content-Type': 'text/css; charset=utf-8',
+}))
+
+async function listFiles(appPath: string, subPath: string = '') {
+ const fullPath = join(appPath, subPath)
+ const entries = await readdir(fullPath, { withFileTypes: true })
+
+ const items = await Promise.all(
+ entries.map(async entry => {
+ const itemPath = join(fullPath, entry.name)
+ const stats = await stat(itemPath)
+ return {
+ name: entry.name,
+ isDirectory: entry.isDirectory(),
+ path: subPath ? `${subPath}/${entry.name}` : entry.name,
+ }
+ })
+ )
+
+ return items.sort((a, b) => {
+ if (a.isDirectory !== b.isDirectory) {
+ return a.isDirectory ? -1 : 1
+ }
+ return a.name.localeCompare(b.name)
+ })
+}
+
+function escapeHtml(text: string): string {
+ return text
+ .replace(/&/g, '&')
+ .replace(//g, '>')
+ .replace(/"/g, '"')
+ .replace(/'/g, ''')
+}
+
+function getLanguage(filename: string): string {
+ const ext = extname(filename).toLowerCase()
+ const langMap: Record = {
+ '.js': 'javascript',
+ '.jsx': 'javascript',
+ '.ts': 'typescript',
+ '.tsx': 'typescript',
+ '.json': 'json',
+ '.css': 'css',
+ '.html': 'html',
+ '.md': 'markdown',
+ '.sh': 'bash',
+ '.yml': 'yaml',
+ '.yaml': 'yaml',
+ }
+ return langMap[ext] || 'plaintext'
+}
+
+app.get('/', async c => {
+ const appName = c.req.query('app')
+ const filePath = c.req.query('file') || ''
+
+ if (!appName) {
+ return c.html(
+
+
+
+
+ Code Browser
+
+
+
+
+
+ Please specify an app name with ?app=<name>
+
+
+
+ )
+ }
+
+ const appPath = join(APPS_DIR, appName)
+
+ try {
+ await stat(appPath)
+ } catch {
+ return c.html(
+
+
+
+
+ Code Browser
+
+
+
+
+
+ App "{appName}" not found
+
+
+
+ )
+ }
+
+ const fullPath = join(appPath, filePath)
+ let stats
+
+ try {
+ stats = await stat(fullPath)
+ } catch {
+ return c.html(
+
+
+
+
+ Code Browser
+
+
+
+
+
+ Path "{filePath}" not found in app "{appName}"
+
+
+
+ )
+ }
+
+ if (stats.isFile()) {
+ const content = readFileSync(fullPath, 'utf-8')
+ const language = getLanguage(basename(fullPath))
+ const parentPath = filePath.split('/').slice(0, -1).join('/')
+
+ return c.html(
+
+
+
+
+ {`${appName}/${filePath}`}
+
+
+
+
+
+
+
+ Code Browser
+ {appName}/{filePath}
+
+
+ ⬅️ Back
+
+
+ {basename(fullPath)}
+ {content}
+
+
+
+
+
+ )
+ }
+
+ const files = await listFiles(appPath, filePath)
+ const parentPath = filePath.split('/').slice(0, -1).join('/')
+
+ return c.html(
+
+
+
+
+ {`${appName}${filePath ? `/${filePath}` : ''}`}
+
+
+
+
+
+ Code Browser
+ {appName}{filePath ? `/${filePath}` : ''}
+
+ {filePath && (
+
+ ⬅️ Back
+
+ )}
+
+ {files.map(file => (
+
+
+ {file.isDirectory ? '📁' : '📄'}
+ {file.name}
+
+
+ ))}
+
+
+
+
+ )
+})
+
+export default app.defaults
diff --git a/apps/code/tsconfig.json b/apps/code/tsconfig.json
new file mode 100644
index 0000000..b16b513
--- /dev/null
+++ b/apps/code/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/*"]
+ }
+ }
+}