Privacy-first mood tracker and daily journal, designed for effortless self-hosting.
Your data, your server, your rules.
Nightlio was inspired by awesome mood-tracking apps like Daylio, but born out of frustration with aggressive subscription models, paywalls, and a lack of cross-platform access. I wanted a beautiful, effective tool to log my mood and journal my thoughts without compromising on privacy or being locked into a single device.
Nightlio is the result: a feature-complete, open-source alternative that you can run anywhere. It's fully web-based and responsive for use on both desktop and mobile. No ads, no subscriptions, and absolutely no data mining. Just you and your data.
- Rich Journaling with Markdown: Write detailed notes for every entry using Markdown for formatting, lists, and links.
- Track Your Mood & Find Patterns: Log your daily mood on a simple 5-point scale and use customizable tags (e.g., 'Sleep', 'Productivity') to discover what influences your state of mind.
- Insightful Analytics: View your mood history on a calendar, see your average mood over time, and track your journaling streak to stay motivated.
- Privacy First, Always: Built from the ground up to be self-hosted. Your sensitive data is stored in a simple SQLite database file on your server. No third-party trackers or analytics.
- Simple Self-Hosting with Docker: Get up and running in minutes with a single
docker compose upcommand. - Gamified Achievements: Stay consistent with built-in achievements that unlock as you build your journaling habit.
Note
By default, Nightlio runs in single-user mode. Enable Google OAuth for multi-user support.
Get your own Nightlio instance running in under 5 minutes.
# 1. Clone the repository
git clone https://github.com/shirsakm/nightlio.git
cd nightlio
# 2. Create your configuration file
cp .env.docker .env
# 3. Set your secrets
# IMPORTANT: Open the .env file and set unique, random values for
# at least SECRET_KEY and JWT_SECRET.
nano .env
# 4. Launch the application (uses published images by default)
docker compose up -dAlternatively, give it a try without cloning!
docker network create nightlio-test || true
docker run -d --name nightlio-api \
--network nightlio-test --network-alias api \
-e SECRET_KEY=$(openssl rand -hex 32) \
-e JWT_SECRET=$(openssl rand -hex 32) \
-e CORS_ORIGINS=http://localhost:5173 \
-e ENABLE_GOOGLE_OAUTH=0 \
-e DEFAULT_SELF_HOST_ID=selfhost_default_user \
-e DATABASE_PATH=/app/data/nightlio.db \
-e PORT=5000 \
-v nightlio_data:/app/data \
ghcr.io/shirsakm/nightlio-api:latest
docker run -d --name nightlio-frontend \
--network nightlio-test \
-p 5173:80 \
ghcr.io/shirsakm/nightlio-frontend:latestYour instance is now live at http://localhost:5173/.
Here are two easy paths for self-hosting using the published GHCR images.
- Clone and configure
git clone https://github.com/shirsakm/nightlio.git
cd nightlio
cp .env.docker .env
# Edit .env: set strong SECRET_KEY and JWT_SECRET, and set CORS_ORIGINS to your domain- Pin images (recommended) and mount data for backups
export API_IMAGE=ghcr.io/shirsakm/nightlio-api:latest
export WEB_IMAGE=ghcr.io/shirsakm/nightlio-frontend:latest
mkdir -p data
# Add a bind mount for your DB by editing docker-compose.prod.yml (api service):
# volumes:
# - ./data:/app/data- Bring up the stack (nginx is the only public service)
docker compose -f docker-compose.prod.yml up -dTLS: put your certs in ./ssl (fullchain.pem, privkey.pem). The provided nginx config will serve 80/443.
Upgrade later:
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -dCreate docker-compose.yml in an empty folder with:
services:
api:
image: ghcr.io/shirsakm/nightlio-api:latest
restart: unless-stopped
environment:
- SECRET_KEY=change-me
- JWT_SECRET=change-me-too
- CORS_ORIGINS=https://your.domain
- ENABLE_GOOGLE_OAUTH=0
- DEFAULT_SELF_HOST_ID=selfhost_default_user
- DATABASE_PATH=/app/data/nightlio.db
- PORT=5000
volumes:
- ./data:/app/data
expose:
- "5000"
networks: { nightlio: { aliases: [api] } }
web:
image: ghcr.io/shirsakm/nightlio-frontend:latest
restart: unless-stopped
depends_on: [api]
ports:
- "80:80" # or put behind your own reverse proxy with TLS
networks: [nightlio]
networks: { nightlio: {} }Run it:
docker compose up -dNote
- Persistent data lives in
./data/nightlio.dbβ include it in backups. - Pin to a version for predictable upgrades; switch to newer tags when ready.
You can customize your Nightlio instance using environment variables in the .env file.
# Core
FLASK_ENV=production
SECRET_KEY=change-this-to-a-long-random-string
JWT_SECRET=change-this-too
DATABASE_PATH=/app/data/nightlio.db
# Feature flags (1 to enable, 0 to disable)
ENABLE_GOOGLE_OAUTH=0
# Google OAuth (if enabled)
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=
# CORS - Add your frontend's domain if deploying publicly
CORS_ORIGINS=http://localhost:5173,[https://your.domain.com](https://your.domain.com)
# This is only needed for local development outside of Docker
VITE_API_URL=http://localhost:5000
# Required for Google OAuth (if enabled)
VITE_GOOGLE_CLIENT_ID=
Interested in contributing or running the project without Docker? Here's what you need to know.
Architecture Overview
- Frontend: React 19 + Vite, served by Nginx.
- Backend: Flask (Python) serving a JSON API.
- Database: SQLite, with auto-migrations on startup.
- Database layer: Modular mixins live in
api/database_*.pywithapi/database.pyacting as the facade. - Authentication: JWT-based. Supports a default local user and optional Google OAuth.
Local Development Setup
Prerequisites: Node.js v18+, Python v3.11+
# Install frontend dependencies
npm install
# Setup and activate backend virtual environment
cd api
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
cd ..
# Run both servers concurrently
npm run dev # Starts Vite frontend dev server
npm run api:dev # Starts Flask backend API serverThe frontend will be available at http://localhost:5173.
API Reference
All protected endpoints require an Authorization: Bearer <jwt> header unless otherwise noted.
Auth
POST /api/auth/local/loginβ 200 { token, user }POST /api/auth/google { token }β 200 { token, user }POST /api/auth/verifyβ 200 { user }
Config & Misc
GET /api/configβ { enable_google_oauth }GET /api/β health payloadGET /api/timeβ { time }
Moods
POST /api/mood { date, mood(1-5), content, time?, selected_options?: number[] }β 201 { entry_id, new_achievements[] }GET /api/moods[?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD]β list of entriesGET /api/mood/:idβ entryPUT /api/mood/:id { mood?, content? }β successDELETE /api/mood/:idβ successGET /api/mood/:id/selectionsβ options linked to the entryGET /api/statisticsβ { statistics, mood_distribution, current_streak }GET /api/streakβ { current_streak, message }
Groups & Options
GET /api/groupsβ [{ id, name, options: [{ id, name }] }]POST /api/groups { name }β { group_id }POST /api/groups/:group_id/options { name }β { option_id }DELETE /api/groups/:group_idβ successDELETE /api/options/:option_idβ success
Achievements
GET /api/achievementsβ user achievements (with metadata)POST /api/achievements/checkβ { new_achievements, count }
Data Model
Tables (SQLite):
users: id, google_id, email, name, avatar_url, ...mood_entries: id, user_id(FK), date, mood, content, ...groups: id, namegroup_options: id, group_id(FK), nameentry_selections: entry_id(FK), option_id(FK)achievements: id, user_id(FK), achievement_type, earned_at, ...
- Data Ownership: Your data is stored in a local SQLite file. You can back it up, move it, or delete it at any time.
- No Telemetry: This application does not collect any usage data or send information to third-party services.
- Secure Authentication: API endpoints are protected using JSON Web Tokens (JWT).
- Configurable CORS: Restrict API access to trusted domains via environment variables.
Nightlio is actively developed. Here are some of the features planned for the future:
- Responsive Design: Full support for usage on mobile devices.
- Multi-User Support: Full support for multiple user accounts on a single instance.
- Data Import/Export: Tools to import data from other services (like Daylio) and export your data to standard formats (JSON, CSV).
- More Themes & Customization: Additional themes and more options to personalize the look and feel of your journal.
- Advanced Analytics: Deeper insights into your data, including correlations between tags and mood.
Pull requests are welcome! For major changes, please open an issue first to discuss what you would like to change.
Please ensure you run the tests before opening a PR:
npm testThis command runs the backend tests using pytest. Please ensure you add tests for any new API functionality.
This project is licensed under the MIT License - see the LICENSE file for details.