A self-hosted note-taking application built with Go backend and React frontend. The server serves both the API and the web application from a single port, making deployment and development simple.
- Notes Management: Create, edit, delete, and organize notes
- Note Types: Support for both plain text notes and todo lists with checkboxes
- Search & Filter: Find notes quickly with search and filtering capabilities
- Responsive Design: Works on desktop and mobile devices
- Self-hosted: Complete control over your data
- SQLite Database: Lightweight, file-based database
- Admin Support: First registered user becomes admin
- Single Binary: Frontend and backend served from one Go binary
- Sliding Sessions: 30-day sessions auto-extend when less than 7 days remain
- Go 1.24+: Download Go
- Node.js 24+: Download Node.js
- npm: Package manager for frontend dependencies
-
Clone the repository:
git clone <repository-url> cd jot
-
Build and run (recommended for most development):
# Build the frontend cd webapp npm install npm run build cd .. # Start the server (serves both API and frontend) cd server go mod tidy COOKIE_SECURE=false go run main.go
This project includes a Taskfile for common development tasks:
# Install Task (if not already installed)
go install github.com/go-task/task/v3/cmd/task@latest
# Available commands
task run-server # Start the Jot server
task run-webapp # Start webapp dev server with HMR
task test # Run all tests
task test-server # Run server tests
task test-webapp # Run webapp tests
task test-e2e # Run Playwright end-to-end tests
task test-mobile # Run mobile app tests
task coverage # Run server tests with coverage report
task lint # Run linters
task lint-server # Run server linting with golangci-lint
task lint-webapp # Run webapp linting
task lint-mobile # Run mobile app linting
task check-translations # Check locale files for missing/extra keys
task gen-docs # Regenerate Swagger API docs (install swag first: go install github.com/swaggo/swag/cmd/swag@v1.16.6)
task clean # Remove generated files and node packages- Access the application:
- Open
http://localhost:8080in your browser - Register your first account with a username and password (becomes admin automatically)
- Start creating notes!
- Open
Run the Vite dev server for instant hot module replacement:
# Terminal 1: Start the Go backend
COOKIE_SECURE=false task run-server
# Terminal 2: Start the Vite dev server with HMR
task run-webappAccess: http://localhost:5173 — API calls are proxied to the Go server automatically.
Configure the application using environment variables or .env file:
# Database configuration
DB_PATH=./jot.db # SQLite database file location
# Server configuration
PORT=8080 # Server port (optional)
STATIC_DIR=../webapp/build/ # Frontend build directory (optional)The full interactive API reference is available via Swagger UI at http://localhost:8080/api/docs/index.html when the server is running.
Build everything into one executable:
# 1. Build frontend (production build)
cd webapp
npm install
npm run build
cd ..
# Alternative: Development build (unminified, with source maps)
# npm run build:dev
# 2. Build backend (includes frontend files)
cd server
go build -o jot main.go
# 3. Deploy single binary
./jotThe binary will serve both API and frontend from port 8080.
Create .env file for production:
# Production environment
DB_PATH=/var/lib/jot/jot.db
PORT=8080# Pull and run the latest image from Docker Hub
docker run -d \
--name jot \
-p 8080:8080 \
-v ./data:/data \
hanzei/jot:latest
# Or use docker-compose
curl -O https://raw.githubusercontent.com/hanzei/jot/master/docker-compose.yml
# add COOKIE_SECURE=false under jot.environment for local HTTP use
docker-compose up -d# Build and run with docker-compose
docker-compose up -d
# Or build manually
docker build -t jot .
docker run -p 8080:8080 -v ./data:/data jotThe Docker image uses multi-stage build:
- Node.js stage: Builds the React frontend
- Go stage: Builds the backend binary
- Alpine stage: Combines everything in minimal production image
For production HTTPS, keep the default secure cookie behavior.
For local HTTP-only testing, override with:
docker run -p 8080:8080 -e COOKIE_SECURE=false -v ./data:/data jothanzei/jot:latest- Latest stable release (master branch)hanzei/jot:pr-<number>- Pull request buildshanzei/jot:<branch>-<sha>- Specific commit builds
# docker-compose.override.yml
version: '3.8'
services:
jot:
image: hanzei/jot:latest
environment:
- DB_PATH=/data/production.db
volumes:
- ./custom-data:/data
ports:
- "80:8080" # Expose on port 80-
Frontend not loading:
# Check if frontend is built ls webapp/build/ # Rebuild frontend cd webapp && npm run build
-
Database permissions:
# Fix SQLite file permissions chmod 664 jot.db -
Port conflicts:
# Use different port PORT=9000 go run main.go -
Migration errors:
# Reset database (WARNING: deletes all data) rm jot.db -
Build errors:
# Clean and rebuild cd webapp && rm -rf node_modules dist build && npm install && npm run build cd ../server && go clean && go mod tidy
- Frontend changes: Rebuild with
npm run buildafter React changes - Backend changes: Restart the server after code changes
- Database inspection: Use SQLite browser or
sqlite3 jot.db - Logs: Check console output for detailed error messages
- API testing: Use browser dev tools or curl/Postman
# Run the server directly
COOKIE_SECURE=false go run main.go
# Frontend development build (separate dev server)
cd webapp && npm run dev
# Or start the Vite dev server with HMR
task run-webapp
# Check database contents
sqlite3 jot.db "SELECT * FROM users;"- Fork the repository
- Clone your fork:
git clone https://github.com/yourusername/jot.git - Create feature branch:
git checkout -b feature/amazing-feature - Make your changes following the existing code style
- Test your changes thoroughly
- Commit your changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Submit a pull request
- Follow Go and React best practices
- Add tests for new functionality
- Update documentation for API changes
- Ensure Docker build passes
- Test both development modes
Jot uses GitHub Actions for automated testing and Docker image publishing:
- Automated testing: All PRs trigger test and lint jobs
- Docker publishing: Master branch builds are published to
hanzei/joton Docker Hub - Multi-platform: Images support both AMD64 and ARM64 architectures
[Add your license here - e.g., MIT, GPL-3.0, etc.]
Jot - Simple, fast, and secure note-taking for everyone. 🚀




