Skip to content

Latest commit

 

History

History
128 lines (88 loc) · 4.76 KB

File metadata and controls

128 lines (88 loc) · 4.76 KB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

This is rDrama, a Reddit-like discussion forum application built with Flask and SQLAlchemy. The application consists of a Python backend with a React-based chat component.

Tech Stack

  • Backend: Python, Flask, SQLAlchemy, Redis, PostgreSQL
  • Frontend: Jinja2 templates, vanilla JavaScript, React (chat component only)
  • Package Management: Poetry (Python), Yarn (JavaScript/chat)
  • Database: PostgreSQL with Alembic migrations

Common Development Commands

Python/Backend

# Install dependencies
poetry install

# Run tests
./util/test.py

# Run database migrations
python3 -m flask db upgrade

# Run flask commands
python3 -m flask [command]
# OR
./util/command_flask.py [command]

Architecture Overview

Application Entry Point

  • files/__main__.py - Main Flask application setup, configures services (THEMOTTE vs CHAT), database connections, Redis cache, rate limiting

Core Structure

  • files/routes/ - HTTP route handlers organized by feature area

    • allroutes.py - Request/response handlers shared across services
    • Major route modules: posts.py, comments.py, login.py, front.py, search.py
    • admin/ - Administrative functionality routes
  • files/classes/ - SQLAlchemy ORM models

    • Key models: User, Submission (posts), Comment
    • Warning: Uses wildcard imports internally - be careful with dependencies
  • files/helpers/ - Utility functions and configurations

    • config/ - Configuration constants and environment variables
  • files/templates/ - Jinja2 templates for server-side rendering

  • files/assets/ - Static assets (CSS, JS, images)

  • chat/ - Separate React application for real-time chat functionality

Database

  • Migrations in migrations/ directory managed by Alembic
  • PostgreSQL database with extensive use of SQLAlchemy ORM
  • Redis for caching and rate limiting

Service Modes

The application can run in different service modes (defined in files/helpers/config/const.py):

  • THEMOTTE - Main forum functionality
  • CHAT - Chat service only

Important Patterns

  1. Imports: Many files use wildcard imports (from files.classes import *). Be careful when modifying imports as it can break unrelated parts of the codebase.

  2. Database Sessions: Uses SQLAlchemy scoped sessions (db_session) configured in __main__.py

  3. Authentication: Session-based authentication with Redis backing

  4. Rate Limiting: Configured via Flask-Limiter with Redis storage

  5. Templates: Server-side rendering with Jinja2, client-side JavaScript for interactivity

Testing

Tests are located in files/tests/ and use pytest. Run all tests with:

./util/test.py

Key test fixtures are defined in files/tests/fixture_*.py files.

Important Testing Patterns

  1. SQLAlchemy Session Expiration: After making HTTP requests in tests, database objects become detached from the session. To verify database changes after an HTTP request, re-query the object using db_session.query(Model).get(id) or db_session.query(Model).filter_by(...).first() instead of using db_session.refresh(obj).

    # ❌ WRONG - object is detached after HTTP request
    response, _ = util.post_with_formkey(client, f"/delete/comment/{comment.id}", data={})
    db_session.refresh(comment)  # This will fail with InvalidRequestError
    
    # ✅ CORRECT - re-query the object
    response, _ = util.post_with_formkey(client, f"/delete/comment/{comment.id}", data={})
    comment_after = db_session.query(Comment).get(comment.id)
    assert comment_after.state_user_deleted_utc is not None
  2. CSRF Protection (formkey): All POST requests in the application require a CSRF token called formkey. In tests, use util.post_with_formkey() helper function instead of client.post() directly:

    # ❌ WRONG - missing formkey, will return 302 redirect
    response = client.post("/delete/comment/123", data={})
    
    # ✅ CORRECT - automatically fetches and includes formkey
    response, _ = util.post_with_formkey(client, "/delete/comment/123", data={})

    The post_with_formkey() helper automatically fetches a page (typically /submit) to extract the session's formkey, then includes it in the POST request data.

Development Environment

The application uses environment variables for configuration. These can be set in:

  • bootstrap/site_env - Site-specific configuration
  • .env - Local overrides (takes precedence)

Key environment variables include:

  • SITE_ID - Site identifier
  • DATABASE_URL - PostgreSQL connection string
  • CACHE_REDIS_URL - Redis connection string
  • SECRET_KEY - Flask secret key
  • ENFORCE_PRODUCTION - Set to false for development