selfhostable, dead simple, period tracker as a progressive web app | github.com/andreuinyu/periodt
5.2K
A privacy-first, self-hosted, dead simple period tracking Progressive Web App. Data stays in your server of choice and you can use it on the web or on your phone as an app.
Periodt is built as a Progressive Web App, which is basically a website that can be "installed" on a device as a standalone application. This allows the users to have a nice mobile experience, without having to develop Android and iOS standalone applications and the hassle of publishing them on app stores.
⚠️IMPORTANT⚠️: this will only work if you access your Periodt service via HTTPS.
Create a (or add to your existing) docker-compose.yml file in a folder of your choosing:
services:
periodt:
container_name: periodt
image: ghcr.io/andreuinyu/periodt:latest # or, andreuinyu/periodt:latest
restart: unless-stopped
ports:
- "3111:8000"
volumes:
- ./periodt_data:/data
environment:
- TZ=UTC
- NOTIFY_DAYS_BEFORE=3
- NOTIFY_HOUR=9
and bring it up with
docker compose up -d
Edit docker-compose.yml to change the port:
ports:
- "2333:8000" # expose on port 2333
or modify the environment variables to the values that suit you the best (if not provided at all, the values will default to these values shown above):
environment:
- TZ=Europe/Dublin
- NOTIFY_DAYS_BEFORE=5
- NOTIFY_HOUR=7
TZ should be something like America/New_York or Europe/Dublin. Find out which one suits you best here.NOTIFY_DAYS_BEFORE configures how many days before the period is supposed to arrive (based off of the historic average) should notifications be sent out to subscribed users.NOTIFY_HOUR configures at what time will the server check if notifications are to be sent out.If instead of useing a real path of your choosing /path/to/your/periodt_data:/data to map the database file out of Docker, you are using a docker volume in the docker-compose.yml (like periodt_data:/data), you can still back it up with:
docker run --rm -v periodt_data:/data -v $(pwd):/backup alpine \
cp /data/tracker.db /backup/tracker_backup.db
⚠️IMPORTANT⚠️: this will only work if you access your Periodt service via HTTPS.
There are many ways to route your self-hosted services through HTTPS. Amongst them:
Any help is welcome, but especially:
value is the name of each .json):
<select id="lang-select" class="settings-select">
<option value="en">English</option>
<option value="cat">Català</option>
<option value="es">Español</option>
...
</select>
const localeMap = { en: 'en-US', cat: 'ca-ES', es: 'es-ES', ... };
| Layer | Tech |
|---|---|
| Backend | Python 3.14 + FastAPI |
| Database | SQLite |
| Frontend | Vanilla JS PWA |
| Container | Docker + Docker Compose |
Set yourself up with:
# 1. Clone / download this folder
cd periodt
# 2. Build and start
docker compose up --build
# 3. Open your browser
open http://localhost:3111
| Method | Path | Description |
|---|---|---|
| GET | /api/cycles | List all cycles |
| POST | /api/cycles | Start a new cycle |
| PATCH | /api/cycles/{id} | Update cycle (e.g. set end date) |
| DELETE | /api/cycles/{id} | Delete a cycle |
| GET | /api/symptoms | List symptom logs |
| POST | /api/symptoms | Log symptoms |
| DELETE | /api/symptoms/{id} | Delete a symptom log |
| GET | /api/predictions | Get next period prediction |
| GET | /api/push/vapid-public-key | Get key for push notifications |
| POST | /api/push/subscribe | Register push subscription |
| POST | /api/push/unsubscribe | Delete push subscription |
| GET | /api/version | dev for local or vX.Y.Z for release |
| GET | /health | for Docker integration |
Interactive API docs: http://localhost:3111/docs
period-tracker/
├── Dockerfile
├── docker-compose.yml # for local developing
├── README.md
├── backend/
│ ├── main.py # FastAPI app
│ ├── notifications.py # Notification handling
│ ├── log_config.json
│ └── requirements.txt
└── frontend/
├── index.html # PWA shell
├── sw.js # Service worker
└── static/
├── manifest.json
├── scripts.js
├── styles.css
├── translations/LANGUAGE.json
└── icons/
├── icon-192.png
└── icon-512.png
Content type
Image
Digest
sha256:0ae9f6ca9…
Size
53.8 MB
Last updated
3 months ago
docker pull andreuinyu/periodt