diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e96999b --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +node_modules/ +.npm/ +.next/ +out/ +dist/ +coverage/ +.bun/ +bun.lockb +.env +.env.local +.env.*.local +.DS_Store +*.log +logs/ +.cache/ +.vercel/ diff --git a/app/api/health/route.ts b/app/api/health/route.ts new file mode 100644 index 0000000..64159b0 --- /dev/null +++ b/app/api/health/route.ts @@ -0,0 +1,5 @@ +import { NextResponse } from 'next/server'; + +export async function GET() { + return NextResponse.json({ ok: true, ts: new Date().toISOString() }); +} diff --git a/app/layout.tsx b/app/layout.tsx new file mode 100644 index 0000000..0c7aea5 --- /dev/null +++ b/app/layout.tsx @@ -0,0 +1,14 @@ +export const metadata = { + title: "Next + Bun Starter", + description: "Deterministic scaffold", +}; + +export default function RootLayout({ children }: { children: React.ReactNode }) { + return ( + + + {children} + + + ); +} diff --git a/app/page.tsx b/app/page.tsx new file mode 100644 index 0000000..e6c001d --- /dev/null +++ b/app/page.tsx @@ -0,0 +1,11 @@ +export default function HomePage() { + return ( +
+

Next.js + Bun

+

Healthy and ready.

+

+ API: /api/health +

+
+ ); +} diff --git a/next-env.d.ts b/next-env.d.ts new file mode 100644 index 0000000..4f11a03 --- /dev/null +++ b/next-env.d.ts @@ -0,0 +1,5 @@ +/// +/// + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/basic-features/typescript for more information. diff --git a/next.config.ts b/next.config.ts new file mode 100644 index 0000000..04af72b --- /dev/null +++ b/next.config.ts @@ -0,0 +1,10 @@ +import type { NextConfig } from "next"; + +const nextConfig: NextConfig = { + reactStrictMode: true, + experimental: { + typedRoutes: true + } +}; + +export default nextConfig; diff --git a/ops/fundraising.md b/ops/fundraising.md new file mode 100644 index 0000000..5de0e97 --- /dev/null +++ b/ops/fundraising.md @@ -0,0 +1,8 @@ +## Fundraising Steps (Deterministic) + +- **prepare-narrative**: One-pager `ops/artifacts/onepager.pdf` + digest JSON. +- **target-list**: `ops/investors.csv` with firm, partner, thesis, stage, last-contact. +- **data-room**: `ops/data-room/manifest.json` indexing files with SHA256 + sizes. +- **outreach**: Sequence emails in `ops/outreach.csv` with timestamps and outcomes. +- **metrics**: Export monthly metrics `ops/metrics.json` (MRR, churn, CAC/LTV, runway) with schema. +- **close**: Track term sheets `ops/term-sheets/*.json` and wire confirmations. diff --git a/ops/hiring.md b/ops/hiring.md new file mode 100644 index 0000000..3bb83eb --- /dev/null +++ b/ops/hiring.md @@ -0,0 +1,7 @@ +## Hiring Plan (Deterministic) + +- **define-roles**: Write machine-readable `ops/roles/*.json` with competencies and leveling. +- **calibrate-bar**: Interview loops per role; store question banks and rubrics in JSON. +- **sourcing**: Track candidates in `ops/candidates.csv`; each row has SHA256 of resume artifact. +- **assess**: Structured scorecards (CSV/JSON) with calibrated anchors. Output aggregate stats. +- **decide**: Offer/no-offer exported as `ops/decisions.json` with rationale and rubric alignment. diff --git a/ops/pilots.md b/ops/pilots.md new file mode 100644 index 0000000..7da0a4e --- /dev/null +++ b/ops/pilots.md @@ -0,0 +1,8 @@ +## Pilot Rollout Steps (Deterministic) + +- **prepare-staging**: Provision `STAGING_BASE_URL`, Postgres, and object storage. Output JSON with endpoints. +- **seed-data**: Run `npm run db:seed` and export a SHA256 of seed fixtures. +- **deploy-staging**: Build (`bunx next build`) and deploy (Vercel or container). Output deployment URL. +- **run-smoke**: Hit `/api/health` and core pages. Save responses to `ops/artifacts/staging-smoke.json` with timestamps and digests. +- **enable-logging**: Ensure request logs and error tracking (Sentry) are active; emit DSN and environment in JSON. +- **collect-feedback**: Structured pilot feedback form; export CSV and digest. diff --git a/package.json b/package.json new file mode 100644 index 0000000..f445d65 --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "next-bun-starter", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "dev": "bunx next dev -p 3000", + "build": "bunx next build", + "start": "bunx next start -p 3000", + "lint": "bunx next lint", + "verify": "bun run tools/verify.ts --spec specs/sample.json", + "test": "bun test" + }, + "dependencies": { + "next": "14.2.7", + "react": "18.3.1", + "react-dom": "18.3.1" + }, + "devDependencies": { + "typescript": "5.6.3", + "@types/node": "20.11.30" + }, + "engines": { + "bun": ">=1.1.0" + } +} diff --git a/specs/sample.json b/specs/sample.json new file mode 100644 index 0000000..c8b226c --- /dev/null +++ b/specs/sample.json @@ -0,0 +1,5 @@ +{ + "target": "README.md", + "algorithm": "sha256", + "expected": "fcc90c86421cc88dd838be68a13ca7176ced265a2594f2a33a5664479be69c3e" +} diff --git a/tools/verify.ts b/tools/verify.ts new file mode 100644 index 0000000..41fcc7b --- /dev/null +++ b/tools/verify.ts @@ -0,0 +1,43 @@ +#!/usr/bin/env bun +import { readFile } from 'node:fs/promises'; +import { createHash } from 'node:crypto'; + +interface VerificationSpec { + target: string; + algorithm: 'sha256' | 'sha512'; + expected: string; // hex string +} + +function hash(content: string | Uint8Array, algo: 'sha256' | 'sha512') { + const h = createHash(algo); + h.update(content); + return h.digest('hex'); +} + +async function main() { + const args = new Map(); + for (let i = 2; i < process.argv.length; i += 2) { + const k = process.argv[i]; + const v = process.argv[i + 1]; + if (!k || !v) continue; + args.set(k.replace(/^--/, ''), v); + } + const specPath = args.get('spec'); + if (!specPath) { + console.error('Usage: bun run tools/verify.ts --spec '); + process.exit(2); + } + const raw = await readFile(specPath, 'utf8'); + const spec: VerificationSpec = JSON.parse(raw); + const file = await readFile(spec.target); + const actual = hash(file, spec.algorithm); + const ok = actual.toLowerCase() === spec.expected.toLowerCase(); + const result = { ok, algorithm: spec.algorithm, expected: spec.expected, actual, target: spec.target }; + console.log(JSON.stringify(result)); + process.exit(ok ? 0 : 1); +} + +main().catch((err) => { + console.error(JSON.stringify({ ok: false, error: String(err) })); + process.exit(1); +}); diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..3a0ca8e --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "target": "ES2020", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "tools/**/*.ts"], + "exclude": ["node_modules"] +}