A lightweight markdown note-taking app and self-educational full-stack TypeScript playground inspired by Raycast Notes.
This is an open-source self-educational playground for any developer who wants to master the fundamentals, essentials, and cores of the TypeScript and Node.js ecosystem, as well as modern full-stack web app development, using real-world best practices by building a lightweight markdown note-taking app.
The repository intentionally optimizes for:
- clarity
- minimalism
- maintainability
- testability
- incremental learning
- avoiding over-engineering
This project is not trying to be the most feature-rich notes app. It is trying to be a clean learning reference.
This repository is designed to help developers practice and understand:
- TypeScript in a real monorepo
- Node.js ecosystem fundamentals
- NestJS API structure
- Prisma + PostgreSQL data modeling
- Zod schema validation
- Next.js app architecture
- autosave UX patterns
- route-driven UI state
- frontend + backend testing
- e2e testing with cleanup
- open-source-friendly project organization
- create note
- browse notes
- search notes
- edit notes
- auto-save
- backend-derived note titles
- pin / unpin notes
- soft delete / restore notes
- web markdown preview
- basic keyboard shortcuts
- route-based note selection
- persistent search query while browsing
- deleted-note visibility toggle
- save status feedback
- lightweight editor-first workflow
- backend unit/controller/service tests
- shared package unit tests
- frontend component smoke tests
- one happy-path Playwright e2e test
- CI workflow
- core project docs and GitHub templates
apps/api— NestJS notes APIapps/web— primary reference clientapps/desktop— thin Electron shell over the web clientapps/mobile— iOS-first NativeScript client with list/create/open/edit flow- shared note domain types, utilities, and reusable notes API client through workspace packages
- desktop remains a thin shell and does not add deep native integrations yet
- mobile support is currently iOS-first only
- mobile markdown preview is intentionally deferred for now
- Android support is not included yet
- packaging and store distribution workflows are not part of the current milestone scope
apps/
api/ # NestJS backend
web/ # Next.js frontend
desktop/ # Electron desktop shell
mobile/ # NativeScript iOS client
packages/
config-eslint/ # shared ESLint config
config-typescript/ # shared TypeScript config
shared-types/ # shared domain and API types
shared-notes/ # shared pure note utilities
docs/
spec.md
architecture.md
roadmap.md
.github/
workflows/
ISSUE_TEMPLATE/Browser
-> Next.js web app
-> HTTP requests
-> NestJS API
-> Prisma ORM
-> PostgreSQLKey design choices:
- single-user local mode for simplicity
- database-first persistence
- soft delete + restore
- plain textarea editing
- web-first reference client
- desktop as a thin shell over web
- mobile as an intentionally smaller native client
- shared domain contracts and reusable notes API client
For more detail, see:
- Node.js 22+
- pnpm
- PostgreSQL
Additional platform prerequisites:
- Desktop (Electron): no extra platform tooling required for local development beyond the web stack
- Mobile (NativeScript iOS): requires macOS with Xcode and related iOS tooling installed for native builds
pnpm installcp apps/api/.env.example apps/api/.env
cp apps/web/.env.example apps/web/.env.local
cp apps/desktop/.env.example apps/desktop/.env
cp apps/mobile/.env.example apps/mobile/.envpnpm --filter @markdown-typer/api prisma:migrate:devpnpm --filter @markdown-typer/api prisma:seedpnpm dev- Web:
http://localhost:3000 - API:
http://localhost:3210/api - API health:
http://localhost:3210/api/health - Desktop shell: loads the URL configured in
apps/desktop/.env(example:http://localhost:3000)
Example:
PORT=3210
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/markdown_typer?schema=app
DEFAULT_USER_NAME=Local User
DEFAULT_USER_EMAIL=local@example.com
WEB_APP_ORIGIN=http://localhost:3000Example:
NEXT_PUBLIC_API_BASE_URL=http://localhost:3210/apiExample:
DESKTOP_WEB_APP_URL=http://localhost:3000Example:
NATIVE_SCRIPT_API_BASE_URL=http://localhost:3210/apipnpm dev
pnpm lint
pnpm typecheck
pnpm format
pnpm format:check
pnpm test
pnpm test:e2e
pnpm build
pnpm checkpnpm --filter @markdown-typer/api dev
pnpm --filter @markdown-typer/api test
pnpm --filter @markdown-typer/api prisma:generate
pnpm --filter @markdown-typer/api prisma:migrate:dev
pnpm --filter @markdown-typer/api prisma:seedpnpm --filter @markdown-typer/web dev
pnpm --filter @markdown-typer/web testpnpm dev:desktop
pnpm desktop:build
pnpm desktop:startpnpm mobile:check
pnpm mobile:doctor
pnpm mobile:build
pnpm dev:mobileThe mobile app is currently an iOS-first NativeScript client.
Its runtime API base URL is configured through apps/mobile/.env.
Current mobile scope includes:
- list notes
- open a note
- create a note
- edit note content
- autosave changes
- mobile-first list/detail navigation
Current intentional mobile limitation:
- markdown preview is deferred for now
Use these commands depending on what you need:
pnpm mobile:check— run mobile linting and TypeScript validation without requiring Xcodepnpm mobile:doctor— inspect whether the NativeScript environment is configured correctlypnpm dev:mobile— start the API and run the NativeScript iOS app locallypnpm mobile:build— build the NativeScript iOS app
To run pnpm dev:mobile or pnpm mobile:build, your machine must have a working iOS toolchain.
At minimum:
- install Xcode
- open Xcode once and complete first-run setup
- ensure Xcode command line tools are selected
- ensure CocoaPods is available
- verify the setup with
pnpm mobile:doctor
If the environment is incomplete, mobile code validation can still continue through pnpm mobile:check, but native iOS execution will fail.
For NativeScript environment setup details, see:
Includes:
- utility tests
- controller tests
- service tests
Includes:
- component smoke tests
Includes:
- one happy-path Playwright test:
- create note
- edit note
- autosave
- search note
pnpm test
pnpm test:e2eCurrent shortcut set is intentionally small:
Ctrl/Cmd + N→ create note/→ focus searchEsc→ blur searchCtrl/Cmd + Shift + P→ pin / unpin current note
This is intentionally limited to keep the UX simple and avoid browser conflicts.
Current markdown preview support is intentionally split by client:
- web: lightweight Edit / Preview toggle
- desktop: inherits the web markdown preview through the Electron shell
- mobile: markdown preview is intentionally deferred for now
The goal is clarity over feature breadth.
This project intentionally avoids adding complexity too early.
Examples of things currently deferred:
- authentication
- multi-user workspaces
- sync across devices
- deep desktop integrations beyond the current Electron shell
- Android support
- mobile markdown preview
- collaborative editing
- rich text editor
- command palette
- advanced note organization systems
The core rule is:
Add complexity only when it clearly improves learning value without significantly harming readability.
- README — overview, setup, scripts, support status, and quick contributor guidance
- Specification — scope, refactor decisions, constraints, and acceptance criteria
- Architecture — ownership boundaries and system rules
- Roadmap — current priorities, next work, and deferred items
This refactor keeps project guidance centered on these four docs and moves desktop/mobile runtime configuration toward explicit per-app environment inputs.
Supporting reference:
Contributions are welcome, especially if they improve:
- documentation
- readability
- maintainability
- testing
- focused UX polish
Before contributing:
- read this README
- review
docs/spec.md,docs/architecture.md, anddocs/roadmap.md - keep changes small and focused
- avoid abstractions or dependencies that do not clearly earn their cost
- update docs when behavior, support status, setup, or decisions change
Validation guidance:
- run the smallest useful validation first
- use
pnpm check,pnpm test, andpnpm build:ciwhen relevant - run
pnpm test:e2ewhen the change affects end-to-end behavior
Please keep changes:
- focused
- minimal
- well-tested
- aligned with the educational purpose of the repository
Current intentional limitations include:
- single-user local mode
- no auth
- no sync
- desktop support is intentionally thin and web-backed
- mobile support is currently iOS-first and depends on local Xcode setup for native runtime
- mobile markdown preview is intentionally deferred
- no advanced markdown rendering beyond the web client’s lightweight preview
- no dedicated trash page
- one happy-path e2e instead of a large e2e suite
These are deliberate tradeoffs for simplicity and learning value.
This repository is currently suitable as an educational MVP and reference project.
It is intended to be:
- useful to study
- easy to run locally
- approachable to contributors
- realistic without being overwhelming