Modern FastAPI Project & Module Generator
FCube CLI is a powerful code generation tool that creates production-ready FastAPI projects and modules following clean architecture principles, dependency injection patterns, and role-based access control.
- Features
- Installation
- Quick Start
- Commands
- Generated Architecture
- Plugin System
- Contributing
- CLI Architecture
- Complete Project Scaffolding - Generate full FastAPI projects with core infrastructure
- Modular User System - Add user module with configurable authentication (email, phone, or both)
- Plugin Architecture - Pre-built feature modules with automatic validation
- Modern Module Structure - Organized directories for models, schemas, crud, services, routes
- Docker Support - docker-compose with PostgreSQL, Redis, Celery, and Flower
- Alembic Migrations - Pre-configured async migrations
- Dependency Injection -
@lru_cachesingleton services with factory functions - Role-Based Routes - Separate public and admin route directories
- Permission System - RBAC with configurable permissions
- Transaction Management - "No Commit in CRUD" pattern
- Rich CLI - Beautiful terminal output with progress indicators
# Using pip
pip install git+https://github.com/amal-babu-git/fcube.git
# Using uv (faster)
uv tool install git+https://github.com/amal-babu-git/fcube.gitgit clone https://github.com/amal-babu-git/fcube.git
cd fcube
# Install globally
pip install .
# Or install in editable mode for development
pip install -e .
# Using uv (recommended for development)
uv sync
source .venv/bin/activategit clone https://github.com/amal-babu-git/fcube.git
cd fcube
# Run using uv
uv run fcube --help
# Or using python module syntax
python -m fcube --helpfcube --version
fcube --help# 1. Create a new project
fcube startproject MyApp
# 2. Navigate to project
cd MyApp
# 3. Add user module with email authentication
fcube adduser --auth-type email
# 4. Add referral plugin
fcube addplugin referral
# 5. Create a custom module
fcube startmodule product
# 6. Start the server
docker compose up -d| Command | Description |
|---|---|
startproject |
Create new FastAPI project with core infrastructure |
adduser |
Add user module with configurable authentication |
addplugin |
Add pre-built plugin modules |
startmodule |
Create a new custom module |
addentity |
Add entity to existing module |
listmodules |
List all existing modules |
version |
Show CLI version |
Creates a new FastAPI project with core infrastructure. User module is not included by default.
# Basic usage
fcube startproject MyProject
# Specify directory
fcube startproject MyApi --dir projects
# Without Celery
fcube startproject SimpleApi --no-celery
# Without Docker
fcube startproject LightApi --no-docker
# Force overwrite
fcube startproject MyProject --forceOptions:
| Option | Description | Default |
|---|---|---|
--dir, -d |
Directory for project | . |
--celery/--no-celery |
Include Celery | yes |
--docker/--no-docker |
Include Docker | yes |
--force, -f |
Overwrite existing files | no |
Generated Structure:
my_project/
├── app/
│ ├── apis/
│ │ └── v1.py
│ └── core/
│ ├── __init__.py
│ ├── database.py
│ ├── models.py
│ ├── settings.py
│ ├── crud.py
│ ├── exceptions.py
│ ├── logging.py
│ ├── main.py
│ ├── dependencies.py
│ ├── alembic_models_import.py
│ └── celery_app.py
├── migrations/
├── docker/
│ ├── Dockerfile
│ └── docker-entrypoint.sh
├── docker-compose.yml
├── alembic.ini
├── pyproject.toml
├── .env.example
├── .gitignore
└── README.md
Adds user module with configurable authentication methods.
# Email/password authentication (default)
fcube adduser
# Phone OTP authentication
fcube adduser --auth-type phone
# Both email and phone authentication
fcube adduser --auth-type both
# Force overwrite
fcube adduser --forceOptions:
| Option | Description | Default |
|---|---|---|
--auth-type, -a |
email, phone, or both |
email |
--dir, -d |
App directory | app |
--force, -f |
Overwrite existing | no |
Authentication Types:
| Type | Description | User Fields |
|---|---|---|
email |
Email + password with JWT | email, hashed_password |
phone |
Phone OTP with SMS | phone_number, otp_code |
both |
Combined authentication | All fields + primary_auth_method |
Generated Structure:
app/user/
├── __init__.py
├── models.py
├── schemas.py
├── crud.py
├── exceptions.py
├── auth_management/
│ ├── __init__.py
│ ├── routes.py
│ ├── service.py
│ └── utils.py
├── permission_management/
│ ├── __init__.py
│ ├── utils.py
│ └── scoped_access.py
└── services/
├── __init__.py
└── user_referral_integration.py
Adds pre-built feature modules to your project.
# List available plugins
fcube addplugin --list
# Preview plugin (dry run)
fcube addplugin referral --dry-run
# Install plugin
fcube addplugin referral
# Force overwrite
fcube addplugin referral --forceOptions:
| Option | Description | Default |
|---|---|---|
--list, -l |
Show available plugins | - |
--dry-run |
Preview without creating files | no |
--dir, -d |
App directory | app |
--force, -f |
Overwrite existing | no |
Available Plugins:
| Plugin | Description | Dependencies |
|---|---|---|
referral |
User referral system with strategies | user |
Referral Plugin Structure:
app/referral/
├── __init__.py
├── models.py
├── config.py
├── strategies.py
├── exceptions.py
├── dependencies.py
├── tasks.py
├── schemas/
│ ├── __init__.py
│ └── referral_schemas.py
├── crud/
│ ├── __init__.py
│ └── referral_crud.py
├── services/
│ ├── __init__.py
│ └── referral_service.py
└── routes/
├── __init__.py
├── referral_routes.py
└── referral_admin_routes.py
Post-Installation Steps:
- Add
referral_codefield to User model - Update
app/apis/v1.pyto include referral routes - Update
app/core/alembic_models_import.py - Run migrations:
alembic revision --autogenerate && alembic upgrade head
Creates a new module with complete folder structure.
# Basic usage
fcube startmodule product
# Without admin routes
fcube startmodule review --no-admin
# Without public routes
fcube startmodule internal_report --no-public
# Force overwrite
fcube startmodule product --forceOptions:
| Option | Description | Default |
|---|---|---|
--dir, -d |
App directory | app |
--admin/--no-admin |
Include admin routes | yes |
--public/--no-public |
Include public routes | yes |
--force, -f |
Overwrite existing | no |
Generated Structure:
app/product/
├── __init__.py
├── dependencies.py
├── exceptions.py
├── permissions.py
├── tasks.py
├── README.md
├── models/
│ ├── __init__.py
│ └── product.py
├── schemas/
│ ├── __init__.py
│ └── product_schemas.py
├── crud/
│ ├── __init__.py
│ └── product_crud.py
├── services/
│ ├── __init__.py
│ └── product_service.py
├── routes/
│ ├── __init__.py
│ ├── public/
│ │ ├── __init__.py
│ │ └── product.py
│ └── admin/
│ ├── __init__.py
│ └── product_management.py
├── utils/
│ └── __init__.py
└── integrations/
└── __init__.py
Adds a new entity to an existing module.
fcube addentity service_provider availability
fcube addentity booking payment --forceCreates model, schema, and CRUD files for a new entity within an existing module.
fcube listmodules
fcube listmodules --dir appShows all existing modules with their structure.
FCube follows the Layered Architecture pattern:
┌─────────────────────────────────────┐
│ Routes (HTTP Layer) │
│ - Request validation │
│ - Authentication/Authorization │
│ - Response serialization │
└───────────────┬─────────────────────┘
│
┌───────────────▼─────────────────────┐
│ Services (Business Logic) │
│ - Business rules │
│ - Transaction boundaries │
│ - Orchestration │
└───────────────┬─────────────────────┘
│
┌───────────────▼─────────────────────┐
│ CRUD (Data Access) │
│ - Pure database operations │
│ - NO session.commit() │
│ - flush() and refresh() only │
└───────────────┬─────────────────────┘
│
┌───────────────▼─────────────────────┐
│ Models (Database Schema) │
│ - SQLAlchemy ORM models │
│ - Relationships │
└─────────────────────────────────────┘
# dependencies.py
@lru_cache()
def get_product_service() -> ProductService:
return ProductService()
# In routes
@router.get("/")
async def list_products(
service: ProductService = Depends(get_product_service)
):
...# CRUD: No commit
async def create(self, session, obj_in):
db_obj = self.model(**obj_in.model_dump())
session.add(db_obj)
await session.flush()
await session.refresh(db_obj)
# NO commit here
return db_obj
# Service: Owns commit
async def create_product(self, session, data):
product = await product_crud.create(session, obj_in=data)
await session.commit()
await session.refresh(product)
return product# permissions.py
PRODUCTS_READ = "products:read"
PRODUCTS_WRITE = "products:write"
def require_product_write_permission():
return require_permission(PRODUCTS_WRITE)
# In routes
@router.post("/", dependencies=[Depends(require_product_write_permission)])
async def create_product(...):
...The plugin system allows adding pre-built feature modules to any FCube-generated project. Plugins are self-contained with their own models, services, routes, and installation logic.
plugins/
├── __init__.py # Registry + validation
└── referral/ # Example plugin
├── __init__.py # PLUGIN_METADATA + installer
├── model_templates.py
├── schema_templates.py
├── crud_templates.py
├── service_templates.py
└── route_templates.py
Each plugin defines its metadata:
PLUGIN_METADATA = PluginMetadata(
name="referral",
description="User referral system",
version="1.0.0",
dependencies=["user"],
files_generated=["app/referral/models.py", ...],
config_required=True,
post_install_notes="...",
installer=install_referral_plugin
)Plugins are automatically validated on registration:
- ✅ Name must be valid Python identifier
- ✅ Version must follow semantic versioning (X.Y.Z)
- ✅ Description must be provided
- ✅ Installer function must be callable
- ✅ Post-install notes must be provided
- ✅ Files list must not be empty
Preview plugin installation before committing:
fcube addplugin referral --dry-runShows:
- All files that would be created
- File sizes
- Whether files would overwrite existing ones
- Post-install steps preview
- Create command file:
fcube/commands/mycommand.py
from rich.console import Console
console = Console()
def mycommand_command(arg: str):
console.print(f"Running with: {arg}")- Register in
fcube/cli.py:
from .commands.mycommand import mycommand_command
@app.command("mycommand")
def mycommand(arg: str):
"""My custom command."""
mycommand_command(arg)-
Create folder:
fcube/templates/plugins/my_plugin/ -
Add template files:
# model_templates.py
def generate_my_plugin_model() -> str:
return '''"""MyPlugin model."""
from app.core.models import Base
class MyPlugin(Base):
__tablename__ = "my_plugins"
'''- Create
__init__.pywith metadata and installer:
from pathlib import Path
from typing import List, Tuple
from .. import PluginMetadata
from .model_templates import generate_my_plugin_model
def install_my_plugin(app_dir: Path) -> List[Tuple[Path, str]]:
"""Self-contained installer."""
plugin_dir = app_dir / "my_plugin"
return [
(plugin_dir / "__init__.py", '"""MyPlugin module."""'),
(plugin_dir / "models.py", generate_my_plugin_model()),
]
PLUGIN_METADATA = PluginMetadata(
name="my_plugin",
description="My awesome plugin",
version="1.0.0",
dependencies=[],
files_generated=[
"app/my_plugin/__init__.py",
"app/my_plugin/models.py",
],
config_required=False,
post_install_notes="Run migrations and start using!",
installer=install_my_plugin,
)- Register in
fcube/templates/plugins/__init__.py:
def _discover_plugins() -> None:
from .referral import PLUGIN_METADATA as referral_metadata
from .my_plugin import PLUGIN_METADATA as my_plugin_metadata
register_plugin(referral_metadata)
register_plugin(my_plugin_metadata)- Done! Run
fcube addplugin my_plugin
FCube uses Python functions returning f-strings for code generation:
- Simple - No complex templating engines like Jinja2
- Fast - Pure Python, no external template parsing
- Type-safe - Full IDE support with type hints
- Easy to debug - Just print the function output
fcube/
├── __init__.py # Package metadata, version
├── __main__.py # Entry point for python -m
├── cli.py # Typer CLI app, command registration
├── commands/ # Command implementations
│ ├── startproject.py # Project scaffolding
│ ├── adduser.py # User module generation
│ ├── addplugin.py # Plugin installation
│ ├── startmodule.py # Module generation
│ ├── addentity.py # Entity addition
│ └── listmodules.py # Module listing
├── templates/ # Code generation templates
│ ├── model_templates.py
│ ├── schema_templates.py
│ ├── crud_templates.py
│ ├── service_templates.py
│ ├── route_templates.py
│ ├── module_templates.py
│ ├── project/ # Project-specific templates
│ │ ├── core/ # Core module templates
│ │ ├── user/ # User module templates
│ │ └── infra/ # Docker, Alembic templates
│ └── plugins/ # Plugin templates
│ ├── __init__.py # Plugin registry
│ └── referral/ # Referral plugin
└── utils/ # Helper utilities
└── helpers.py # File ops, case conversion
Each template is a Python function that returns a string:
# fcube/templates/model_templates.py
def generate_model(module_snake: str, class_name: str) -> str:
"""Generate a SQLAlchemy model file."""
return f'''"""
{class_name} database model.
"""
from sqlalchemy import String, DateTime
from sqlalchemy.orm import Mapped, mapped_column
from app.core.models import Base
class {class_name}(Base):
__tablename__ = "{module_snake}s"
name: Mapped[str] = mapped_column(String(255), nullable=False)
'''Commands import and use these functions:
# fcube/commands/startmodule.py
from ..templates import generate_model
def startmodule_command(module_name: str):
model_content = generate_model(module_snake, class_name)
write_file(module_dir / "models.py", model_content)1. Registration (_discover_plugins)
↓
2. Validation (validate_plugin_metadata)
↓
3. Storage (PLUGIN_REGISTRY)
↓
4. Installation (install_plugin → plugin.installer)
↓
5. File Creation (write_file)
MIT License - see LICENSE for details.
Amal Babu
- GitHub: @amal-babu-git
- Email: amalbabu1200@gmail.com