From 10a8ad7ceac419f4586e53d3f2d9149e9209263f Mon Sep 17 00:00:00 2001 From: Feiko Wielsma Date: Wed, 25 Mar 2026 10:14:31 +0100 Subject: [PATCH] Added readme for future me --- README.md | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..ff570a6 --- /dev/null +++ b/README.md @@ -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)