Added readme for future me

This commit is contained in:
Feiko Wielsma 2026-03-25 10:14:31 +01:00
parent d8ceb50e9f
commit 10a8ad7cea

88
README.md Normal file
View file

@ -0,0 +1,88 @@
# Sailing Forms
A self-hosted Flask-based custom signup application for managing sailing event registrations. It provides dynamically generated registration forms based on a YAML configuration and automatically saves submitted data to Google Sheets.
## Features
- **Dynamic Event Forms**: Simply define new events in `events.yaml` without touching the code. Each event gets a clean URL based on its slug (e.g., `domain.com/zomeravond`).
- **Google Sheets Integration**: Automatically appends participant details to specific Google Sheet tabs in real-time.
- **Public Participant Lists**: Securely displays public-safe participant data (e.g., class, sail number, boat name) at the bottom of the registration page, while keeping sensitive info (email, phone) private.
- **CSRF Protection**: Form submissions are protected against Cross-Site Request Forgery.
- **Dockerized Base**: Includes a `Dockerfile` and `docker-compose.yaml` utilizing `gunicorn` for simple and reliable production deployments.
## Prerequisites
- **Python 3.9+** (if running locally)
- **Docker and Docker Compose** (if deploying via containers)
- **Google Service Account**: You need a `credentials.json` file authorized for the Google Sheets API.
## Setup & Configuration
### 1. Credentials
Place your Google Service Account credentials inside a file named `credentials.json` in the root of the project. This is required for the application to access the Google Sheets via the `gspread` library.
### 2. Environment Variables
Create a `.env` file in the root directory and add a secure, random string to be used as your Flask session secret key. This is required for CSRF protection and session management.
```env
SECRET_KEY=your_very_secret_random_string_here
```
### 3. Events Configuration (`events.yaml`)
Define your sailing events in `events.yaml`. You can set a global `master_sheet_id` or specific `sheet_id` for each event. The `tab_name` specifies which worksheet inside the Google Sheet the data should append to.
```yaml
master_sheet_id: "your_spreadsheet_id_here" # From the Google Sheets URL
events:
zomeravond: # The URL slug
title: "Zomeravondregatta 2026"
tab_name: "Zomeravond 2026" # Exact tab name in Google Sheets
description: "De gezelligste avondwedstrijd van het jaar."
```
## Running the Application
### Option A: Using Docker (Recommended for Production)
The easiest way to run the service is using Docker Compose. The `docker-compose.yaml` is configured to mount your configuration and credentials without rebuilding the container.
```bash
docker-compose up -d --build
```
The application will run on port `5000` (mapped to `localhost:5000`). Make sure your `credentials.json`, `.env` and `events.yaml` files are in the same directory as the `docker-compose.yaml` file so they are correctly mounted into the container as volumes.
### Option B: Local Development
If you're making changes to the codebase and need to run it directly:
1. Create a virtual environment and activate it:
```bash
python -m venv .venv
source .venv/bin/activate
```
2. Install the required dependencies:
```bash
pip install -r requirements.txt
```
3. Run the development server:
```bash
python app.py
```
## Automated Testing
The project uses `pytest` for unit and E2E testing (located in the `tests/` directory).
To run the tests locally:
```bash
pytest
```
*Note: The testing suite automatically bypasses the need for a real `SECRET_KEY` and passes `TESTING_NO_APPEND=1` to prevent test submissions from cluttering the live Google Sheets.*
## Tech Stack Overview
- **Backend Context:** Flask (Web Framework), Gunicorn (Production WSGI server)
- **Google Sheets Integration:** `gspread`
- **Data Configuration:** `PyYAML`
- **Frontend Context:** Rendered via standard Jinja2 `templates/` (HTML)