Skip to main content

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

Project description

OneSite

中文文档 · Training guide

OneSite is a model-driven CLI that generates an admin-style full-stack application from SQLModel definitions. models/ is the source of truth; site sync generates FastAPI schemas, CRUD, services and REST endpoints, plus React/Vite pages, API clients, navigation, translations and theme assets.

Requirements and installation

  • Python 3.10+
  • Node.js and npm for generated frontends
  • Docker or Podman only when building containers
pip install onesite
site --help

For development in this repository:

python -m pip install -e .

Quick start

site create inventory
cd inventory

# Add or edit SQLModel classes in models/.
site sync --install
site run

The frontend is available at http://localhost:5173; FastAPI documentation is at http://localhost:8000/docs. A new project seeds admin@example.com / admin; change this credential before deploying.

The normal edit/generate loop is:

edit models/*.py or site_config.json → site sync → test /docs and the frontend

Do not treat backend/app/models/ as the model source of truth: it is synced from models/. Schemas, endpoints, CRUD/services and generated frontend pages can be regenerated by site sync; keep durable business customizations in deliberate extension points, not solely in generated files.

CLI

Command Purpose
site init Initialize site_config.json, base models and icon reference in the current directory.
site create <project_name> Create a new full-stack project.
site sync Copy models and regenerate backend/frontend code.
site sync --install / -i Regenerate, then install backend and frontend dependencies.
site run Run backend and frontend.
site run --component backend Run only FastAPI.
site run --component frontend Run only Vite.
site run <project_path> --component all Run a project from another directory.
site build [-c backend|frontend|all] [-e docker|podman] [-t TAG] [-p PORT] Build images and generate docker-compose.yml.
site compose [--engine docker|podman] up -d Forward a Compose command to Docker Compose or Podman Compose.

component is an option: use site run --component backend, not site run backend.

Project configuration

site_config.json is created with sensible defaults. Common settings are:

{
  "project_name": "Inventory",
  "database_url": "sqlite:///./app.db",
  "upload_dir": "uploads",
  "secret_key": "replace-with-a-random-production-secret",
  "access_token_expire_minutes": 11520,
  "allowed_origins": ["http://localhost:5173", "http://localhost:3000"],
  "style": "normal",
  "radius": 1.0,
  "nav_order": ["user", "category", "product"]
}

Supported themes are normal, industrial, anime and cute. Use a production database URL and a strong, private secret_key outside local development.

Model basics

from typing import Optional
from sqlmodel import Field, SQLModel

class Product(SQLModel, table=True):
    __onesite__ = {
        "translations": {
            "zh": {
                "name": "商品",
                "fields": {"name": "名称", "price": "价格"},
            },
        },
    }

    id: Optional[int] = Field(default=None, primary_key=True)
    name: str = Field(
        unique=True,
        sa_column_kwargs={"info": {"site_props": {"is_search_field": True}}},
    )
    price: float = 0
    is_active: bool = True

Field types, requiredness, defaults, enums and unique constraints become API validation and form controls. Fields named like image, avatar, photo, *_image use the image uploader; file, attachment, *_file use the file uploader. Override detection with site_props.component: image, file, textarea or json.

Business primary keys

Integer IDs with default=None are database-generated and are not accepted by the create API by default. A business key can be passed on creation by making the id field required and explicitly granting it create permission:

class Device(SQLModel, table=True):
    id: str = Field(
        primary_key=True,
        nullable=False,
        sa_column_kwargs={"info": {"site_props": {"permissions": "rcu"}}},
    )
    name: str

OneSite generates id: str consistently in its create/read schemas, endpoint paths, CRUD/service functions and frontend client for this model. Primary keys are immutable through the normal update API.

Relations

Foreign keys are inferred from a {target}_id field with foreign_key="target.id":

category_id: Optional[int] = Field(default=None, foreign_key="category.id")

The generated UI selects and displays related labels. Make a useful target label field unique=True and/or is_search_field=True.

For many-to-many relations, mark the link table:

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

Link tables with only relation keys become multi-select fields; extra fields keep standalone CRUD support. Self-referencing FKs can generate a tree view.

__onesite__ model configuration

Place model-level options in __onesite__ (or table info.site_props). Key options include:

Option Effect
translations Model, field and enum labels for zh/en.
icon Lucide icon name for navigation.
permissions Model CRUD permissions by role.
visible Navigation visibility by role.
owner_field User-owned resource filtering, e.g. "owner_id".
is_link_table Marks a many-to-many link table.
is_singleton Creates a single configuration-like record UI/API.
frontend_only Excludes a model from backend persistence.
page_edit Use a full page rather than dialogs for create/edit.
actions Adds permission-controlled custom action buttons.
importable / exportable Enables CSV import/export flows.
import_key Field used for import upsert matching.
refresh_interval Enables periodic list refresh.
visualize Adds generated dashboard statistics/charts.
is_notification_table Enables notification-center behavior and realtime push.
time_series_table Configures TimescaleDB/time-series generation.

Useful field-level site_props are permissions, is_search_field, component, create_optional, update_optional, is_foreign_key, reverse_display, allow_download, group, fixed_keys and lock_keys.

Permissions and visibility

Permissions are independent at three layers:

  1. Model CRUD controls endpoint and button access: c, r, u, d.
  2. Field CRU controls a field's presence in create, read and update schemas/forms: c, r, u.
  3. visible controls whether the model appears in navigation.
class PremiumContent(SQLModel, table=True):
    __onesite__ = {
        "permissions": {"user": "", "admin": "crud", "developer": "crud"},
        "visible": ["admin", "developer"],
    }
    id: Optional[int] = Field(default=None, primary_key=True)
    title: str = Field(sa_column_kwargs={"info": {"site_props": {
        "permissions": {"user": "r", "admin": "cru", "developer": "cru"},
    }}})

Roles are user, admin, developer (in ascending hierarchy). A model permission not specified for a role is no access; an unset model permission defaults to full CRUD for all roles. Field permissions inherit the model permissions without d. The implicit defaults are id: hidden, created_at: read, updated_at: read/update; explicitly set field permissions override them.

owner_field adds server-side ownership protection: non-admin users only list, read, update and delete their own records, and creation assigns their own user ID.

Generated capabilities

  • JWT authentication and role-based access control
  • REST CRUD, unique-constraint validation, list search and filters
  • Image/file upload and download controls
  • JSON fields, including structured Pydantic-model editors and lockable keys
  • Foreign-key label display, M2M selectors, tree views and owner-scoped resources
  • Custom actions with role permissions and conditional field updates
  • CSV import/export with import-key upserts
  • Singleton/configuration models
  • Notification center and WebSocket real-time updates
  • Dashboard statistics/charts and configurable auto-refresh
  • Scheduled jobs via APScheduler with UI management
  • EN/ZH locale generation and four built-in themes
  • Docker/Podman images and generated Compose configuration
  • Optional time-series/TimescaleDB flows

Container deployment

After syncing a project, build and start it:

site build --engine docker --tag v1 --port 3000
site compose up -d
site compose logs -f

site build writes docker-compose.yml. PostgreSQL is included when database_url starts with postgresql; configure production credentials and API origins before exposing the application.

Generated project layout

project/
├── site_config.json
├── models/                   # SQLModel source of truth
├── backend/app/
│   ├── api/endpoints/         # generated REST routes
│   ├── schemas/ cruds/ services/
│   └── models/                # synced model copy
└── frontend/src/
    ├── pages/ services/ stores/
    └── components/

See the Chinese training guide and examples/ for end-to-end model examples, including permissions and IoT/time-series scenarios.

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.16.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.16-py3-none-any.whl (274.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: onesite-0.1.16.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.16.tar.gz
Algorithm Hash digest
SHA256 53d5d9649703bc1f49cb4d80d7f3733ebedc2432eb30c6e9bc15311c57b3129d
MD5 aca4d47cf94dbe2b2e03b284539ac5c9
BLAKE2b-256 f4bdfb9f88125559d09eaabd28c14f7a2b92c47960193782696a5435a7e6fb0d

See more details on using hashes here.

File details

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

File metadata

  • Download URL: onesite-0.1.16-py3-none-any.whl
  • Upload date:
  • Size: 274.0 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.16-py3-none-any.whl
Algorithm Hash digest
SHA256 3c1a5fa7f421f3655702ef3b56a186c4706ee280753d5a4e532e16f8d7d5992e
MD5 80b7912c2e69ab2df3763824da465b30
BLAKE2b-256 27c12d9715e5e5c665cbcd8d12a40245491be5cafc25e14f7dd28f3c6281e469

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