Skip to main content

Quick Start

This guide takes a new user from zero setup to custom UI in production.

Prerequisites

  • Python 3.12+ (python --version)
  • uv package manager (install)

The fastest way to get started is using a pre-configured cloud development environment. This handles all dependencies, database setup, and the studio environment for you.

Open in GitHub Codespaces Open in DevPod


Project Setup (from scratch)

mkdir my-project && cd my-project
uv init

# Core runtime
uv add framework-m

# Developer tooling
uv add --dev framework-m-studio

Optional Feature Groups

Framework M is highly modular. You can install optional groups to add specific capabilities without bloating the core installation:

  • [server]: High-performance ASGI server, fast JSON, and secure sessions. Required to run web servers.
  • [postgres]: PostgreSQL database driver and migration tools.
  • [redis]: Redis cache and pub/sub support.
  • [nats]: NATS JetStream support for distributed event bus.
  • [elastic]: Elasticsearch driver.
  • [metrics]: Prometheus client for metrics.
  • [oauth]: OAuth and OIDC providers for federated authentication.
  • [tracing]: OpenTelemetry SDK and auto-instrumentation for distributed tracing.
  • [aws]: Async Boto3 (aioboto3) for AWS services like S3 storage integration.

Because these features belong to the standard adapters, you install them by targeting the standard package directly:

uv add "framework-m-standard[server,postgres]"

1) Base App

Create your first app package:

uv run m new app crm
cd crm
uv sync

Create your first DocType:

uv run m new doctype Contact

Example Contact DocType (src/crm/doctypes/contact/doctype.py):

from __future__ import annotations

from typing import ClassVar

from framework_m import DocType, Field


class Contact(DocType):
__doctype_name__: ClassVar[str] = "Contact"

first_name: str = Field(description="First name")
last_name: str = Field(description="Last name")
email: str = Field(default="", description="Email address")

class Meta:
requires_auth: ClassVar[bool] = False # Allow access without login (dev)
apply_rls: ClassVar[bool] = False # All users can access all records (dev)
naming_rule: ClassVar[str] = "autoincrement"
api_resource: ClassVar[bool] = True
show_in_desk: ClassVar[bool] = True
permissions: ClassVar[dict[str, list[str]]] = {
"create": ["All"],
"read": ["All"],
"write": ["All"],
"delete": ["All"],
}

Note: if your project has not implemented authentication and a custom permission model yet, keep these Meta defaults so Desk create/read/update/delete works during development.

If you want to implement authentication and role-based access control (RBAC), refer to:

Install database dependencies (important):

Because Framework M is modular and supports database-free edge deployments, persistent storage dependencies are optional. To use a database, install the framework with your preferred engine's extra group:

# Development (SQLite requires aiosqlite)
uv add aiosqlite

# Production (PostgreSQL requires standard extras)
uv add "framework-m-standard[postgres]"

Set database URL in your app .env (important):

Create crm/.env (the same directory where you run uv run m ...):

# Development (SQLite)
DATABASE_URL=sqlite+aiosqlite:///./dev.db

# Production example (PostgreSQL)
# DATABASE_URL=postgresql+asyncpg://user:password@localhost:5432/crm

# Stateless / Database-Free Mode (Pure Message Passing, CLI, or Edge)
# DATABASE_URL=none

If DATABASE_URL is set to none (or completely omitted), Framework M boots in Stateless Mode. In this mode, the database engine is bypassed, migrations are skipped, and the framework runs entirely database-free—perfect for transient edge microservices, real-time calculators, or CLI applications.

Run migrations:

For rapid development, use sync to automatically update your database schema based on your DocType definitions:

uv run m migrate sync

Alternatively, use all to run both versioned patches and schema synchronization:

uv run m migrate all

Or follow the traditional Alembic workflow:

uv run m migrate init
uv run m migrate create "Add Contact doctype" --autogenerate
uv run m migrate run

2) Base Desk UI

Start with bundled Desk UI:

uv run m prod

Open http://127.0.0.1:8888/desk/.

Use this when you want ready UI with no custom frontend build.


3) Frontend

Initialize your frontend scaffold:

# Execute from crm root
uv run m new frontend

This creates ./frontend under your crm app and installs dependencies.

Build custom UI when ready:

cd ./frontend
pnpm build
# Switch back to crm root
cd ..

4) Extended UI Apps

Install additional app packages (example):

uv add business-m wms-app

Discovery model:

  • framework_m.apps entry points → backend DocTypes/routes
  • framework_m.frontend entry points → frontend plugin discovery in dev/build flows

5) Extended UI Plugins

Add local/custom plugin entries in your app frontend modules for composition.

Typical flow:

  • add plugin entry files
  • run uv run m dev for live composition
  • run frontend build for production artifacts

Reference docs:


6) m dev

Use this for day-to-day development:

uv run m dev

Current behavior:

  • Backend API server on 127.0.0.1:8888
  • Frontend Vite dev server on 127.0.0.1:5173
  • Hot reload for frontend + backend workflows

7) m prod

Use this for production-style runtime:

# Bundled Desk via backend
uv run m prod

# Custom UI deployment mode (prebuilt dist served by backend)
uv run m prod --with-frontend

Important for --with-frontend:

  • Backend serves prebuilt static from frontend/dist (via FRAMEWORK_M_FRONTEND_DIST)
  • m prod --with-frontend does not run frontend build

For high-scale production, nginx/CDN static serving is optional. Use this reusable nginx template:

It includes placeholders:

  • ${APP_NAME}
  • ${STATIC_ROOT}
  • ${BACKEND_UPSTREAM}

Quick API Check

curl http://127.0.0.1:8888/health
curl http://127.0.0.1:8888/api/meta/doctypes

Next Steps