4.9 KiB
4.9 KiB
AGENTS.md - Guidelines for Agentic Coding
Project Overview
This is a Flask web application - a "Jeopardy-style" quiz game about the Russian short story "Уроки французского" by Valentin Rasputin.
Tech Stack:
- Backend: Python 3.13 with Flask
- Frontend: HTML, CSS, JavaScript (vanilla)
- Data Storage: JSON file (
data/questions.json) - State: Browser localStorage (client-side)
- Container: Docker
Build/Test Commands
Running Locally (without Docker)
# Activate virtual environment
source venv/bin/activate
# Run Flask app (default port 5000)
python src/app.py
# Run on specific port
python -c "from src.app import app; app.run(port=5002)"
Running with Docker
# Build image
./build.sh
# Run container
./run.sh
# Stop container
docker stop sigra && docker rm sigra
Note: Dockerfile copies only src/ directory into the container (app.py, data/, templates/, static/).
Manual Testing
This project does not have a formal test suite. For manual testing:
- Use
curlto test API endpoints - Test in browser at http://localhost:5000
Code Style Guidelines
Python (app.py)
Imports - Standard library first, then third-party:
import json
from flask import Flask, render_template, request, redirect, url_for, make_response
Formatting
- Use 4 spaces for indentation
- Maximum line length: 100 characters
- Blank lines: 2 between top-level definitions, 1 between function definitions
Naming Conventions
snake_casefor variables, functionsPascalCasefor classesUPPER_SNAKE_CASEfor constants
Error Handling
- Use try/except for file operations (JSON loading/saving)
- Return proper HTTP error codes (400, 404, 500)
- Log errors to console
Flask-Specific
- Use
app.secret_keyfor sessions - Always use
ensure_ascii=Falsewith JSON for Cyrillic support - Use
context_processorfor global template variables
JavaScript (templates/*.html)
General
- Use vanilla JavaScript (no frameworks)
- Prefer
varoverlet/constfor compatibility - Use
functionkeyword instead of arrow functions
Event Handling
- Use
onclickdirectly in HTML orelement.onclick = function() - Avoid
addEventListenerfor simplicity
DOM Manipulation
- Use
document.getElementByIdanddocument.querySelector - Template literals for dynamic content
- Use
JSON.parse()andJSON.stringify()for localStorage
Naming - camelCase for variables and functions
HTML/CSS (templates/*.html)
Template Syntax (Jinja2)
- Use
{% for %}loops withenumerate()for indexed iteration - Pass data via
{{ variable }}syntax - Use
|tojsonfilter for JavaScript data
CSS
- Use CSS custom properties (variables) for colors
- Follow BEM-like naming for classes
- Keep responsive design in mind
Structure
- Inline CSS in
<style>tags - Inline JS in
<script>tags at end of body
File Organization
/home/eof/dev/roma/sigra/
├── Dockerfile # Docker image definition
├── build.sh # Build script
├── run.sh # Run script
├── .dockerignore # Docker ignore
├── src/ # Application source (copied to container)
│ ├── app.py # Flask application
│ ├── data/
│ │ └── questions.json # Game questions
│ ├── templates/ # Jinja2 templates
│ └── static/ # Static assets
├── helm/ # Kubernetes Helm chart
├── venv/ # Virtual environment
├── SPEC.md # Project specification
├── AGENTS.md # This file
└── .gitignore # Git ignore rules
Common Patterns
Adding a New Question
- Edit
data/questions.jsonmanually or via admin panel at/admin - Structure:
{ "cost": 600, "question": "Question text?", "options": ["Option 1", "Option 2", "Option 3", "Option 4"], "answer": 0 }
Adding a New Route
- Add route in
app.pyusing@app.route() - Return
render_template()orjsonify()
Game State (localStorage)
- Key:
francuzskiy_game - Structure:
{ score: 0, answered: [], userAnswers: {}, teams: [] } answered: array of "cat_q" keys (e.g., ["0_0", "1_2"])userAnswers: object with keys and{team, answer}values
Multi-team Support
- Teams: 1-3 teams supported
- Questions: 30 (always, regardless of team count)
- Auto-switch to next team after answering
Security Notes
- Admin panel password: stored in
app.py(ADMIN_PASSWORD) - No database - data in JSON file
- No SQL injection risk
- XSS: user input in questions is trusted (admin-only)
Dependencies
Flask==3.1.3
Jinja2==3.1.6
Werkzeug==3.1.6
Git Conventions
- Do NOT commit without explicit user request
- Run lint/typecheck before committing if available
- Keep commits focused and descriptive