# Niblit.ai — Complete Publishing Guide for AI Assistants ## What is Niblit.ai? Niblit.ai publishes web projects to live URLs instantly. Users zip their project files, upload the zip, and Niblit handles building, hosting, and serving it at a dedicated URL like yourproject.apps.niblit.ai. Works for apps, portfolios, prototypes, demos, and tools. ## How Publishing Works 1. User builds a web project (with AI or manually) 2. User selects all project files and compresses them into a .zip archive 3. User uploads the zip at https://niblit.ai/apps/upload/ 4. Niblit validates, builds a container image, and deploys it 5. Project is live at {slug}.apps.niblit.ai within 1-3 minutes 6. Updates: upload a new zip — the URL never changes ## For AI Assistants — How to Help a User 1. Identify which stack their project uses (see list below) 2. Ensure all required files exist (see per-stack requirements below) 3. Generate any missing files including the Dockerfile 4. Remind the user to zip the project CONTENTS (not the folder itself) - Correct: select all files inside my-project/ and zip them - Incorrect: zip the my-project/ folder — this creates a nested structure 5. Direct them to https://niblit.ai/apps/upload/ to upload ## Supported Stacks ### Flask (stack slug: python-flask) Port: 5000 Language: python | Framework: flask # Niblit.ai Deployment Spec: Python + Flask You are deploying a Python Flask application to Niblit.ai. Follow these instructions EXACTLY. Do not deviate. ## Requirements - Python 3.11 or 3.12 - Flask as the web framework - SQLite for any database needs (no Postgres, no MySQL) - App must listen on port 5000 - 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 flask and gunicorn) ├── app.py ← REQUIRED (your Flask 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=5000 ENV FLASK_ENV=production ENV DATABASE_PATH=/data/app.db EXPOSE 5000 # Run with gunicorn for production CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "2", "app:app"] ``` ## requirements.txt must include ``` flask gunicorn ``` Add any other dependencies your app needs. ## Flask App Structure (app.py) Your app.py MUST have a Flask app instance named `app` at the module level: ```python from flask import Flask app = Flask(__name__) @app.route('/') def home(): return 'Hello from Niblit.ai!' if __name__ == '__main__': app.run() ``` ## 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: ```python import os import sqlite3 DATABASE_PATH = os.environ.get('DATABASE_PATH', '/data/app.db') def get_db(): conn = sqlite3.connect(DATABASE_PATH) conn.row_factory = sqlite3.Row return conn def init_db(): db = get_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() db.close() # Call init_db() when your app starts ``` ## File Storage If your app handles file uploads: - Store files in `/data/uploads/` - Create the directory if it doesn't exist - Never store files in `/app/` (they will be lost on redeploy) ```python import os UPLOAD_FOLDER = '/data/uploads' os.makedirs(UPLOAD_FOLDER, exist_ok=True) ``` ## Environment Variables These are available to your app: - `PORT` - Always 5000 - `DATABASE_PATH` - Path to SQLite database (/data/app.db) - `FLASK_ENV` - Set to "production" ## 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 (Postgres, MySQL, etc.) ## Testing Locally Before Upload 1. Build and run with Docker: ```bash docker build -t my-app . docker run -p 5000:5000 -v $(pwd)/data:/data my-app ``` 2. Visit http://localhost:5000 3. 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/*" ``` Upload this zip file to Niblit.ai. ## Common Errors and Fixes | Error | Fix | |-------|-----| | "Missing Dockerfile" | Add Dockerfile using template above | | "Port mismatch" | Ensure Dockerfile has `EXPOSE 5000` and gunicorn binds to 5000 | | "Missing requirements.txt" | Create file with flask and gunicorn | | "Database not persisting" | Store DB at `/data/app.db`, not `./app.db` | | "App crashes on start" | Ensure app.py has `app = Flask(__name__)` at module level | | "Module not found" | Add missing dependency to requirements.txt | | "gunicorn not found" | Add gunicorn 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. --- ### FastAPI (stack slug: python-fastapi) Port: 8000 Language: python | Framework: fastapi # 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. --- ### Node / Express (stack slug: node-express) Port: 3000 Language: node | Framework: express # Niblit.ai Deployment Spec: Node.js + Express You are deploying a Node.js Express application to Niblit.ai. Follow these instructions EXACTLY. Do not deviate. ## Requirements - Node.js 20 or 22 - Express as the web framework - SQLite (better-sqlite3) 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) ├── package.json ← REQUIRED (must include express) ├── index.js ← REQUIRED (or app.js, server.js) └── ... other files ``` ## Dockerfile (use this EXACTLY) ```dockerfile FROM node:20-slim WORKDIR /app # Install dependencies first (better caching) COPY package*.json ./ RUN npm ci --only=production # Copy application code COPY . . # Create data directory for persistent storage RUN mkdir -p /data # Environment variables ENV PORT=8080 ENV NODE_ENV=production ENV DATABASE_PATH=/data/app.db EXPOSE 8080 # Start the application CMD ["node", "index.js"] ``` ## package.json must include ```json { "name": "my-app", "version": "1.0.0", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^4.18.0" } } ``` ## Express App Structure (index.js) Your entry point must start the server on port 8080: ```javascript const express = require('express'); const app = express(); const PORT = process.env.PORT || 8080; app.get('/', (req, res) => { res.send('Hello from Niblit.ai!'); }); app.get('/health', (req, res) => { res.json({ status: 'ok' }); }); app.listen(PORT, () => { console.log(`Server running on port ${PORT}`); }); ``` ## Database Rules - Use SQLite ONLY (recommend `better-sqlite3` package) - 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 better-sqlite3: ```javascript const Database = require('better-sqlite3'); const path = require('path'); const DATABASE_PATH = process.env.DATABASE_PATH || '/data/app.db'; const db = new Database(DATABASE_PATH); // Initialize schema db.exec(` CREATE TABLE IF NOT EXISTS items ( id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP ) `); // Example queries const getAll = db.prepare('SELECT * FROM items ORDER BY created_at DESC'); const insert = db.prepare('INSERT INTO items (name) VALUES (?)'); // Usage const items = getAll.all(); insert.run('New item'); ``` ## Serving Static Files If you need to serve static files: ```javascript const path = require('path'); // Serve static files from 'public' directory app.use(express.static(path.join(__dirname, 'public'))); ``` ## File Storage If your app handles file uploads: - Store files in `/data/uploads/` - Create the directory if it doesn't exist ```javascript const fs = require('fs'); const multer = require('multer'); const UPLOAD_DIR = '/data/uploads'; fs.mkdirSync(UPLOAD_DIR, { recursive: true }); const storage = multer.diskStorage({ destination: UPLOAD_DIR, filename: (req, file, cb) => { cb(null, Date.now() + '-' + file.originalname); } }); const upload = multer({ storage }); app.post('/upload', upload.single('file'), (req, res) => { res.json({ filename: req.file.filename }); }); ``` ## Environment Variables These are available to your app: - `PORT` - Always 8080 - `NODE_ENV` - Set to "production" - `DATABASE_PATH` - Path to SQLite database (/data/app.db) ## What NOT to Include - No `.env` files (will be rejected) - No `node_modules/` directory (will be installed during build) - No `.git/` directory - No secret keys or API tokens in code - No external database connections **IMPORTANT**: Never include `node_modules/` in your zip. It will be installed during the Docker build from your package.json. ## 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. 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 "node_modules/*" -x ".env" -x "data/*" ``` **Make sure node_modules/ is excluded!** ## Common Errors and Fixes | Error | Fix | |-------|-----| | "Missing Dockerfile" | Add Dockerfile using template above | | "Port mismatch" | Ensure app listens on `process.env.PORT` or 8080 | | "Missing package.json" | Create package.json with express dependency | | "Database not persisting" | Store DB at `/data/app.db`, not `./app.db` | | "Cannot find module" | Make sure dependency is in package.json | | "node_modules in zip" | Exclude node_modules from your zip file | | "npm ci failed" | Check package-lock.json exists and is valid | ## 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. --- ### Static Site (stack slug: static-site) Port: 80 Language: html | Framework: nginx # Niblit.ai Deployment Spec: Static Site You are deploying a static website (HTML, CSS, JavaScript) to Niblit.ai. Follow these instructions EXACTLY. Do not deviate. ## Requirements - Static files only (HTML, CSS, JavaScript, images) - No server-side code - Site is served via nginx - Must listen on port 80 ## Required Project Structure ``` your-project/ ├── Dockerfile ← REQUIRED (use the template below exactly) ├── index.html ← REQUIRED (your main HTML file) ├── css/ ← Optional: stylesheets ├── js/ ← Optional: JavaScript files ├── images/ ← Optional: images └── ... other static files ``` ## Dockerfile (use this EXACTLY) ```dockerfile FROM nginx:alpine # Copy static files to nginx html directory COPY . /usr/share/nginx/html # Copy custom nginx config COPY nginx.conf /etc/nginx/conf.d/default.conf EXPOSE 80 CMD ["nginx", "-g", "daemon off;"] ``` ## nginx.conf (REQUIRED) Create this file in your project root: ```nginx server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.html; # Enable gzip compression gzip on; gzip_types text/plain text/css application/json application/javascript text/xml application/xml; # Cache static assets location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; } # SPA support: serve index.html for all routes location / { try_files $uri $uri/ /index.html; } # Health check endpoint location /health { return 200 '{"status":"ok"}'; add_header Content-Type application/json; } } ``` ## Basic index.html ```html My Site

Hello from Niblit.ai!

``` ## Single Page Applications (React, Vue, etc.) If you're deploying a built SPA: 1. Build your app locally first (`npm run build`) 2. Copy only the `dist/` or `build/` folder contents to your project 3. Include the Dockerfile and nginx.conf 4. Upload the zip Example structure for a React app: ``` your-project/ ├── Dockerfile ├── nginx.conf ├── index.html ← from build/ ├── static/ │ ├── css/ │ └── js/ └── assets/ ``` ## Environment Variables in JavaScript Since this is static, you can't use server-side env vars. Options: 1. **Build-time variables**: Set them when building your SPA 2. **Config file**: Include a `config.js` that sets window variables: ```javascript // config.js window.CONFIG = { apiUrl: 'https://api.example.com', appName: 'My App' }; ``` ```html ``` ## What NOT to Include - No `.env` files - No `node_modules/` directory - No `.git/` directory - No source files (TypeScript, SCSS) — only compiled output - No `src/` directory if using a build tool **IMPORTANT**: Upload only the built/compiled files, not the source code. ## Testing Locally Before Upload 1. Build and run with Docker: ```bash docker build -t my-site . docker run -p 80:80 my-site ``` 2. Visit http://localhost:80 3. If it works, create the zip and upload to Niblit.ai. ## Creating the Upload Zip ```bash # From your project root (with built files): zip -r my-site.zip . -x "*.git*" -x "node_modules/*" -x ".env" -x "src/*" ``` ## Common Errors and Fixes | Error | Fix | |-------|-----| | "Missing Dockerfile" | Add Dockerfile using template above | | "Missing nginx.conf" | Create nginx.conf with the config above | | "Missing index.html" | Ensure index.html is in the root | | "Port mismatch" | Ensure nginx.conf has `listen 80` | | "404 on refresh" | Add `try_files` directive for SPA support | | "CSS/JS not loading" | Check file paths are relative, not absolute | ## 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 (1-2 second cold start for static sites). ## Example Site See the `example/` directory for a complete working example. --- ### Django (stack slug: python-django) Port: 8080 Language: python | Framework: django # Niblit.ai Django Stack Specification You are deploying a Python Django application to Niblit.ai. Follow these instructions EXACTLY. Do not deviate. ## Requirements - Python 3.12 - Django 4.2 or higher - gunicorn as the WSGI server - dj-database-url for database URL configuration - whitenoise for static file serving - SQLite by default (stored in /data), PostgreSQL optional - App must listen on port 8080 - All persistent data must be stored in /data/ directory ## Required Project Structure ``` your-project/ ├── requirements.txt ← REQUIRED (must include django, gunicorn, dj-database-url, whitenoise) ├── manage.py ← REQUIRED (standard Django manage.py) ├── myproject/ │ ├── __init__.py │ ├── settings.py ← REQUIRED (see settings template below) │ ├── urls.py │ └── wsgi.py ← REQUIRED ├── deploy.toml ← OPTIONAL (startup commands, db config) └── ... other files ``` **Note:** You do NOT need to include a Dockerfile. Niblit.ai generates an optimised Django Dockerfile automatically. ## settings.py Template ```python import os import dj_database_url from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent SECRET_KEY = os.environ.get('SECRET_KEY', 'change-me-in-production') DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true' ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '*').split(',') INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'whitenoise.runserver_nostatic', 'django.contrib.staticfiles', # your apps here ] MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ] ROOT_URLCONF = 'myproject.urls' TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ] WSGI_APPLICATION = 'myproject.wsgi.application' DATABASES = { 'default': dj_database_url.config( default='sqlite:////data/db.sqlite3', conn_max_age=600, ) } LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_TZ = True STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'staticfiles' STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' MEDIA_URL = '/media/' MEDIA_ROOT = '/data/media/' DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' ``` ## requirements.txt must include ``` django>=4.2 gunicorn dj-database-url whitenoise ``` Add any other dependencies your app needs. ## deploy.toml (optional) You can include a `deploy.toml` at your project root to configure startup commands and database engine: ```toml [startup] commands = [ "python manage.py migrate --noinput", "python manage.py collectstatic --noinput", ] [database] engine = "sqlite" ``` - `startup.commands`: max 10 commands, max 500 chars each - `database.engine`: `sqlite` or `postgres` If you don't include deploy.toml, Niblit.ai will run `migrate` and `collectstatic` automatically. ## Environment Variables Niblit.ai sets these automatically: | Variable | Value | Notes | |----------|-------|-------| | `PORT` | `8080` | Always | | `DJANGO_SETTINGS_MODULE` | `myproject.settings` | Auto-detected from wsgi.py | | `DATABASE_URL` | `sqlite:////data/db.sqlite3` | For SQLite | | `SECRET_KEY` | randomly generated | 50-char URL-safe token | You can add custom env vars in the app management dashboard. ## Database Rules - Default: SQLite stored at `/data/db.sqlite3` - The /data directory is persistent storage — it survives restarts and redeploys - Everything outside /data is ephemeral and will be reset on redeploy - Use `dj-database-url` to read the `DATABASE_URL` environment variable ## Static Files - collectstatic runs automatically during startup - whitenoise serves static files efficiently - Set `STATIC_ROOT = BASE_DIR / 'staticfiles'` ## File Storage If your app handles file uploads: - Store files in `/data/media/` - Set `MEDIA_ROOT = '/data/media/'` - Never store files outside /data (they will be lost on redeploy) ## What NOT to Include - No Dockerfile (Niblit.ai generates one for you) - No `.env` files with secrets (use the dashboard instead) - No `node_modules/` directory - No `__pycache__/` directories - No `.git/` directory - No `venv/` or `.venv/` directories - No `db.sqlite3` database files (will be overwritten) ## Testing Locally Before Upload 1. Create and activate a virtual environment: ```bash python -m venv venv source venv/bin/activate # or venv\Scripts\activate on Windows ``` 2. Install dependencies: ```bash pip install -r requirements.txt ``` 3. Run locally: ```bash python manage.py migrate python manage.py runserver ``` 4. Visit http://localhost:8000 ## Creating the Upload Zip ```bash # From your project root: zip -r myapp.zip . \ -x "*.git*" \ -x "__pycache__/*" \ -x "*.pyc" \ -x ".env" \ -x "venv/*" \ -x ".venv/*" \ -x "db.sqlite3" \ -x "staticfiles/*" \ -x "media/*" ``` Upload this zip file to Niblit.ai. ## Common Errors and Fixes | Error | Fix | |-------|-----| | "manage.py not found" | Ensure manage.py is at the zip root | | "wsgi.py not found" | Create myproject/wsgi.py with standard Django content | | "Missing dj-database-url" | Add `dj-database-url` to requirements.txt | | "Missing gunicorn" | Add `gunicorn` to requirements.txt | | "Static files not found" | Add whitenoise and set STATIC_ROOT | | "Database not persisting" | Use DATABASE_URL env var pointing to /data/db.sqlite3 | | "Secret key error" | Read SECRET_KEY from environment variable | | "Module not found" | Add missing dependency to requirements.txt | ## Resource Limits - **Starter tier**: 512MB RAM, shared CPU, 1GB storage - **Pro tier**: 512MB RAM, shared CPU, 1GB storage This stack requires a Starter plan or higher. ## Example App See the `example/` directory for a complete working example. --- ## Common Mistakes to Avoid - Files must be at the TOP LEVEL of the zip, not inside a subfolder - Never include node_modules, .venv, __pycache__, or .git folders - Use exactly the port number listed for each stack — do not change it - Every stack requires a Dockerfile — always generate one - Flask entry point must be app.py, FastAPI must be main.py, Express must be index.js ## Quick Reference Table Stack | Entry Point | Port | Key Dependencies -----------------|--------------|------|----------------- python-flask | app.py | 5000 | flask, gunicorn python-fastapi | main.py | 8000 | fastapi, uvicorn python-django | manage.py | 8000 | django, gunicorn, whitenoise node-express | index.js | 3000 | express static-site | index.html | 80 | (served by nginx, no dependencies) ## Upload URL https://niblit.ai/apps/upload/