Skip to main content

A CLI tool to generate full-stack web projects from SQLModel

Project description

OneSite

OneSite is a model-driven CLI tool that generates full-stack web applications (FastAPI + React/Vite) from SQLModel definitions.

pip install onesite

Quick Start

# Create a new project
site create myproject
cd myproject

# Define your SQLModel classes in models/
# Then sync to generate backend and frontend code
site sync --install

# Run both servers
site run
  • Backend: http://localhost:8000 (Docs: http://localhost:8000/docs)
  • Frontend: http://localhost:5173
  • Default admin: admin@example.com / admin

Defining Models

Basic Model

from typing import Optional
from sqlmodel import Field, SQLModel

class Product(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    price: float
    is_active: bool = True

Foreign Key

class Post(SQLModel, table=True):
    id: Optional[int] = Field(default=None, primary_key=True)
    title: str
    content: str
    user_id: Optional[int] = Field(default=None, foreign_key="user.id")

FK fields auto-detect their target table. List pages display the related record's label (first unique + is_search_field field) instead of raw IDs.

Many-to-Many

class PostTagLink(SQLModel, table=True):
    __onesite__ = {"is_link_table": True}
    post_id: Optional[int] = Field(default=None, foreign_key="post.id", primary_key=True)
    tag_id: Optional[int] = Field(default=None, foreign_key="tag.id", primary_key=True)

M2M link tables generate multi-select components on the source model's form. If a link table has extra non-FK fields, it generates standalone CRUD pages for editing them.

User-Owned Resources (owner_field)

Mark a model as user-owned so non-admin users can only see/edit their own records:

class Item(SQLModel, table=True):
    __onesite__ = {
        "owner_field": "owner_id",
    }
    id: Optional[int] = Field(default=None, primary_key=True)
    name: str
    owner_id: Optional[int] = Field(default=None, foreign_key="user.id")
  • Users only see their own items (list filtered by owner_id = current_user.id)
  • Admins/developers see all items
  • Create forces owner_id = current_user.id for non-admin users
  • Detail/update/delete return 404 if the item doesn't belong to the current user
  • Frontend shows "My Items" in the menu and page title for user role

Permission System

Three-layer permission system: model-level CRUD, field-level CRU, and frontend visibility.

Permission chars: c = create, r = read, u = update, d = delete.

Permission Formats

Both model-level and field-level permissions accept two formats:

  • Dict format — specify per-role permissions individually
  • String format — shorthand that applies the same permission chars to all roles
# Dict format (per-role)
"permissions": {"user": "ru", "admin": "rcud", "developer": "rcud"}

# String format (applies to all roles, equivalent to above)
"permissions": "rcud"

"r" is equivalent to {"user": "r", "admin": "r", "developer": "r"}. Use string format when all roles have the same permission level, dict format when you need per-role differentiation.

Layer 1 — Model-level CRUD

class Product(SQLModel, table=True):
    __onesite__ = {
        # Dict format — per-role
        "permissions": {
            "user": "ru",       # read + update
            "admin": "rcud",    # full access
            "developer": "rcud",
        },
        # String format — all roles get same perms (equivalent)
        # "permissions": "rcud",
        "visible": ["admin", "developer"],  # menu visibility
    }

Role hierarchy: developer >= admin >= user. Missing roles default to "" (no access). If unset, all roles get "crud".

Layer 2 — Field-level CRU

Controls field inclusion in schemas and forms. d is model-level only, automatically stripped at field level.

email: str = Field(sa_column_kwargs={"info": {"site_props": {
    # Dict format — per-role
    "permissions": {
        "user": "r",
        "admin": "rcu",
        "developer": "rcu",
    }
    # String format — all roles get same perms (equivalent)
    # "permissions": "rcu",
}}})

Special field defaults: id = read-only, created_at = read-only, updated_at = read+update.

Key Features

  • Code generation: Backend (FastAPI, SQLModel, Pydantic) + Frontend (React, Tailwind, Zustand)
  • CRUD with validation: Auto-generated endpoints and forms with unique constraint checks
  • Search & filters: Mark fields with is_search_field to generate filter panels
  • Smart FK display: Shows related record labels instead of raw IDs
  • File & image upload: Auto-detected by field name conventions (_image, _file, avatar, etc.)
  • JSON fields: Support for Dict, List, and Pydantic models as JSON columns with structured editors
  • CSV import/export: Configure importable/exportable on any model
  • Notifications: Optional notification center with WebSocket real-time push
  • Dashboard: Auto-generated stats cards and charts (bar, line, pie)
  • Scheduled tasks: Cron and interval tasks via APScheduler, manageable from the UI
  • Internationalization: EN/ZH locale files generated from model translations
  • Themes: Built-in styles (normal, industrial, anime, cute)
  • Containerization: Docker/Podman build and Compose support
  • Authentication: JWT-based login, role-based access control
  • Singleton models: Config-style models (e.g., SystemConfig) with singleton endpoints
  • Custom actions: One-click buttons with conditional logic and field updates
  • Auto refresh: Real-time data monitoring with configurable intervals

Site Configuration

Customize via site_config.json in the project root:

{
    "project_name": "My Project",
    "style": "anime",
    "radius": 1.0,
    "database_url": "sqlite:///./app.db",
    "nav_order": ["user", "product", "tag"]
}

Styles: normal, industrial, anime, cute — full color systems, typography, and shadows.

Project Structure

myproject/
├── site_config.json    # Project configuration
├── models/             # SQLModel definitions (source of truth)
├── backend/
│   ├── app/
│   │   ├── api/endpoints/  # Generated REST endpoints
│   │   ├── schemas/        # Pydantic schemas
│   │   ├── services/       # Business logic
│   │   ├── cruds/          # CRUD operations
│   │   ├── models/         # Synced SQLModel classes
│   │   ├── core/           # Config, security, database
│   │   └── initial_data.py # Admin user seeding
│   └── tests/
└── frontend/
    └── src/
        ├── pages/      # Generated list/detail pages
        ├── services/   # API clients
        ├── stores/     # Zustand state
        └── components/ # UI components

Commands

Command Description
site init Initialize config and base models in existing project
site create <name> Create new project scaffold
site sync [--install] Sync models and generate code
site run [backend|frontend|all] Start development servers
site build [--engine] [--tag] [--port] Build Docker/Podman images
site compose up|down|logs -f Run docker-compose commands

Requirements

  • Python 3.10+
  • Node.js & npm (for frontend)
  • Docker or Podman (optional, for containerization)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

onesite-0.1.15.tar.gz (99.7 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

onesite-0.1.15-py3-none-any.whl (272.7 kB view details)

Uploaded Python 3

File details

Details for the file onesite-0.1.15.tar.gz.

File metadata

  • Download URL: onesite-0.1.15.tar.gz
  • Upload date:
  • Size: 99.7 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for onesite-0.1.15.tar.gz
Algorithm Hash digest
SHA256 423094d1c79b718c3210855614be05e7abc3b5039b6fabcf6a41c400550b784f
MD5 dde1468b1650ef5b984a5da3ac60aec7
BLAKE2b-256 5f161b2b285d46e287e9db9842877206d533e1cbc6c5ba85a41a310ac8fff40b

See more details on using hashes here.

File details

Details for the file onesite-0.1.15-py3-none-any.whl.

File metadata

  • Download URL: onesite-0.1.15-py3-none-any.whl
  • Upload date:
  • Size: 272.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.2

File hashes

Hashes for onesite-0.1.15-py3-none-any.whl
Algorithm Hash digest
SHA256 d4ae439add33955c306795a2382d4faae894b5d35a78b0809449b9f3aefd99a8
MD5 f5332cb8f5c56299156b6b10bf33f4fb
BLAKE2b-256 845e348a8b6c9a9abbefea082a92e20e8b10483fc5d4a98d900d1aceffa6f007

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page