Skip to content

Repository files navigation

NoteVault

A local-first, OneNote-style notebook app. All notes are stored as JSON files on your own filesystem — no account, no cloud, no telemetry.


Features

Organization

  • Notebooks with custom colors — one JSON file per notebook, easy to back up or version-control
  • Sections with named creation and a full color picker — color-coded tabs like OneNote
  • Pages and sub-pages (one level deep) per section
  • Drag-and-drop reordering of pages and sections
  • Full-text search across all pages in a notebook (Ctrl+F)

Rich Text Editor

Built on TipTap (ProseMirror):

Formatting

  • Bold, Italic, Underline, Strikethrough
  • Superscript, Subscript
  • Text color and multi-color highlight
  • Font family (Sans-serif / Serif / Monospace)
  • Font size
  • Text alignment (left / center / right)
  • Indentation via Tab / Shift+Tab (paragraphs, headings, and nested lists)

Structure

  • Headings H1–H4
  • Bullet lists, ordered lists, and task lists (checkboxes) — with full nesting support
  • Blockquotes
  • Code blocks with syntax highlighting (100+ languages via lowlight)
  • Inline code
  • Horizontal rules
  • Callout / info boxes (info, warning, success, error styles)

Tables

  • Insert tables with a header row
  • Add / remove rows and columns
  • Merge and split cells
  • Toggle header row
  • Mouse-drag column resize
  • Manual column width input (percentage)
  • Copy column widths from one table and paste to another (proportionally rescaled if column counts differ)
  • Vertical cell alignment (top / middle / bottom) per cell

Images

  • Upload via toolbar or drag-and-drop
  • Paste images directly from the clipboard (screenshots, Finder, etc.)
  • Paste rich content containing images — each image is uploaded individually, text is preserved
  • Inline resize handle (drag right edge)
  • Inline alignment controls (left / center / right / full-width)

YouTube

  • Paste any YouTube URL (youtube.com or youtu.be) → automatically replaced with the video thumbnail and a play button; clicking it opens the video in a new tab

Links & Navigation

  • Hyperlinks with inline editing
  • Internal page links — type [[ to open an autocomplete picker of all pages in any section; renders as a clickable chip that navigates to the target page

Content Outline

  • Collapsible outline panel listing all headings on the current page
  • Click any entry to scroll the editor to that heading
  • Headings inside tables are excluded

Workflow

  • Auto-save — debounced 1 second after the last keystroke
  • Manual save — Ctrl+S / Cmd+S for an immediate flush
  • Save indicator in the top bar (Saving… → Saved ✓)
  • Print — Ctrl+P or toolbar button; hides all UI chrome, resets layout to a clean page
  • Export — download a full notebook as a ZIP of HTML files (one per page) plus all images
  • Page width — drag the right-edge handle or pick a preset (Narrow / Medium / Wide) from the toolbar

Themes

  • Light and dark mode; follows system preference by default, overridable in Settings

Running with Docker (recommended)

Docker handles all dependencies — no Node.js installation required.

docker-compose up app

First run installs npm packages inside the container (~1–2 min). Once you see Starting dev servers...:

# Stop (keeps data and installed packages)
docker-compose stop

# Stop and remove containers (keeps data, discards package cache)
docker-compose down

# Stop and remove everything including named volumes
docker-compose down -v

# Rebuild after changing dependencies
docker-compose up --build app

Running locally (Node.js 20+)

# Install all workspace dependencies
npm install

# Start both the API server and the Vite dev server in parallel
npm run dev

By default, notebooks and images are stored in ~/Documents/NoteVault/. Change this in Settings.

Individual servers

npm run dev:server   # API only  → :3001
npm run dev:client   # UI only   → :5173

Build

npm run build   # compiles server TypeScript + bundles React client
npm run lint    # lint all workspaces

Deployment

The Dockerfile has a multi-stage production build that compiles the TypeScript server and bundles the React client into a single Node.js image (~120 MB). The server serves both the API and the static frontend from one port.

Build the production image

docker build --target production -t notevault .

Run it

docker run -d \
  --name notevault \
  -p 3001:3001 \
  -v /your/data/path:/app/storage \
  notevault

Replace /your/data/path with the absolute path on the host where you want notebooks and images to live. The app is then available at http://localhost:3001.

Environment variables

Variable Default Description
PORT 3001 Port the server listens on
STORAGE_PATH ~/Documents/NoteVault Absolute path to the storage directory
CLIENT_ORIGIN http://localhost:5173 Allowed CORS origin (dev only; ignored in production)
NODE_ENV Set to production to enable static file serving from client/dist

Reverse proxy (nginx / Caddy)

The production container exposes a single port. Point your proxy at it and increase the client body size for image uploads:

nginx

location / {
    proxy_pass         http://127.0.0.1:3001;
    proxy_set_header   Host $host;
    proxy_set_header   X-Real-IP $remote_addr;
    client_max_body_size 20m;
}

Caddy

your.domain.com {
    reverse_proxy localhost:3001
}

Security note: NoteVault is a personal, single-user tool. If you expose it on the internet, put it behind a firewall, VPN, or HTTP basic auth at the proxy level.


Mac App (Electron)

Packages NoteVault as a native .app / .dmg for macOS. The Express server runs inside the Electron process — no separate terminal or browser needed. Data is stored in ~/Library/Application Support/NoteVault/storage/.

Prerequisites

Node.js 20+ installed locally.

Build the DMG

# Install dependencies (once)
npm install

# Build client + server + Electron main process, then package
npm run electron:pack

The output lands in dist-app/ — a universal .dmg for both Apple Silicon and Intel (arm64 + x64).

Run without packaging (dev preview)

npm run electron:dev

Builds everything and opens an Electron window against the local server. Useful for testing before packaging.


Architecture

This is an npm workspaces monorepo with two packages: client/ and server/.

notevault/
├── client/                  # React + TipTap frontend (Vite)
│   └── src/
│       ├── components/
│       │   ├── editor/      # TipTap editor, toolbar, table menu, outline panel
│       │   ├── layout/      # AppShell, three-panel layout, TopBar
│       │   ├── modals/      # Notebook / section / confirm dialogs, color picker
│       │   └── sidebar/     # Notebook tree, section list, page list
│       ├── store/           # Zustand: notebookStore, uiStore
│       ├── hooks/           # useAutoSave, usePage, …
│       └── api/             # Axios wrapper (api/client.ts)
│
├── server/                  # Express REST API
│   └── src/
│       ├── routes/          # notebooks, sections, pages, images, settings, auth
│       └── services/
│           └── fileService.ts   # All reads/writes; no ORM, no database
│
├── storage/                 # Data directory (mounted as a volume in Docker)
│   ├── notebooks/           # One <uuid>.json per notebook + index.json
│   └── images/              # Uploaded images
│
├── electron/                # Electron wrapper for the Mac app
├── Dockerfile
└── docker-compose.yml

Data model

Each notebook is one self-contained JSON file. The hierarchy is:

Notebook → SectionGroup (optional) → Section → Page → SubPage (one level)

Page content is a TipTap JSON document (ProseMirror AST). This means individual pages are human-readable and portable — any tool that understands ProseMirror JSON can read them.

API base

http://localhost:3001/api

Resource Endpoints
Notebooks GET /notebooks · POST /notebooks · `GET
Sections POST /notebooks/:id/sections · `PUT
Pages `GET
Images POST /images/upload · GET /images/:filename
Settings `GET

Tech stack

Layer Technology
Frontend framework React 18 + TypeScript
Editor TipTap v2 (ProseMirror)
Styling Tailwind CSS v3 + custom CSS variables
State Zustand (with persist middleware)
Backend Express + TypeScript
Persistence Flat JSON files — no database
Build Vite (client) · tsc (server)
Icons Lucide React
Image upload Multer
Syntax highlighting lowlight (highlight.js grammar)
Desktop app Electron
Container Docker / Docker Compose

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages