AIVOT

Every constraint, a solution.

Quick start View on GitHub
Why AIVOT

Scheduling that explains itself

Most planning tools give you a grid or an error. AIVOT gives you a grid and the reasoning: why this schedule, why an empty one, and — when no schedule exists — exactly which rules collide.

Requirements & preferences

Every rule is either a hard requirement or a weighted preference. The engine satisfies the former, sacrifices the latter as little as possible — and reports every violation with its cost.

🔍

Explained outcomes

Empty result? AIVOT tells you no rule forces assignments. Infeasible? It lists the minimal core of conflicting rules, so you know precisely what to relax.

🧩

No-code rule builder

21 catalog rules across 8 families, plus a custom builder: count assignments per shift, person, day, week or sliding window — with filters — and bound the result. No code.

🛍

Recipe store

Publish rule sets that work, install the community's. Recipes are pure data — never code — with admin moderation built in.

📺

Embeddable schedules

Every schedule can become a public widget: one revocable <iframe> to paste into any website, intranet or wiki.

🌍

Bilingual, end to end

English and Italian across the UI, API messages, solver explanations, emails and the rule catalog itself. Adding a language is a dictionary, not a rewrite.

How it works

Five guided steps

A path anyone can follow the first time, and skip around freely afterwards.

1
Project A container for one planning problem
2
People Names and skills — or bulk import from Excel/CSV
3
Shifts Generated from your day bands and date range
4
Rules Picked from the catalog, tuned with weights
5
Schedule Computed, explained, archived, embeddable
Under the hood

One engine, many rules

Rules are data (JSON in the database), translated into a CP-SAT model at runtime. The engine — Google OR-Tools — never changes; the variety lives in the catalog.

USER ── composes ──> ConstraintInstance   JSON data in DB, never code
                          │
                          ▼  runtime translation
                solver/handlers.py        registry: type → ctx.limit(…)
                          │
                          ▼
                solver/engine.py          two-phase CP-SAT1) fast solve, full presolve2) if infeasible → conflict core
                          ▼
                Run + explain.py          assignments · violations ·
                                          conflicts · explanation

The two-phase design matters: solving without assumption literals keeps CP-SAT's presolve at full strength (milliseconds on typical problems), while the second pass — run only on infeasibility — identifies the minimal set of rules to blame.

The catalog

21 rules, 8 families — and yours

Core rules Coverage Capacity Sequence Fairness Preferences People & pairs Custom

Minimum coverage

At least N people (optionally with a skill) on every shift.

Minimum rest

At least N hours between shifts — midnight-crossing aware.

Forbidden sequence

After a night, no morning the day after.

Fair distribution

Night shifts spread evenly: max−min within tolerance.

Paired people

Tutor and trainee always share the same shifts.

Custom rule

“Each person, at most 2 nights per sliding 7-day window, weekends only, in August.” Built from a form.

Quick start

One command

# clone, then:
docker compose up --build
WhatWhereCredentials
Platformlocalhost:5173 sign up, or demo / demo1234
Backofficelocalhost:8001/admin admin / aivot-admin
APIlocalhost:8001/api token via /api/auth/login/
Everything is configurable via .env (emails through Brevo, Google Sign-In, admin credentials) — and nothing breaks if you configure none of it. See the README for the full reference.

…or deploy to the cloud

One button provisions the whole stack on Google Cloud — Cloud SQL, Cloud Run for the Django backend, Firebase Hosting for the frontend, and the Cloud Tasks queues that run emails and solver jobs in the background.

Open in Cloud Shell

It opens Google Cloud Shell; run bash deploy.sh, answer a couple of prompts (project id, billing account) and it builds everything in ~10–15 minutes, then prints the live URLs. Creating a new project requires picking a billing account (Google's cost protection); the rest is automatic.

Answer yes to the CI/CD pipeline prompt and it also wires up push-to-deploy: state on a shared bucket, a deploy service account, and your GitHub secrets set for you. After that every push to the production branch redeploys automatically:

git push origin main:production
Full deploy guide, fork instructions, least-privilege roles and the CI/CD runbook: infra/README.