Hackbeanpot Project
This backend powers the AI-driven carnival layout generator. It receives form data, asks the Gemini API to propose layouts, and returns structured layout data for the frontend to render.
- The user fills out a form (event info + attractions).
- The backend turns that into a clean request for the AI.
- The AI responds with 2-3 layout options.
- The backend returns those options to the frontend.
No drag-and-drop, no manual placement. Just input -> AI -> map.
- Client sends a request to the layout endpoint.
- The request is validated by Pydantic models.
- The layout planner builds constraints and a prompt.
- The Gemini client calls the API and gets a response.
- The backend returns layout options to the client.
The Carnival Layout Generator collects information about your event and attractions to create optimized layouts.
When the user submits a form, we collect the basic event details:
| Field | Type | Purpose | Example |
|---|---|---|---|
| Event Name | Text | Identifier for the carnival/fair | "Summer Fair 2026" |
| Daily Attendance | Number | Expected crowd size | 10,000 |
| Venue Width | Whole Number (feet) | Width for grid mapping | 500 feet |
| Venue Length | Whole Number (feet) | Length for grid mapping | 435 feet |
| Parking Lots | Whole Number | Number of parking lots | 2 |
| Entrance Type | Dropdown | Entrance, Exit, or Both | Entrance |
| Entrance Side | Cardinal Direction | Which side has the access point | North, South, East, or West |
| Entrance Position | Position | Where on that side | Corner, Center, or Edge |
| Entrance Corner | Corner | Corner designation when position is Corner | Northeast, Northwest, Southeast, Southwest |
For each attraction (ride, food stall, game booth, stage, seating, utility, etc.), we collect:
| Field | Type | Purpose | Example |
|---|---|---|---|
| Type | Dropdown | Category | Ride, Food, Games, Merchandise, Stage, Seating, Utilities |
| Building Type | Dropdown | Specific variant | Ferris Wheel, Food Truck, Game Booth, Bleachers, etc. |
| Popularity | Scale 1-5 | How popular (1=least, 5=most) | 4 = high popularity |
| Width | Whole Number (feet) | Physical width for grid mapping | 20 feet |
| Length | Whole Number (feet) | Physical length for grid mapping | 30 feet |
| Quantity | Number | How many of this | 5 (five 20Γ30 food trucks) |
| Target Age Group | Dropdown (optional) | Audience for this attraction | Kids, Families, Teens, Adults, Mixed (defaults to Mixed) |
You don't have to specify theseβwe calculate them from the venue dimensions:
- Restroom Facilities: 1 per acre (e.g., 5 acres = 5 restrooms)
- First Aid Stations: 1 per 2 acres (e.g., 5 acres = 3 stations)
- Security/Staff Stations: 1 per 1.5 acres (e.g., 5 acres = 4 stations)
- Utility Placement: Optimal locations for restrooms, first aid, and security
Endpoint: POST /api/v1/layouts/generate-maps
What it does: Takes your event and attraction data, uses AI to optimize placement, and returns 3 layout options.
Request body: Follows the schema shown above (event setup + attractions list)
Response:
{
"success": true,
"maps": [
{
"id": 1,
"name": "Classic Flow Layout",
"description": "Traditional carnival setup with entrance focus",
"layout_text": "πͺ ASCII map of the layout...",
"reasoning": "High-popularity attractions positioned near entrance..."
},
{
"id": 2,
"name": "Central Hub Layout",
"description": "Circular radial design with central gathering space",
"layout_text": "πͺ ASCII map of the layout...",
"reasoning": "Radial layout encourages natural exploration..."
},
{
"id": 3,
"name": "Linear Journey Path",
"description": "Guided path through themed zones",
"layout_text": "πͺ ASCII map of the layout...",
"reasoning": "Linear path guides visitors through distinct zones..."
}
],
"message": "Generated 3 carnival layouts for Summer Fair 2026 with 8 total attractions across 3 types"
}The system enforces smart limits to keep requests reasonable:
- β Event name: 1-255 characters
- β Daily attendance: > 0 (up to 1 million)
- β Venue width/length: > 0 feet (up to 100,000, whole numbers only for grid mapping)
- β Popularity: Must be 1-5
- β Dimensions: Must be > 0 feet, < 10,000 feet (whole numbers only for grid mapping)
- β Attraction types: Max 100 different types
- β Total units: Max 1,000 individual attractions across all types
- β At least 1 attraction required
Endpoint: GET /api/v1/layouts/status
What it does: Checks if the Gemini API is configured and reachable.
Response:
{
"gemini_configured": true,
"gemini_reachable": true,
"api_ready": true,
"message": "Service is operational"
}- Copy env template:
- Make a new file named
.envinbackend/. - Copy the contents of
.env.exampleinto it. - Add your Gemini API key.
- Make a new file named
- Install Python packages:
- Use
pip install -r backend/requirements.txt.
- Use
- Run the server:
- Use
uvicorn app.main:app --reloadfrom insidebackend/.
- Use
- Open the API docs in your browser:
http://localhost:8000/docs
- Install test tools:
- Use
pip install -r backend/requirements.txt.
- Use
- Run tests from the repo root:
- Use
pytest backend/tests.
- Use
- backend/: Python backend root
- backend/app/: FastAPI app code
- backend/app/api/: API routes (HTTP endpoints)
- backend/app/core/: settings and logging setup
- backend/app/schemas/: request/response models
- backend/app/services/: business logic and Gemini integration
- backend/app/utils/: constants and validation helpers
- backend/tests/: backend tests
- backend/app/main.py: FastAPI app entry point and router wiring
- backend/app/api/layouts.py: layout generation endpoints
- backend/app/schemas/layout.py: layout request/response models
- backend/app/services/gemini_client.py: Gemini API wrapper
- backend/app/services/layout_planner.py: prompt and constraint builder
- backend/app/services/exporter.py: export hooks (PNG/PDF)
- backend/.env.example: sample environment variables
- backend/requirements.txt: Python dependencies
- If Gemini is not hooked up yet, we can return stubbed layout data.
- The frontend can render layouts as SVG or canvas based on the response.
- This repo currently focuses only on layout generation, not ticketing or payments.
The backend requires these environment variables. Copy .env.example to .env and configure:
| Variable | Required | Default | Description |
|---|---|---|---|
GEMINI_API_KEY |
β Yes | - | Your Google Gemini API key. |
APP_NAME |
No | "Carnival Layout Generator" | Application display name |
DEBUG |
No | False |
Enable debug mode (more verbose logging) |
GEMINI_MODEL |
No | gemini-pro |
Which Gemini model to use for layout generation |
API_TIMEOUT |
No | 30 |
Timeout for Gemini API calls (seconds) |
MAX_RETRIES |
No | 3 |
Number of retry attempts for failed API calls |
Quick setup:
# 1. Install dependencies
cd backend
pip install -r requirements.txt
# 2. Copy the example file
cp .env.example .env
# 3. Edit .env and add your Gemini API key
# Get your key from: https://makersuite.google.com/app/apikey
# 4. Test your configuration
python test_config.py
# 5. Run the server
uvicorn app.main:app --reloadImportant: Never commit your .env file! It contains sensitive API keys.
- Go to Google AI Studio
- Click "Get API Key" or "Create API Key"
- Sign in with your Google account if prompted
- Click "Create API key in new project" (or select an existing project)
- Copy the generated API key (starts with
AIza...)
β οΈ Important: Keep your API key secret! Never commit it to Git.
- Navigate to the
backend/folder in your terminal:
cd backend- Copy the example environment file:
# On Mac/Linux
cp .env.example .env
# On Windows
copy .env.example .env- Open
.envin your text editor and add your key:
GEMINI_API_KEY=AIzaSyYourActualKeyHere123456789- Start the backend server:
cd backend
py -m uvicorn app.main:app --reload- Look for this message in the terminal:
π Validating Gemini API key...
β
Gemini API key is valid!
- If you see an error, double-check:
- Your
.envfile is in thebackend/folder - The key is copied correctly (no extra spaces)
- You have internet connection
- Your
"GEMINI_API_KEY not found"
- Make sure
.envfile exists inbackend/folder - Check that the variable name is exactly
GEMINI_API_KEY=
"Rate limit exceeded"
- Gemini has free tier limits (60 requests/minute)
- Wait a minute and try again
- Consider upgrading your plan for higher limits
"Invalid API key"
- Generate a new key at Google AI Studio
- Make sure you copied the entire key
- 60 requests per minute
- 1,500 requests per day
- Should be plenty for hackathon testing!
For more info: Gemini API Documentation
