Skip to content

Commit 247edcb

Browse files
committed
feat: start new deepnotes
1 parent 70f6c7e commit 247edcb

41 files changed

Lines changed: 5012 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: new-deepnotes CI
2+
3+
on:
4+
push:
5+
paths:
6+
- 'new-deepnotes/**'
7+
- '.github/workflows/new-deepnotes-ci.yml'
8+
pull_request:
9+
paths:
10+
- 'new-deepnotes/**'
11+
- '.github/workflows/new-deepnotes-ci.yml'
12+
13+
defaults:
14+
run:
15+
working-directory: new-deepnotes
16+
17+
jobs:
18+
ci:
19+
runs-on: ubuntu-latest
20+
services:
21+
postgres:
22+
image: postgres:16-alpine
23+
env:
24+
POSTGRES_USER: postgres
25+
POSTGRES_PASSWORD: postgres
26+
POSTGRES_DB: deepnotes
27+
ports:
28+
- 5432:5432
29+
options: >-
30+
--health-cmd "pg_isready -U postgres -d deepnotes"
31+
--health-interval 3s
32+
--health-timeout 5s
33+
--health-retries 15
34+
redis:
35+
image: redis:7-alpine
36+
ports:
37+
- 6379:6379
38+
options: >-
39+
--health-cmd "redis-cli ping"
40+
--health-interval 3s
41+
--health-timeout 5s
42+
--health-retries 10
43+
steps:
44+
- uses: actions/checkout@v4
45+
- uses: pnpm/action-setup@v4
46+
with:
47+
version: 9
48+
- uses: actions/setup-node@v4
49+
with:
50+
node-version: 22
51+
cache: pnpm
52+
cache-dependency-path: new-deepnotes/pnpm-lock.yaml
53+
- name: Install
54+
run: pnpm install --frozen-lockfile
55+
- name: Copy env
56+
run: cp template.env .env
57+
- name: Lint
58+
run: pnpm lint
59+
- name: Build
60+
run: pnpm build
61+
- name: Typecheck
62+
run: pnpm typecheck
63+
- name: Test
64+
run: pnpm test
65+
- name: Apply migrations
66+
run: pnpm db:migrate
67+
- name: Drizzle check
68+
run: pnpm db:check

new-deepnotes/.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
node_modules
2+
dist
3+
.turbo
4+
.wrangler
5+
.dev.vars
6+
.env
7+
.env.*
8+
!.env.example
9+
coverage
10+
*.tsbuildinfo

new-deepnotes/LICENSE

Lines changed: 661 additions & 0 deletions
Large diffs are not rendered by default.

new-deepnotes/PLAN_PROGRESS.md

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
# Restart plan — progress
2+
3+
Living checklist for the greenfield stack in this folder. **Authoritative plan:** [docs/RESTART_PLAN.md](../docs/RESTART_PLAN.md) (parent repo).
4+
5+
**Last reviewed:** 2026-04-26
6+
7+
Update this file when phases advance: tick items, add dates or short notes in *Notes*, and adjust *Blocked / decisions* when something is waiting on a call or env.
8+
9+
---
10+
11+
## Phases (see [RESTART_PLAN.md §6](../docs/RESTART_PLAN.md))
12+
13+
### Phase 0 — inventory → OpenAPI + Drizzle
14+
15+
| Item | Status | Notes |
16+
|------|--------|--------|
17+
| Map legacy tRPC + WS handlers → proposed REST / WS names || Source: `apps/app-server/src/trpc/**`, `src/websocket/**` |
18+
| Skeleton OpenAPI (routes may `501`) | partial | `/api/v1/health` + generated `openapi/openapi.json`; expand paths |
19+
| Transcribe `postgres-init.sql` → Drizzle + ordered migrations | partial | Bootstrap `app_meta` + `0000_init`; full schema pending |
20+
| Document cookie names, JWT claims, CORS origins || Add to `template.env` / small `docs/` snippet when defined |
21+
| List legacy `@deepnotes/*` forks the new client can drop || |
22+
23+
**Exit (plan):** OpenAPI v0 + Drizzle schema in repo + feature checklist from old tRPC tree — **not done**.
24+
25+
---
26+
27+
### Phase 1 — legacy repo hygiene (optional)
28+
29+
| Item | Status | Notes |
30+
|------|--------|--------|
31+
| (Only if still editing old monorepo) inspect-brk, tests, Node/pnpm || Optional parallel track |
32+
33+
---
34+
35+
### Phase 2 — repository bootstrap
36+
37+
| Item | Status | Notes |
38+
|------|--------|--------|
39+
| pnpm + Turborepo 2, Node 22+ | done | Root `package.json`, `turbo.json` |
40+
| Docker Compose: Postgres + Redis, `REDIS_URL`-style env | done | `docker-compose.yml`, `template.env` |
41+
| Cloudflare: Wrangler, Hyperdrive placeholder, Pages story | partial | `apps/worker/wrangler.toml`; Hyperdrive + Pages + env matrix TBD |
42+
| CI: lint, typecheck, `drizzle-kit check`, unit smoke | partial | `.github/workflows/new-deepnotes-ci.yml`; optional deploy job TBD |
43+
44+
---
45+
46+
### Phase 3 — backend (REST + Drizzle)
47+
48+
| Item | Status | Notes |
49+
|------|--------|--------|
50+
| Auth + sessions (cookies + JWT) || |
51+
| Pages / groups REST + Drizzle || |
52+
| Realtime + collab (no key rotation, no tRPC) || Protocol + DO vs service decision |
53+
| Load tests (after protocols frozen) || |
54+
| Stripe webhooks (no RevenueCat) || |
55+
56+
---
57+
58+
### Phase 4 — new client MVP
59+
60+
| Item | Status | Notes |
61+
|------|--------|--------|
62+
| Vite + Vue SPA, feature folders, fetch + OpenAPI client || |
63+
| Slice: auth → list → page → Yjs collab → groups || |
64+
| Port/reuse crypto libs where stable || |
65+
| Capacitor / Tauri after web || |
66+
67+
---
68+
69+
### Phase 5 — cutover
70+
71+
| Item | Status | Notes |
72+
|------|--------|--------|
73+
| Staged rollout + retire `/trpc` for supported clients || |
74+
| Data + Stripe + E2E + decrypt spot-checks green || |
75+
76+
---
77+
78+
## Success criteria (see [RESTART_PLAN.md §8](../docs/RESTART_PLAN.md))
79+
80+
- [ ] OpenAPI is source of truth for public HTTP; client uses generated types or shared Zod.
81+
- [ ] Drizzle migrations apply from empty DB to target schema deterministically; production upgrade documented.
82+
- [ ] Cold `pnpm dev` API start under ~2 s on a typical laptop (no `inspect-brk` by default).
83+
- [ ] Collab + realtime each have at least one integration test (Redis + docker or in-memory).
84+
- [ ] No tRPC / `superjson` / RevenueCat in new default stack; no key-rotation paths; Stripe/IAP handling agreed.
85+
- [ ] New client: zero undocumented framework forks, or a short owned exception list.
86+
- [ ] Cloudflare: API + static/SSG deploy documented; Hyperdrive + Postgres + Redis proven in staging; collab/realtime topology chosen and load-tested.
87+
88+
---
89+
90+
## Blocked / decisions
91+
92+
| Topic | Decision / next step |
93+
|-------|----------------------|
94+
| Collab / realtime topology | Durable Objects vs separate services — decide and record here |
95+
| OpenAPI vs Zod single source | Pick codegen or zod-to-openapi-only and stick to it (plan §4.0) |
96+
97+
---
98+
99+
## Changelog
100+
101+
| Date | Change |
102+
|------|--------|
103+
| 2026-04-26 | Initial tracker; Phase 2 largely started, Phase 0 partially. |

new-deepnotes/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# new-deepnotes
2+
3+
Greenfield DeepNotes stack per [docs/RESTART_PLAN.md](../docs/RESTART_PLAN.md): pnpm + Turborepo 2, **Hono** on **Cloudflare Workers**, **Drizzle** + Postgres, **Redis**, **OpenAPI** + Zod contracts (no tRPC).
4+
5+
**Plan progress:** [PLAN_PROGRESS.md](./PLAN_PROGRESS.md)
6+
7+
## Quick start
8+
9+
1. `docker compose up -d` (Postgres + Redis)
10+
2. `cp template.env .env`
11+
3. `pnpm install`
12+
4. `pnpm db:migrate` — apply Drizzle migrations
13+
5. `pnpm dev` — runs the API worker via Wrangler (`apps/worker`)
14+
15+
## Packages
16+
17+
| Package | Role |
18+
|--------|------|
19+
| `@deepnotes/db` | Drizzle schema, migrations, `createDb()` for Node (Hyperdrive wiring in Workers comes later). |
20+
| `@deepnotes/api-contracts` | Zod models + generated `openapi/openapi.json`. |
21+
| `@deepnotes/worker` | HTTP API entry (Hono). |
22+
23+
## Scripts
24+
25+
- `pnpm build` / `pnpm typecheck` / `pnpm lint` / `pnpm test`
26+
- `pnpm db:generate` — emit a new migration from schema changes
27+
- `pnpm db:migrate` — apply migrations (`drizzle-kit migrate`)
28+
- `pnpm db:check` — Drizzle Kit against `DATABASE_URL`
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"name": "@deepnotes/worker",
3+
"version": "0.0.0",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"build": "tsc -p tsconfig.json --noEmit",
8+
"dev": "wrangler dev",
9+
"lint": "eslint .",
10+
"typecheck": "tsc -p tsconfig.json --noEmit",
11+
"test": "echo \"no tests yet\""
12+
},
13+
"dependencies": {
14+
"@deepnotes/api-contracts": "workspace:*",
15+
"hono": "^4.6.14"
16+
},
17+
"devDependencies": {
18+
"@cloudflare/workers-types": "^4.20241230.0",
19+
"typescript": "^5.7.2",
20+
"wrangler": "^3.99.0"
21+
}
22+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export type Env = Record<string, never>;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { healthResponseSchema } from '@deepnotes/api-contracts';
2+
import { Hono } from 'hono';
3+
import { cors } from 'hono/cors';
4+
import { secureHeaders } from 'hono/secure-headers';
5+
6+
import type { Env } from './env.js';
7+
8+
const app = new Hono<{ Bindings: Env }>();
9+
10+
app.use('*', secureHeaders());
11+
app.use(
12+
'*',
13+
cors({
14+
origin: '*',
15+
allowMethods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'OPTIONS'],
16+
}),
17+
);
18+
19+
app.get('/api/v1/health', (c) => {
20+
const body = {
21+
status: 'ok' as const,
22+
service: 'deepnotes-api',
23+
time: new Date().toISOString(),
24+
};
25+
const parsed = healthResponseSchema.safeParse(body);
26+
if (!parsed.success) {
27+
return c.json({ error: 'internal' }, 500);
28+
}
29+
return c.json(parsed.data);
30+
});
31+
32+
export default app;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"compilerOptions": {
4+
"lib": ["ES2022"],
5+
"types": ["@cloudflare/workers-types"],
6+
"module": "ESNext",
7+
"moduleResolution": "Bundler",
8+
"noEmit": true
9+
},
10+
"include": ["src/**/*.ts"]
11+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name = "deepnotes-api"
2+
main = "src/index.ts"
3+
compatibility_date = "2025-04-01"
4+
5+
# Node.js APIs used by Drizzle/pg should be validated with `nodejs_compat` before wiring DB.
6+
# compatibility_flags = [ "nodejs_compat" ]
7+
8+
# Hyperdrive: create in the Cloudflare dashboard, then set `id` and uncomment.
9+
# Local dev: use `wrangler dev` with Hyperdrive local config (see Cloudflare Hyperdrive docs).
10+
# [[hyperdrive]]
11+
# binding = "HYPERDRIVE"
12+
# id = "<hyperdrive-id>"
13+
14+
[vars]
15+
# Non-secret defaults for previews; override in the dashboard for production.

0 commit comments

Comments
 (0)