TinyBase is a lightweight, self-hosted Backend-as-a-Service (BaaS) framework for Python developers.
It focuses on being:
- Easy to deploy (single binary-like package, Docker-ready).
- Easy to extend (Python-first, FastAPI-based).
- Lightweight (SQLite, minimal dependencies).
- Flexible โ with custom collections, typed functions, scheduling, built-in admin UI, and much more.
๐ Read the docs: https://maximiliancw.github.io/TinyBase/
- SQLite-backed data storage
- Dynamic collections with JSON schemas.
- Pydantic-based validation for records.
- Authentication
- User registration and login.
- Opaque token-based auth (Bearer tokens).
- Basic role support (
is_admin).
- Typed functions
- Define server-side functions with Pydantic input/output models.
- Use a strongly-typed
Contextobject (DB handle, user info, timestamps). - Exposed via
/api/functions/{name}with OpenAPI docs.
- Scheduling
- Once, interval, and cron schedules.
- All backed by a single JSON schedule config and Pydantic models.
- Execution metadata
FunctionCallrecords for each function call (status, duration, errors).
- Admin UI
- SPA built with Vue 3, Pinia, Vite, and PicoCSS.
- Manage collections, records, users, functions, schedules, and function calls.
- OpenAPI
- Full OpenAPI spec available at
/openapi.jsonfor client generation.
- Full OpenAPI spec available at
- Simple configuration
- Reasonable defaults.
- Configuration via
tinybase.tomland environment variables.
- uv-friendly
- Built for use with the
uvtool (Astral) for dependency and script management.
- Built for use with the
Install from PyPI:
pip install tinybaseor using uv:
uv add tinybaseFor development, use uv to manage Python dependencies and yarn for the admin UI in /app.
Initialize a new TinyBase instance in the current directory:
tinybase initThis will:
- Create a
tinybase.tomlconfig file (if missing). - Initialize the SQLite database.
- Optionally create an admin user.
- Create a
functions/package directory with example functions, if not present.
Start the server:
tinybase serveBy default, TinyBase listens on:
http://0.0.0.0:8000- OpenAPI docs at
http://0.0.0.0:8000/docs - Admin UI at
http://0.0.0.0:8000/admin(after building the SPA).
TinyBase reads configuration from:
- Environment variables.
tinybase.tomlin the current directory.- Internal defaults.
Typical configuration options:
[server]
host = "0.0.0.0"
port = 8000
debug = false
log_level = "info"
[database]
url = "sqlite:///./tinybase.db"
[auth]
token_ttl_hours = 24
[functions]
path = "./functions"
[scheduler]
enabled = true
interval_seconds = 5
token_cleanup_interval = 60
[cors]
allow_origins = ["*"]
[admin]
static_dir = "builtin" # or path to custom admin static files
[environments.production]
url = "https://tinybase.example.com"
api_token = "ADMIN_TOKEN"Corresponding environment variables (examples):
TINYBASE_SERVER_HOSTTINYBASE_SERVER_PORTTINYBASE_DB_URLTINYBASE_AUTH_TOKEN_TTL_HOURSTINYBASE_FUNCTIONS_PATHTINYBASE_SCHEDULER_ENABLEDTINYBASE_SCHEDULER_INTERVAL_SECONDSTINYBASE_SCHEDULER_TOKEN_CLEANUP_INTERVALTINYBASE_CORS_ALLOW_ORIGINSTINYBASE_ADMIN_STATIC_DIR
Admin bootstrap (used by tinybase init if present):
TINYBASE_ADMIN_EMAILTINYBASE_ADMIN_PASSWORD
Functions are regular Python callables registered with a decorator and (automatically) exposed as HTTP endpoints and schedulable tasks. Each function should live in its own file within the functions/ package directory generated by tinybase init.
Example (functions/add_numbers.py):
from pydantic import BaseModel
from tinybase.functions.register import register
from tinybase.functions import Context
class AddInput(BaseModel):
x: int
y: int
class AddOutput(BaseModel):
sum: int
@register(
name="add_numbers",
description="Add two numbers",
auth="auth", # "public" | "auth" | "admin"
input_model=AddInput,
output_model=AddOutput,
tags=["math"],
)
def add_numbers(ctx: Context, payload: AddInput) -> AddOutput:
return AddOutput(sum=payload.x + payload.y)This function is automatically exposed at:
POST /api/functions/add_numbers
Request body:
{
"x": 1,
"y": 2
}Response:
{
"call_id": "<uuid>",
"status": "succeeded",
"result": {
"sum": 3
}
}Function calls are also recorded as FunctionCall records for diagnostics (status, duration, errors).
Use the CLI to generate boilerplate for a new function:
tinybase functions new my_function -d "My example function"This appends a typed function template to your functions.py file.
TinyBase supports scheduling functions using three methods:
once(single run at a particular date/time).interval(every N seconds/minutes/hours/days).cron(cron expressions, viacroniter).
Schedules are defined as JSON objects stored in the schedule field of FunctionSchedule and validated with Pydantic.
Examples:
Once:
{
"method": "once",
"timezone": "Europe/Berlin",
"date": "2025-11-25",
"time": "08:00:00"
}Interval:
{
"method": "interval",
"timezone": "UTC",
"unit": "hours",
"value": 1
}Cron:
{
"method": "cron",
"timezone": "Europe/Berlin",
"cron": "0 8 * * *",
"description": "every day at 8am"
}Admin endpoints for schedules:
GET /api/admin/schedulesPOST /api/admin/schedulesGET /api/admin/schedules/{id}PATCH /api/admin/schedules/{id}DELETE /api/admin/schedules/{id}
Note: The scheduler runs as a background loop in TinyBase and triggers functions according to their schedule, creating
FunctionCallrecords for each invocation.
TinyBase collections are dynamic, schema-driven tables stored in SQLite.
- Collections are defined with a JSON schema describing their fields and constraints.
- Pydantic models are generated at startup to validate records.
- CRUD endpoints are provided for each collection.
Example schema (Collection.schema):
{
"fields": [
{
"name": "title",
"type": "string",
"required": true,
"max_length": 200
},
{
"name": "published",
"type": "boolean",
"required": false,
"default": false
}
]
}Associated endpoints:
GET /api/collectionsPOST /api/collections(admin)GET /api/collections/{collection_name}GET /api/collections/{collection_name}/recordsPOST /api/collections/{collection_name}/recordsGET /api/collections/{collection_name}/records/{id}PATCH /api/collections/{collection_name}/records/{id}DELETE /api/collections/{collection_name}/records/{id}
The admin UI is a single-page application built with:
- Vue 3
- Pinia
- Vite
- PicoCSS
Source:
- Located in the repository root under
/app.
Build:
cd app
yarn install
yarn buildThis produces a /app/dist directory, which should be copied into the Python package (e.g. tinybase/admin_static) during the build process.
At runtime, FastAPI serves the admin UI at:
GET /admin
The admin UI allows administrators to:
- Log in.
- Manage collections and schemas.
- Inspect and edit records.
- View and manage users.
- View and manage functions.
- Configure schedules.
- Inspect function call metadata.
For the Python backend:
# Install uv (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Create virtual environment and install dependencies
uv venv
source .venv/bin/activate # or `.venv\Scripts\activate` on Windows
uv pip install -e ".[dev]"For the admin UI:
cd app
yarn install
yarn dev # Start development server with hot reload# Initialize TinyBase
tinybase init --admin-email admin@example.com --admin-password yourpassword
# Start the server
tinybase serve --reloadThe included Dockerfile uses a multi-stage build that:
- Builds the Vue admin UI with yarn
- Creates a minimal Python runtime using uv
Build and run:
docker build -t tinybase .
docker run -p 8000:8000 tinybaseThe Docker image handles building the admin UI automatically.
Planned improvements may include:
- Optional JWT support.
- More advanced querying and filtering for records.
- Extended function tooling (e.g. dependency inspection utilities).
- Additional configuration presets for production deployments.
TinyBase is released under the MIT License.
Please refer to the LICENSE file for details.
