Skip to main content

A production-ready FastAPI boilerplate framework for building multi-tenant SaaS applications

Project description

Apex SaaS Framework

Build production-ready SaaS applications in minutes, not months!

A modern FastAPI framework with LangChain-style simplicity for building multi-tenant SaaS applications. Get authentication, user management, organizations, roles, permissions, payments, and more with just 2 lines of code!

โšก Super Quick Start

from apex import Apex

app = Apex().app

# That's it! You now have a complete SaaS backend! ๐ŸŽ‰
# Run with: uvicorn app:app --reload

You instantly get:

  • โœ… Complete authentication (signup, login, password reset)
  • โœ… User management with JSONB settings
  • โœ… Organization management with multi-tenancy
  • โœ… Role-based permissions (RBAC)
  • โœ… PayPal payment integration
  • โœ… Auto-created database tables
  • โœ… Interactive API docs at /docs

๐Ÿ“ฆ Installation

From PyPI (Production - Recommended)

Simple installation:

pip install apex-saas-framework

That's it! No special flags needed! โœ…

From Test PyPI (For Testing)

If you want to test pre-release versions:

pip install --index-url https://pypi.org/simple/ --extra-index-url https://test.pypi.org/simple/ apex-saas-framework

๐Ÿš€ Features

  • ๐ŸŽฏ LangChain-Style Simplicity - Minimal imports, maximum functionality
  • ๐Ÿข Multi-tenant Architecture - Organizations with row-level isolation
  • ๐Ÿ‘ฅ User Management - Complete user system with JWT authentication
  • ๐Ÿ” Authentication - Signup, login, forgot/reset password, change password
  • ๐Ÿ›ก๏ธ RBAC - Role-based access control with permissions
  • ๐Ÿ“ฆ Extensible Models - Extend base models using ORM inheritance
  • ๐Ÿ—„๏ธ PostgreSQL - SQLAlchemy 2.0 with async support
  • ๐Ÿ’ณ PayPal Integration - Subscription management and webhooks
  • โš™๏ธ JSONB Settings - Flexible user and organization settings
  • ๐ŸŽจ Feature Flags - Module system for enabling/disabling features
  • ๐Ÿ“ง Email Integration - SendGrid adapter with templates
  • ๐Ÿ› ๏ธ CLI Tools - Command-line utilities
  • ๐Ÿ“ Auto-Documentation - Interactive API docs with FastAPI

๐Ÿ’ก Simple Examples

Minimal App (2 Lines!)

from apex import Apex
app = Apex().app

With Custom Models

from apex import Apex, User, Organization
from sqlalchemy import Column, String

class MyUser(User):
    __tablename__ = "users"
    department = Column(String(100))

app = Apex(models=[MyUser]).app

With Custom Endpoints

from apex import Apex, auth_required, User

app = Apex().app

@app.get("/api/profile")
@auth_required
async def get_profile(user: User):
    return {"email": user.email, "name": user.first_name}

Fluent API Style

from apex import Apex

app = (
    Apex()
    .with_auth()
    .with_payments()
    .with_rbac()
    .build()
)

๐ŸŽฏ Quick Start Guide

1. Create Your Models

Start by re-exporting the Apex defaults so each table is only registered once:

# app/models.py
from apex.app.models.default import (
    Organization,
    OrganizationLocation,
    Permission,
    Role,
    User,
)

__all__ = ["Organization", "OrganizationLocation", "Permission", "Role", "User"]

Need custom columns? Create new subclasses (e.g. class CustomUser(User): ...) in a separate module and update the dependency overrides (get_user_service, get_organization_model, etc.) to point at them. Avoid redefining the stock tables in placeโ€”SQLAlchemy will raise โ€œTable โ€ฆ already definedโ€ otherwise.

2. Configure Settings

Copy .env.example to .env and update with your values:

cp .env.example .env

Minimum required configuration:

# Database (Required)
DATABASE_URL=postgresql://user:password@localhost:5432/mydb

# Security (Required)
SECRET_KEY=your-secret-key-here-minimum-32-characters

Generate a secure secret key:

python -c "import secrets; print(secrets.token_urlsafe(32))"

See Configuration Reference below for all available options.

3. Set Up Database

# app/database.py
from apex.infrastructure.database import Base, engine
from app.models import User, Organization, Role, Permission

# Create tables
async def init_db():
    async with engine.begin() as conn:
        await conn.run_sync(Base.metadata.create_all)

4. Create Your FastAPI App

# app.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from apex.api.v1.auth.router import router as auth_router
from apex.core.authentication.dependencies import get_auth_service
from apex.core.config import get_settings
from app.dependencies import get_auth_service as project_get_auth_service

settings = get_settings()

app = FastAPI(
    title=settings.APP_NAME,
    version=settings.APP_VERSION,
    debug=settings.DEBUG,
)

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.CORS_ORIGINS,
    allow_credentials=settings.CORS_ALLOW_CREDENTIALS,
    allow_methods=settings.CORS_ALLOW_METHODS,
    allow_headers=settings.CORS_ALLOW_HEADERS,
)

app.dependency_overrides[get_auth_service] = project_get_auth_service
app.include_router(auth_router, prefix=settings.API_V1_PREFIX)

@app.get("/")
async def root():
    return {"message": "Apex"}

5. Override Auth Service

# app/services.py
from apex.domain.services.auth import AuthService
from app.models import User
from sqlalchemy.ext.asyncio import AsyncSession

def get_auth_service(db: AsyncSession) -> AuthService:
    return AuthService(session=db, user_model=User)

6. Run Migrations

Set up Alembic:

alembic init migrations

Copy apex/migrations/env.py to your project and modify it to import your models:

# migrations/env.py
from apex.infrastructure.database.base import Base
from app.models import User, Organization, Role, Permission

target_metadata = Base.metadata

Create and run migrations:

alembic revision --autogenerate -m "Initial migration"
alembic upgrade head

Architecture

Project Structure

apex/
โ”œโ”€โ”€ core/                    # Core functionality
โ”‚   โ”œโ”€โ”€ config/              # Settings (Pydantic BaseSettings)
โ”‚   โ”œโ”€โ”€ security/            # Password hashing, JWT utilities
โ”‚   โ”œโ”€โ”€ authentication/      # Auth dependencies (get_current_user, etc.)
โ”‚   โ”œโ”€โ”€ permissions/         # RBAC dependencies (require_role, require_permission)
โ”‚   โ””โ”€โ”€ utils/               # Utility functions
โ”œโ”€โ”€ domain/                  # Business logic layer
โ”‚   โ”œโ”€โ”€ models/              # Base domain models (abstract)
โ”‚   โ”‚   โ”œโ”€โ”€ user.py          # BaseUser model
โ”‚   โ”‚   โ”œโ”€โ”€ organization.py  # BaseOrganization, BaseOrganizationLocation
โ”‚   โ”‚   โ”œโ”€โ”€ role.py          # BaseRole model
โ”‚   โ”‚   โ””โ”€โ”€ permission.py    # BasePermission model
โ”‚   โ”œโ”€โ”€ repositories/        # Repository pattern (BaseRepository)
โ”‚   โ””โ”€โ”€ services/            # Business services (AuthService, UserService)
โ”œโ”€โ”€ infrastructure/          # External adapters
โ”‚   โ”œโ”€โ”€ database/            # Database setup (SQLAlchemy async, session mgmt)
โ”‚   โ”œโ”€โ”€ email/               # Email adapters (SMTP, abstract interface)
โ”‚   โ”œโ”€โ”€ storage/             # File storage adapters (Local, S3-ready)
โ”‚   โ””โ”€โ”€ payments/            # Payment scaffolding (Stripe-ready)
โ”œโ”€โ”€ api/                     # API layer
โ”‚   โ””โ”€โ”€ v1/                  # API version 1
โ”‚       โ”œโ”€โ”€ auth/            # Authentication routes
โ”‚       โ”‚   โ””โ”€โ”€ router.py    # Login, logout, refresh, me endpoints
โ”‚       โ””โ”€โ”€ schemas/         # Pydantic request/response schemas
โ”‚           โ”œโ”€โ”€ auth.py      # Auth schemas
โ”‚           โ””โ”€โ”€ user.py      # User schemas
โ”œโ”€โ”€ migrations/              # Alembic templates
โ”‚   โ”œโ”€โ”€ env.py               # Alembic environment (copy to user project)
โ”‚   โ””โ”€โ”€ script.py.mako       # Migration script template
โ””โ”€โ”€ cli/                     # CLI utilities (Typer)
    โ””โ”€โ”€ main.py              # CLI commands (version, check, init-db, etc.)

Design Principles

  1. Clean Architecture - Separation of concerns with clear layers
  2. Extensibility - Extend base classes, don't modify them
  3. Type Safety - Full type hints throughout
  4. Async First - Built for async/await patterns
  5. Framework Agnostic Core - Business logic independent of FastAPI

Usage Examples

Authentication

from apex.domain.services.auth import AuthService
from app.models import User

# Login
auth_service = AuthService(session=db, user_model=User)
user = await auth_service.authenticate_user("user@example.com", "password")
tokens = await auth_service.create_tokens(user)

User Management

from apex.domain.services.user import UserService

user_service = UserService(session=db, user_model=User)

# Create user
user = await user_service.create_user(
    email="user@example.com",
    password="securepassword",
    full_name="John Doe",
)

# Update user
await user_service.update_user(user, full_name="Jane Doe")

# Change password
await user_service.change_password(user, "oldpass", "newpass")

Permissions

from apex.core.permissions import require_permission, require_role

# In your router
@router.post("/users")
async def create_user(
    current_user: dict = Depends(require_permission("users", "create"))
):
    # User has "users:create" permission
    pass

@router.delete("/users/{id}")
async def delete_user(
    id: str,
    current_user: dict = Depends(require_role("admin"))
):
    # User has "admin" role
    pass

File Storage

from apex.infrastructure.storage import LocalStorageAdapter

storage = LocalStorageAdapter()

# Upload file
file_path = await storage.upload_file(
    file=uploaded_file,
    filename="document.pdf",
    folder="documents"
)

# Get file URL
url = await storage.get_file_url(file_path)

Email

from apex.infrastructure.email import SMTPEmailAdapter

email = SMTPEmailAdapter()

await email.send_email(
    to="user@example.com",
    subject="Welcome!",
    body="Welcome to our platform",
    html="<h1>Welcome!</h1>"
)

Configuration

All configuration is done via environment variables or .env file. Copy .env.example to .env and customize.

Required Settings

Variable Description Example
DATABASE_URL PostgreSQL connection string postgresql://user:pass@localhost:5432/db
SECRET_KEY JWT secret key (min 32 chars) Generate with secrets.token_urlsafe(32)

Application Settings

Variable Description Default
APP_NAME Application name "Apex Backend"
DEBUG Debug mode False
API_V1_PREFIX API version 1 prefix "/api/v1"

Database Settings

Variable Description Default
DB_ECHO Log SQL queries False
DB_POOL_SIZE Connection pool size 5
DB_MAX_OVERFLOW Max overflow connections 10

JWT/Auth Settings

Variable Description Default
ALGORITHM JWT algorithm "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES Access token lifetime 30
REFRESH_TOKEN_EXPIRE_DAYS Refresh token lifetime 7

CORS Settings

Variable Description Default
CORS_ORIGINS Allowed origins (comma-separated) "http://localhost:3000"
CORS_ALLOW_CREDENTIALS Allow credentials True
CORS_ALLOW_METHODS Allowed HTTP methods "GET,POST,PUT,DELETE,PATCH,OPTIONS"
CORS_ALLOW_HEADERS Allowed headers "*"

Email Settings (Optional)

Variable Description Example
SMTP_HOST SMTP server smtp.gmail.com
SMTP_PORT SMTP port 587
SMTP_USER SMTP username your-email@gmail.com
SMTP_PASSWORD SMTP password Your app password
SMTP_FROM_EMAIL From email address noreply@yourdomain.com
SMTP_USE_TLS Use TLS True

Storage Settings

Variable Description Default
STORAGE_TYPE Storage type (local or s3) "local"
STORAGE_LOCAL_PATH Local storage path "./uploads"
AWS_ACCESS_KEY_ID AWS access key (if using S3) -
AWS_SECRET_ACCESS_KEY AWS secret key (if using S3) -
AWS_REGION AWS region (if using S3) "us-east-1"
AWS_S3_BUCKET S3 bucket name (if using S3) -

Payment Settings (Optional)

Variable Description Example
STRIPE_SECRET_KEY Stripe secret key sk_test_...
STRIPE_PUBLISHABLE_KEY Stripe publishable key pk_test_...
STRIPE_WEBHOOK_SECRET Stripe webhook secret whsec_...

Multi-tenancy

Variable Description Default
MULTI_TENANT_MODE Enable multi-tenancy True

CLI Commands

The apex command-line tool provides utilities for managing your application:

# Show package version
apex version

# Check configuration and database connection
apex check

# Initialize database (base implementation - extend in your app)
apex init-db

# Create superuser (base implementation - extend in your app)
apex create-superuser --email admin@example.com --password

Note: init-db and create-superuser are base implementations. You should extend these commands in your application to work with your specific User model.

Extending the Framework

Custom User Model

class User(BaseUser):
    __tablename__ = "users"
    
    # Add custom fields
    avatar_url: Mapped[str | None] = None
    bio: Mapped[str | None] = None

Custom Service

from apex.domain.services.user import UserService

class CustomUserService(UserService):
    async def get_users_by_organization(self, org_id: str):
        # Custom logic
        pass

Custom Repository

from apex.domain.repositories.base import BaseRepository

class UserRepository(BaseRepository[User]):
    async def get_by_email(self, email: str) -> User | None:
        # Custom query
        pass

Testing

from fastapi.testclient import TestClient
from apex.infrastructure.database import get_db

# Override database dependency
app.dependency_overrides[get_db] = get_test_db

client = TestClient(app)
response = client.post("/api/v1/auth/login", json={
    "email": "test@example.com",
    "password": "password"
})

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

MIT License - see LICENSE file for details.

Project Files

  • pyproject.toml - Package configuration and dependencies
  • .env.example - Template for environment variables (copy to .env)
  • .gitignore - Git ignore patterns
  • .cursor/rules/cursorrules.mdc - Cursor AI editing rules
  • README.md - This file

Support

Roadmap

  • S3 storage adapter implementation
  • Stripe payment integration
  • Audit logging system
  • Module/feature flag system
  • WebSocket support
  • GraphQL support
  • More comprehensive tests
  • Docker deployment examples

Built with โค๏ธ using FastAPI, SQLAlchemy, and modern Python practices.

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

apex_saas_framework-0.3.11.tar.gz (76.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

apex_saas_framework-0.3.11-py3-none-any.whl (101.7 kB view details)

Uploaded Python 3

File details

Details for the file apex_saas_framework-0.3.11.tar.gz.

File metadata

  • Download URL: apex_saas_framework-0.3.11.tar.gz
  • Upload date:
  • Size: 76.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for apex_saas_framework-0.3.11.tar.gz
Algorithm Hash digest
SHA256 40a59be6dd78fb77c5a074054337f7c37da4295ce00906b11e1124060a83545b
MD5 ade25ebca8455bc5148b401e06cb0d8d
BLAKE2b-256 721610c2c5de890ad0f5f119d20052003a4962275fbdb5526d8974fc77689b19

See more details on using hashes here.

File details

Details for the file apex_saas_framework-0.3.11-py3-none-any.whl.

File metadata

File hashes

Hashes for apex_saas_framework-0.3.11-py3-none-any.whl
Algorithm Hash digest
SHA256 1d77116ad17eb348a0664ed797b4e0142a59bed0a92e269b8112b2adada564d0
MD5 88cb0681764049c00c195baef1808f7a
BLAKE2b-256 85d1abcad24bcb452266ded942326135d43ebcbdc5c8816a1a4e2293f9ee210c

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