Grumpy Tracker is a time tracking system for keeping track of work hours and flex time.
- Time reporting: work, travel, breaks, and extra time
- Flex balance calculation and summary
- Multilingual support (Swedish, English, Finnish, Norwegian, Latvian, Estonian, Lithuanian, Danish)
- User profiles and settings
- GDPR: data export and deletion
- Admin: user and translation management
- Responsive design with Tailwind CSS
- Node.js v20 or later
- Docker (for easy local development)
- PostgreSQL v16 (if not running via Docker)
git clone https://github.com/Bagro/grumpy-tracker.git
cd grumpy-trackerCopy .env.example to .env and fill in your values:
cp .env.example .env| Variable | Description | Example |
|---|---|---|
DATABASE_URL |
PostgreSQL connection string | postgres://grumpy:grumpysecret@localhost:5432/grumpytracker |
SESSION_SECRET |
Secret key for session management (keep private) | a-long-random-string |
NODE_ENV |
Environment (development / production) |
development |
Note:
DATABASE_URLis used at runtime by the app (viaprisma.config.tsandsrc/db.js) and bynpx prisma migratefor CLI operations.
docker-compose up --build- App: http://localhost:3000
- Database: port 5432
The container automatically runs npx prisma migrate deploy on startup before launching the server (see start.sh).
Note: The
docker-compose.ymlsetsDATABASE_URLfor the app container. AddSESSION_SECRETto the environment section indocker-compose.ymlfor production deployments.
-
Start PostgreSQL and create the database
grumpytracker -
Install dependencies:
npm install
-
Run database migrations:
npx prisma migrate deploy
For a brand new local environment (creates migration history):
npx prisma migrate dev
-
Build Tailwind CSS:
npm run tailwind:build
Or watch for changes during development:
npm run tailwind:watch
-
Start the app:
npm run dev
Register a user with the email admin@grumpy.local — it will automatically receive admin rights.
| File | Purpose |
|---|---|
.env |
Runtime environment variables (not committed) |
prisma.config.ts |
Prisma 7 datasource config — provides the pg adapter for CLI and ORM |
prisma/schema.prisma |
Database schema (models and relations) |
eslint.config.js |
ESLint flat config (ESLint 10+) |
vitest.config.js |
Vitest config with globals: true for Jest-compatible test syntax |
tailwind.config.js |
Tailwind CSS configuration |
docker-compose.yml |
Local Docker setup (app + PostgreSQL) |
The project has two test runners:
Vitest (default, recommended):
npx vitest runJest (legacy, used by npm test):
npm testIntegration tests require a running PostgreSQL database with
DATABASE_URLset.
To ensure all tables are created when using Docker:
docker compose down
docker compose up --build -d db
sleep 10
docker compose run --rm app npx prisma migrate deploy
docker compose exec db psql -U grumpy -d grumpytracker -c '\dt'You should see all tables from schema.prisma (User, TimeEntry, ExtraTime, Settings, WorkPeriod, Absence, Session, _prisma_migrations).
Make sure
prisma/migrations/is committed and not listed in.dockerignoreor.gitignore.
- Backend: Node.js (ESM), Express 5, Prisma 7, Passport.js, i18next
- Frontend: EJS templates, Tailwind CSS 4, htmx (attribute-based, forms also work without JS)
- Database: PostgreSQL 16 via
@prisma/adapter-pg - Linting: ESLint 10 with flat config (
eslint.config.js) - See
.github/copilot-instructions.mdfor code standards
This project is licensed under the MIT License. See the LICENSE file for details.