The Formula 1 fantasy game — create a private league with your friends, run a credit auction to build your roster of drivers and teams, and challenge each other race after race with scores calculated automatically from real Championship results.
Built to be self-hosted: one docker compose up and you're ready — your data and accounts stay on your own server.
👉 See the screenshots to get a feel for it.
Calendar, driver and result data is imported automatically from the Jolpica F1 API (free, Ergast's successor). This project is not affiliated with Formula 1®, the FIA, or Jolpica.
Just Docker and Docker Compose — no other dependency to install on the machine.
git clone https://github.com/<your-username>/fanta-f1.git
cd fanta-f1
cp .env.example .env
docker compose up -d --build
On first boot the app generates its own application key and creates the database tables — no extra manual command needed. After a minute (build time), the app is ready at http://localhost:8080.
Last step, to be done once, to import the current season's calendar and drivers:
docker compose exec app php artisan f1:sync-season
From here on, the calendar and results update automatically on their own (the scheduler service checks daily/hourly). Go to http://localhost:8080, sign up, and create your first league.
Edit APP_PORT in the .env file before starting the containers (or run docker compose up -d again if already running), and update APP_URL accordingly.
The docker-compose.yml publishes nginx directly on the chosen port (APP_PORT, default 8080) and works as-is. If you want to put it behind Traefik, Caddy, or another proxy with your own domain/TLS, create a docker-compose.override.yml file (automatically loaded by Docker Compose alongside the main file, and should never be committed to Git) with something like:
services:
nginx:
networks:
- my_proxy_network
labels:
- traefik.enable=true
- traefik.http.routers.fantaf1.rule=Host(`fantaf1.yourdomain.com`)
- traefik.http.routers.fantaf1.entrypoints=websecure
- traefik.http.routers.fantaf1.tls=true
- traefik.http.services.fantaf1.loadbalancer.server.port=80
networks:
my_proxy_network:
external: true
Adjust the network names and labels to match your proxy, then docker compose up -d.
# Update the app after a git pull
docker compose up -d --build
# Tail a service's logs
docker compose logs -f app
# Manually import/refresh a specific season
docker compose exec app php artisan f1:sync-season 2027
# Import/force the results of a specific race (ID from the races table)
docker compose exec app php artisan f1:sync-results 1
# Laravel console (tinker)
docker compose exec app php artisan tinker
| Service | What it does |
|---|---|
app | Laravel application (PHP-FPM) |
nginx | web server, published on APP_PORT |
queue | processes background jobs (score calculation after each race) |
scheduler | runs periodic checks (new results, auction round closing) |
db | MySQL 8 |
redis | cache, sessions, and queues |
phpmyadmin | (optional) web UI for the database, on :8081 — remove it from the file if you don't need it |
Database data and compiled assets live in named Docker volumes, independent of the containers: you can recreate the containers without losing anything.
Laravel 11 · Livewire 3 · Tailwind CSS · MySQL · Redis · Vite + vite-plugin-pwa · Jolpica F1 API.
MIT — see LICENSE.
The Formula 1 fantasy game — create a private league with your friends, run a credit auction to build your roster of drivers and teams, and challenge each other race after race with scores calculated automatically from real Championship results.
Built to be self-hosted: one docker compose up and you're ready — your data and accounts stay on your own server.
👉 See the screenshots to get a feel for it.
Calendar, driver and result data is imported automatically from the Jolpica F1 API (free, Ergast's successor). This project is not affiliated with Formula 1®, the FIA, or Jolpica.
Just Docker and Docker Compose — no other dependency to install on the machine.
git clone https://github.com/<your-username>/fanta-f1.git
cd fanta-f1
cp .env.example .env
docker compose up -d --build
On first boot the app generates its own application key and creates the database tables — no extra manual command needed. After a minute (build time), the app is ready at http://localhost:8080.
Last step, to be done once, to import the current season's calendar and drivers:
docker compose exec app php artisan f1:sync-season
From here on, the calendar and results update automatically on their own (the scheduler service checks daily/hourly). Go to http://localhost:8080, sign up, and create your first league.
Edit APP_PORT in the .env file before starting the containers (or run docker compose up -d again if already running), and update APP_URL accordingly.
The docker-compose.yml publishes nginx directly on the chosen port (APP_PORT, default 8080) and works as-is. If you want to put it behind Traefik, Caddy, or another proxy with your own domain/TLS, create a docker-compose.override.yml file (automatically loaded by Docker Compose alongside the main file, and should never be committed to Git) with something like:
services:
nginx:
networks:
- my_proxy_network
labels:
- traefik.enable=true
- traefik.http.routers.fantaf1.rule=Host(`fantaf1.yourdomain.com`)
- traefik.http.routers.fantaf1.entrypoints=websecure
- traefik.http.routers.fantaf1.tls=true
- traefik.http.services.fantaf1.loadbalancer.server.port=80
networks:
my_proxy_network:
external: true
Adjust the network names and labels to match your proxy, then docker compose up -d.
# Update the app after a git pull
docker compose up -d --build
# Tail a service's logs
docker compose logs -f app
# Manually import/refresh a specific season
docker compose exec app php artisan f1:sync-season 2027
# Import/force the results of a specific race (ID from the races table)
docker compose exec app php artisan f1:sync-results 1
# Laravel console (tinker)
docker compose exec app php artisan tinker
| Service | What it does |
|---|---|
app | Laravel application (PHP-FPM) |
nginx | web server, published on APP_PORT |
queue | processes background jobs (score calculation after each race) |
scheduler | runs periodic checks (new results, auction round closing) |
db | MySQL 8 |
redis | cache, sessions, and queues |
phpmyadmin | (optional) web UI for the database, on :8081 — remove it from the file if you don't need it |
Database data and compiled assets live in named Docker volumes, independent of the containers: you can recreate the containers without losing anything.
Laravel 11 · Livewire 3 · Tailwind CSS · MySQL · Redis · Vite + vite-plugin-pwa · Jolpica F1 API.
MIT — see LICENSE.