← All Stacks

FastAPI

Raw Text

✨ How to use: Copy this entire spec and paste it into your AI assistant (Claude, ChatGPT, etc.) when asking it to prepare your project for Niblit.ai deployment.

# Niblit.ai Deployment Spec: Python + FastAPI

You are deploying a Python FastAPI application to Niblit.ai.
Follow these instructions EXACTLY. Do not deviate.

## Requirements

- Python 3.11 or 3.12
- FastAPI as the web framework
- Uvicorn as the ASGI server
- SQLite for any database needs (no Postgres, no MySQL)
- App must listen on port 8080
- All persistent data must be stored in /data/ directory

## Required Project Structure

```
your-project/
├── Dockerfile ← REQUIRED (use the template below exactly)
├── requirements.txt ← REQUIRED (must include fastapi and uvicorn)
├── main.py ← REQUIRED (your FastAPI application entry point)
└── ... other files
```

## Dockerfile (use this EXACTLY)

```dockerfile
FROM python:3.12-slim

WORKDIR /app

# Install dependencies first (better caching)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy application code
COPY . .

# Create data directory for persistent storage
RUN mkdir -p /data

# Environment variables
ENV PORT=8080
ENV DATABASE_PATH=/data/app.db

EXPOSE 8080

# Run with uvicorn for production
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
```

## requirements.txt must include

```
fastapi
uvicorn[standard]
```

Add any other dependencies your app needs.

## FastAPI App Structure (main.py)

Your main.py MUST have a FastAPI app instance named `app` at the module level:

```python
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def home():
return {"message": "Hello from Niblit.ai!"}

@app.get("/health")
def health():
return {"status": "ok"}
```

## Database Rules

- Use SQLite ONLY
- Database file MUST be stored at: `/data/app.db`
- The /data directory is persistent storage — it survives restarts and redeploys
- Everything outside /data is ephemeral and will be reset on redeploy

Example database setup with SQLite:

```python
import os
import sqlite3
from contextlib import contextmanager

DATABASE_PATH = os.environ.get('DATABASE_PATH', '/data/app.db')

@contextmanager
def get_db():
conn = sqlite3.connect(DATABASE_PATH)
conn.row_factory = sqlite3.Row
try:
yield conn
finally:
conn.close()

def init_db():
with get_db() as db:
db.execute('''
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
''')
db.commit()

# Call init_db() on startup
@app.on_event("startup")
def startup():
init_db()
```

## Serving Static Files

If you need to serve static files (HTML, CSS, JS):

```python
from fastapi.staticfiles import StaticFiles
from fastapi.responses import HTMLResponse

# Mount static files directory
app.mount("/static", StaticFiles(directory="static"), name="static")

@app.get("/", response_class=HTMLResponse)
def home():
with open("static/index.html") as f:
return f.read()
```

## File Storage

If your app handles file uploads:
- Store files in `/data/uploads/`
- Create the directory if it doesn't exist

```python
import os
from fastapi import UploadFile

UPLOAD_FOLDER = '/data/uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

@app.post("/upload")
async def upload_file(file: UploadFile):
path = os.path.join(UPLOAD_FOLDER, file.filename)
with open(path, "wb") as f:
f.write(await file.read())
return {"filename": file.filename}
```

## Environment Variables

These are available to your app:
- `PORT` - Always 8080
- `DATABASE_PATH` - Path to SQLite database (/data/app.db)

## What NOT to Include

- No `.env` files (will be rejected)
- No `node_modules/` directory
- No `__pycache__/` directories
- No `.git/` directory
- No `venv/` or `.venv/` directories
- No secret keys or API tokens in code
- No external database connections

## Testing Locally Before Upload

1. Build and run with Docker:

```bash
docker build -t my-app .
docker run -p 8080:8080 -v $(pwd)/data:/data my-app
```

2. Visit http://localhost:8080

3. Check the API docs at http://localhost:8080/docs

4. If it works, create the zip and upload to Niblit.ai.

## Creating the Upload Zip

```bash
# From your project root:
zip -r my-app.zip . -x "*.git*" -x "__pycache__/*" -x "*.pyc" -x ".env" -x "venv/*" -x ".venv/*" -x "data/*"
```

## Common Errors and Fixes

| Error | Fix |
|-------|-----|
| "Missing Dockerfile" | Add Dockerfile using template above |
| "Port mismatch" | Ensure Dockerfile has `EXPOSE 8080` and uvicorn uses port 8080 |
| "Missing requirements.txt" | Create file with fastapi and uvicorn[standard] |
| "Database not persisting" | Store DB at `/data/app.db`, not `./app.db` |
| "App crashes on start" | Ensure main.py has `app = FastAPI()` at module level |
| "uvicorn not found" | Add `uvicorn[standard]` to requirements.txt |

## Resource Limits

- **Free tier**: 256MB RAM, shared CPU, 1GB storage
- **Pro tier**: 512MB RAM, shared CPU, 1GB storage
- **Team tier**: 1GB RAM, 2 shared CPUs, 5GB storage

Free tier apps sleep after 5 minutes of no traffic and wake automatically (3-5 second cold start).

## Example App

See the `example/` directory for a complete working example.