TOSTI is a comprehensive web application designed for Tartarus to manage take-away orders and various other features for student associations at Radboud University.
- Order Management System: Online ordering system for take-away items (such as tostis)
- Financial Transactions: User balance tracking and transaction management
- User Authentication: SAML-based SSO integration (with Radboud University via SURFconext)
- Music Control: Spotify and Marietje integration for controlling music players
- Room Reservations: Venue reservation system with calendar integration
- Borrel Management: Event reservation system with inventory tracking
- Age Verification: Yivi-based age verification system
- Smart Fridge Access: Digital lock system for automated fridge access, using TOSTI-fridge-client
- QR Code Identification: Token-based user identification system
- Bookkeeping Integration: Synchronization with Silvasoft accounting system
- Multi-venue support with separate canteens (North/South)
- Real-time order status tracking
- Statistics and analytics dashboard
- OAuth2 API for third-party integrations
- iCal feeds for reservations
- Automated music scheduling
TOSTI is built using:
- Backend: Django 5.1 (Python)
- Frontend: Django templates with Bootstrap 5
- Database: PostgreSQL (production) / SQLite (development)
- Caching: File-based cache (production) / In-memory (development)
- Authentication: SAML2 (via djangosaml2)
- API: Django REST Framework with OAuth2
- Task Scheduling: Custom cron implementation
- Containerization: Docker & Docker Compose
website/
├── age/ # Age verification module
├── announcements/ # System announcements
├── associations/ # Student associations management
├── borrel/ # Event/borrel reservation system
├── cron/ # Custom cron job implementation
├── fridges/ # Smart fridge access control
├── orders/ # Core ordering system
├── qualifications/ # User qualifications (e.g., borrel brevet)
├── silvasoft/ # Bookkeeping integration
├── status_screen/ # Order status display
├── thaliedje/ # Music player control
├── tosti/ # Main application settings
├── transactions/ # Financial transactions
├── users/ # User management
├── venues/ # Venue reservation system
└── yivi/ # Yivi integration for age verification
-
Clone the repository
git clone https://github.com/KiOui/TOSTI.git cd TOSTI -
Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh -
Set up uv environment
uv sync --locked --all-extras --dev
-
Set up the database
cd website uv run ./manage.py migrate -
Create a superuser
uv run ./manage.py createsuperuser
-
Load initial data (optional)
uv run ./manage.py loaddata tosti/fixtures/default.json
-
Run the development server
uv run ./manage.py runserver
The application will be available at http://localhost:8000.
- SAML authentication is disabled in development mode
- Use
/admin-loginin production for local authentication - API documentation is available at
/api/docs
All third-party JS/CSS is vendored in-repo — no CDN dependencies at runtime. To bump versions:
# Vue (use the production build only — the dev build emits a runtime warning)
curl -sfL https://unpkg.com/vue@<X.Y.Z>/dist/vue.global.prod.js \
-o website/tosti/static/tosti/js/vue.global.prod.js
# qrcode.vue
curl -sfL https://unpkg.com/qrcode.vue@<X.Y.Z>/dist/qrcode.vue.browser.min.js \
-o website/tosti/static/tosti/js/qrcode.vue.browser.min.js
# Chart.js (used on the statistics page; the bundle references its sourcemap)
curl -sfL https://cdn.jsdelivr.net/npm/chart.js@<X.Y.Z>/dist/chart.umd.min.js \
-o website/tosti/static/tosti/js/chart.umd.min.js
curl -sfL https://cdn.jsdelivr.net/npm/chart.js@<X.Y.Z>/dist/chart.umd.min.js.map \
-o website/tosti/static/tosti/js/chart.umd.min.js.map
# FullCalendar 6+ — CSS is inlined into the JS, no separate stylesheet
curl -sfL https://cdn.jsdelivr.net/npm/fullcalendar@<X.Y.Z>/index.global.min.js \
-o website/venues/static/venues/js/fullcalendar.index.global.min.js
# Bootstrap (grab both minified and unminified + source maps)
BS=<X.Y.Z>
for f in js/bootstrap.bundle.js js/bootstrap.bundle.js.map \
js/bootstrap.bundle.min.js js/bootstrap.bundle.min.js.map \
css/bootstrap.css css/bootstrap.css.map \
css/bootstrap.min.css css/bootstrap.min.css.map; do
curl -sfL "https://cdn.jsdelivr.net/npm/bootstrap@$BS/dist/$f" \
-o "website/tosti/static/tosti/$f"
done
# Swagger UI (used on /api/docs)
SW=<X.Y.Z>
for f in swagger-ui-bundle.js swagger-ui-bundle.js.map \
swagger-ui-standalone-preset.js swagger-ui-standalone-preset.js.map; do
curl -sfL "https://cdn.jsdelivr.net/npm/swagger-ui-dist@$SW/$f" \
-o "website/tosti/static/tosti/js/$f"
done
for f in swagger-ui.css swagger-ui.css.map; do
curl -sfL "https://cdn.jsdelivr.net/npm/swagger-ui-dist@$SW/$f" \
-o "website/tosti/static/tosti/css/$f"
doneThe Neucha font is also self-hosted under website/tosti/static/tosti/fonts/.
Verify Vue: head -2 website/tosti/static/tosti/js/vue.global.prod.js should print the expected version, and the file should be a single-line minified bundle (not ~16 000 lines of source — that would be the dev build in disguise).
TOSTI runs in production as a Docker Compose stack on a VM. Deployments are automated: every push to master that passes CI (test + lint + image build) is deployed by .github/workflows/deploy.yaml.
Deployment configuration — docker-compose.yml, Caddyfile, .env.example — lives in deploy/. See deploy/README.md for VM prerequisites, required GitHub secrets, and rollback procedure.
To run the stack manually (e.g. on a fresh VM before CI is wired up):
cd deploy
cp .env.example .env # fill in POSTGRES_PASSWORD, DJANGO_SECRET_KEY, YIVI_TOKEN, SENTRY_DSN
docker compose up -dSpecific configuration is managed through Django Constance for runtime settings:
- General: Footer text, cleaning scheme URL
- Email: Notification recipients for reservations
- Shifts: Default maximum orders per shift
- Music (Thaliedje): Start/stop times, holiday mode
- Silvasoft: API credentials for bookkeeping
- Fridges: Daily opening requirements
TOSTI provides a RESTful API with OAuth2 authentication.
read: Read access to the APIwrite: Write access to the APIorders:order: Place ordersorders:manage: Manage all ordersthaliedje:request: Request songsthaliedje:manage: Control music playerstransactions:write: Create transactions
Interactive API documentation is available at /api/docs when running the application.
Run the test suite:
cd website
uv run python manage.py testRun with coverage:
uv run coverage run website/manage.py test website/
uv run coverage reportuv run black website
uv run flake8 website
uv run pydocstyle websiteThe project uses GitHub Actions for automated testing and linting on every push.
Contributions are welcome!
- Fork the repository
- Create a feature branch
- Make your changes
- Run tests and linting
- Submit a pull request
- Follow PEP 8
- Use Black for formatting
- Write docstrings for all functions
- Maximum line length: 119 characters
- Maintainers: Website committee of Tartarus
- Email: tartaruswebsite@science.ru.nl
- Security Issues: www-tosti@science.ru.nl
For security vulnerabilities, please email www-tosti@science.ru.nl instead of creating a public issue.
This project is licensed under the MIT License - see the LICENSE file for details.
- Original developers: Lars van Rhijn, Job Doesburg
- All contributors who have helped improve TOSTI
-
- CNCZ for hosting infrastructure