JavaScript/TypeScript implementation of memos.
- Backend: Hono REST API under
/api/v1 - Frontend: React + Vite SPA (
web/) - Deployment targets:
- Node.js + SQLite
- Cloudflare Workers + D1 + Static Assets
If you need the Chinese guide, I can add README.zh-CN.md in a follow-up.
| Path | Purpose |
|---|---|
server/ |
Backend source: Hono app, DB adapters, Node/Worker entrypoints |
web/ |
Frontend source (React + Vite) |
dist/public/ |
Frontend build output, served by Node/Worker |
dist/server/ |
Node backend build output (dist/server/node.js) |
migrations/ |
SQL migrations (NNNN_description.sql) for SQLite and D1 |
wrangler.jsonc |
Worker, D1, and static assets config |
- Root/backend: Node.js 18+ recommended
- Frontend (
web/): Node.js version that satisfiesweb/package.json(engines.node >= 24) - Worker deployment: Cloudflare account + D1 database
Install dependencies:
npm installnpm run devThis runs API + web + URL helper concurrently.
- Open frontend: http://localhost:3001
- Vite proxies
/apiand/healthzto http://localhost:3000
npm run dev:node
npm run dev:webnpm run dev:workerdev:worker ensures dist/public is up to date and runs local D1 migrations first.
| Goal | Command |
|---|---|
| Start API + web dev | npm run dev |
| Start Node backend only | npm run dev:node |
| Start Vite web only | npm run dev:web |
| Start Worker local dev | npm run dev:worker |
| Build frontend | npm run build:web |
| Build backend | npm run build:node |
| Build both | npm run build |
| Run built Node server | npm run start:node |
| Typecheck | npm run typecheck |
| Tests (once) | npm test |
| Tests (watch) | npm run test:watch |
Naming convention: db:<action>:<target>
- actions:
migrate,empty,clear - targets:
sqlite,d1:local,d1:remote(remote for migrate only)
| Goal | Command |
|---|---|
| Apply local SQLite migrations | npm run db:migrate:sqlite |
| Empty local SQLite data, keep schema | npm run db:empty:sqlite |
| Delete local SQLite database file | npm run db:clear:sqlite |
| Apply local D1 migrations | npm run db:migrate:d1:local |
| Apply remote D1 migrations | npm run db:migrate:d1:remote |
| Empty local D1 data, keep schema | npm run db:empty:d1:local |
| Delete local Wrangler state | npm run db:clear:d1:local |
For empty / clear, stop the corresponding dev server first. SQLite empty / clear and D1 local clear accept -- --yes for non-interactive runs.
Add a new SQL file under migrations/:
- Filename:
NNNN_short_description.sql(4-digit prefix) - Keep migration version aligned with
schema_migrations - No TypeScript changes are required for normal schema updates
Node startup and npm run db:migrate:sqlite apply pending migrations by filename order.
D1 uses Wrangler migration commands on the same migrations/ directory.
npm run build
npm run start:nodeAt minimum, ship:
dist/public/dist/server/migrations/- production dependencies
Node serves both static files and /api/* from one process.
- Configure
wrangler.jsonc(database_id, Worker name, vars/secrets) - Build frontend:
npm run build:web- Apply remote D1 migrations:
npm run db:migrate:d1:remote- Deploy:
One-step full release (same as upload + 100% promote):
npm run deploy:worker:fullTwo-step (upload, then route traffic in promote; 100% = full, under 100% = canary — interactive or --percentage, see wrangler versions deploy --help):
npm run deploy:worker
npm run deploy:worker:promote| Variable | Description |
|---|---|
PORT |
Listen port, default 3000 |
MEMOS_STATIC_ROOT |
Override static root directory |
DATA_DIR |
SQLite data directory (default: data/) |
MEMOS_MIGRATIONS_DIR |
Optional absolute migration directory |
MEMOS_INSTANCE_URL |
External instance URL |
MEMOS_VERSION |
Instance version string |
MEMOS_DEMO |
Set to 1 for demo JWT secret mode |
For API/proto parity, use this repository's golang branch as source of truth:
proto/- Go tree under
server/andplugin/
Current gap documents:
Note: that Go server/ is different from this branch's TypeScript server/.
See AGENTS.md for collaboration rules.