# 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.