A CLI tool to generate full-stack web projects from SQLModel
Project description
OneSite
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:
- Model CRUD controls endpoint and button access:
c,r,u,d. - Field CRU controls a field's presence in create, read and update schemas/forms:
c,r,u. visiblecontrols 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
53d5d9649703bc1f49cb4d80d7f3733ebedc2432eb30c6e9bc15311c57b3129d
|
|
| MD5 |
aca4d47cf94dbe2b2e03b284539ac5c9
|
|
| BLAKE2b-256 |
f4bdfb9f88125559d09eaabd28c14f7a2b92c47960193782696a5435a7e6fb0d
|
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3c1a5fa7f421f3655702ef3b56a186c4706ee280753d5a4e532e16f8d7d5992e
|
|
| MD5 |
80b7912c2e69ab2df3763824da465b30
|
|
| BLAKE2b-256 |
27c12d9715e5e5c665cbcd8d12a40245491be5cafc25e14f7dd28f3c6281e469
|