Skip to content

shirsakm/nightlio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Nightlio

GitHub license GitHub stars GitHub Actions Workflow Status GitHub last commit GitHub Tag

Privacy-first mood tracker and daily journal, designed for effortless self-hosting.
Your data, your server, your rules.

Preview

Why Nightlio?

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.

Key Features

  • 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 up command.
  • Gamified Achievements: Stay consistent with built-in achievements that unlock as you build your journaling habit.
πŸŒ™

Usage

Docker Quickstart (Recommended)

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 -d

Alternatively, 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:latest

Your instance is now live at http://localhost:5173/.

Self-hosting

Here are two easy paths for self-hosting using the published GHCR images.

Use the repo’s production compose (nginx + TLS)

  1. 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
  1. 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
  1. Bring up the stack (nginx is the only public service)
docker compose -f docker-compose.prod.yml up -d

TLS: 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 -d

Minimal compose

Create 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 -d

Note

  1. Persistent data lives in ./data/nightlio.db β€” include it in backups.
  2. Pin to a version for predictable upgrades; switch to newer tags when ready.
πŸŒ™

πŸ”§ Configuration (.env)

You can customize your Nightlio instance using environment variables in the .env file.

Server (API)

# 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)

Frontend (Vite)

# 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=
πŸŒ™

Developer Reference

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_*.py with api/database.py acting 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 server

The 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 payload
  • GET /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 entries
  • GET /api/mood/:id β†’ entry
  • PUT /api/mood/:id { mood?, content? } β†’ success
  • DELETE /api/mood/:id β†’ success
  • GET /api/mood/:id/selections β†’ options linked to the entry
  • GET /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 β†’ success
  • DELETE /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, name
  • group_options: id, group_id(FK), name
  • entry_selections: entry_id(FK), option_id(FK)
  • achievements: id, user_id(FK), achievement_type, earned_at, ...
πŸŒ™

Security & Privacy

  • 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.

Roadmap

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.

Contributing

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 test

This command runs the backend tests using pytest. Please ensure you add tests for any new API functionality.

License

This project is licensed under the MIT License - see the LICENSE file for details.

About

A minimal mood logger and journal.

Topics

Resources

License

Stars

Watchers

Forks

Sponsor this project

 

Packages

 
 
 

Contributors 5