Tree-based markdown documentation. No database for content. Single binary deployment.
NoteRoot is a high-performance, self-hosted documentation engine designed for developers, homelabs, and internal engineering teams. It treats the local filesystem as the absolute source of truth for your content while layering on an embedded SQLite database for authentication and user permission management, all delivered as a single compiled Go binary.
NoteRoot is built on a decoupled client-server architecture, bound together during the final build process.
- Language: Go 1.23
- Routing:
gin-gonic/ginfor high-throughput HTTP REST API routing. - Persistence:
modernc.org/sqlite(CGO-free embedded SQLite) strictly for user management and auth state. Content is strictly filesystem-bound. - Authentication:
golang-jwt/jwt/v5handling stateless JWT issuing and verification. - Utilities:
gosimple/slugfor URL-safe path generation,x/crypto/bcryptfor secure credential hashing.
- Framework: React 19 + TypeScript, bundled with Vite.
- Routing & State:
react-router-domfor client-side routing,zustandfor lightweight global state management. - UI & Styling: Neo-brutalist Design System built via TailwindCSS, featuring bold contrast, flat colors, and
framer-motionfor micro-interactions. Accessible base primitives powered by Radix UI. - Markdown Rendering:
react-markdownecosystem (remark-gfm,rehype-highlight) for GitHub-flavored markdown and syntax highlighting.
NoteRoot intentionally avoids storing documentation content in a relational database.
- The
PageStoreinterface implemented ininternal/core/tree/traverses a specified target directory (--docs). - Directories represent structural nodes;
.mdfiles act as standard pages, whileindex.mdacts as a directory's root content. - Page rendering, structural tree generation, and path resolution happen dynamically. Slug collisions are mitigated via backend sequence checking.
- Stateless API Layer: Protected routes use Go middleware to validate
BearerJWT tokens embedded in theAuthorizationheader. - User Segregation: The system supports Admin and Editor roles. Read-only endpoints do not inherently require auth if public viewing is enabled, while mutations (POST/PUT/DELETE) enforce rigid JWT checks against the SQLite user table.
The typical deployment model compiles the React frontend into static assets (dist/), which are then embedded directly into the Go binary using the embed package. The Gin router serves static files natively, routing all unrecognized paths to index.html to allow react-router to take over client side routing.
Ensure you have Go 1.23+ and Node.js installed.
cd ui/noteroot-ui
npm install
npm run buildCopy the contents of ui/noteroot-ui/dist/ into internal/http/dist/ if you are embedding the UI into the binary.
# Return to the repo root
go build -o noteroot ./cmd/noterootFor local active development, run the backend and frontend separately:
Start the Go API Server:
go run ./cmd/noteroot/main.go --port 8080 --jwt-secret "dev-secret" --docs ./test-docsStart the Vite Dev Server:
cd ui/noteroot-ui
npm run devThe Vite dev server proxies all /api requests to localhost:8080, bypassing CORS issues and ensuring exact environment parity with production.
NoteRoot can be configured using command-line flags or environment variables.
| Flag | Environment Variable | Default | Description |
|---|---|---|---|
--docs |
NOTEROOT_DOCS |
./docs |
Target directory for Markdown storage. |
--port |
NOTEROOT_PORT |
8080 |
HTTP listener port. |
--host |
NOTEROOT_HOST |
0.0.0.0 |
Bind interface. |
--admin-password |
NOTEROOT_ADMIN_PASSWORD |
admin |
Seed password for the initial admin user. |
--jwt-secret |
NOTEROOT_JWT_SECRET |
runtime | Cryptographic secret for signing auth tokens. |
REST architectural endpoints mapped in router.go:
POST /api/auth/loginβ Validates bcrypt hash, issues short-lived JWT.GET /api/usersβ Returns sanitized user structs (Admin only).
GET /api/treeβ Recursively generates JSON schema of the doc tree.GET /api/pages/by-pathβ Traverses filesystem to return specific MD payload.POST /api/pagesβ Injects new node into the virtual tree, writes literal.mdfile to disk.PUT /api/pages/:id/moveβ Triggers an OS-level file move/rename, re-indexes virtual tree.
- Handles
multipart/form-datauploads, streaming bytes directly to the associated page directory alongside the.mdfile.
NoteRoot was built with a strict adherence to operational simplicity:
- No External Dependencies: Docker, Postgres, Redis, and reverse proxies are strictly optional.
- Text is King: Standard tools (
git,grep,rsync) remain the best ways to interact with text. NoteRoot layers on top of this abstraction, rather than hiding text in a DB BLOB field.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request
Distributed under the MIT License. See LICENSE for more information.