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.14.tar.gz (99.6 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.14-py3-none-any.whl (191.8 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: onesite-0.1.14.tar.gz
  • Upload date:
  • Size: 99.6 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.14.tar.gz
Algorithm Hash digest
SHA256 455c3e4911ac8435fb04267c27743a81918e78072bd1424ea42e57076929458a
MD5 936d8ebc8a2cc36ffd07bb4bcda5d51f
BLAKE2b-256 38fbc14d6c8330ed755959200caccdd6c2ab8eb9cb5b6b19820805b0a300c051

See more details on using hashes here.

File details

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

File metadata

  • Download URL: onesite-0.1.14-py3-none-any.whl
  • Upload date:
  • Size: 191.8 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.14-py3-none-any.whl
Algorithm Hash digest
SHA256 3e7a6b2b3eea0c949afc887113bc9b332369d60f8ec97f9b8ead8fcca2f6160d
MD5 8e845d9c9fb187fbe10cf3ed0ac4118f
BLAKE2b-256 807ad5aa8aa3f8f31aa475814cfe4056754dc28a46fbb8045e4dd79ab918d907

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