# Vibetuner > Vibetuner is a production-ready FastAPI project scaffolding tool that generates full-stack web applications with authentication, flexible database support (MongoDB or SQL), frontend, Docker deployment, and CLI tools pre-configured in seconds. Built by All Tuner Labs for rapid iteration and modern development. Important notes: - Vibetuner consists of four packages: a Python framework (`vibetuner`), a JavaScript build-deps package (`@alltuner/vibetuner`) which bundles tailwind, daisyui, htmx and an npm-shipped mirror of the framework's jinja templates (`@alltuner/vibetuner-jinja`, pulled in as a transitive — consumers don't install it directly), and a Copier scaffolding template - The framework separates immutable framework code (`vibetuner` package) from your application code (`src/app/`) for clean updates - In all examples, `app` refers to your project's Python package (the directory under `src/`). The actual name depends on your project slug (e.g., `src/myproject/` for a project named "myproject") - HTMX is used instead of React/Vue for simplicity - server-rendered HTML with sprinkles of interactivity - All tools are chosen for speed: uv (Python), bun (JavaScript), Granian (ASGI server), Ruff (linting) - The project is designed to work excellently with AI coding assistants like Claude, Cursor, and ChatGPT ## Quick Start - [Quick Start Guide](https://vibetuner.alltuner.com/quick-start/): Get started with Vibetuner in 5 minutes - [Installation](https://vibetuner.alltuner.com/installation/): Prerequisites and installation options - [Your First Project](https://vibetuner.alltuner.com/quick-start/#create-your-first-project): Interactive project setup with `uvx vibetuner scaffold new` ## Core Documentation - [Development Guide](https://vibetuner.alltuner.com/development-guide/): Daily development workflow, adding routes, models, templates, and background jobs - [Architecture](https://vibetuner.alltuner.com/architecture/): System design, four-package architecture, request flow, and core components - [Tech Stack](https://vibetuner.alltuner.com/tech-stack/): Detailed information about all technologies used and why they were chosen - [Authentication](https://vibetuner.alltuner.com/authentication/): OAuth and magic link authentication setup and configuration - [Background Tasks](https://vibetuner.alltuner.com/background-tasks/): Background task system powered by Streaq and Redis with retries, cron scheduling, and SSE integration - [Runtime Configuration](https://vibetuner.alltuner.com/runtime-config/): Layered configuration system with MongoDB persistence, debug UI, and feature flags - [HTMX v2 to v4 Migration](https://vibetuner.alltuner.com/htmx-migration/): Breaking changes and migration guide for upgrading from HTMX v2 to v4 - [Theming](https://vibetuner.alltuner.com/theming/): Build-time brand palette via cascade override of DaisyUI's `[data-theme="…"]` selectors in `config.css` (no consumer-side `daisyui` dep needed), plus runtime per-tenant overrides via the embedded `TenantTheme` model + opt-in `register_tenant_theme_provider()` helper + shipped `base/theme.html.jinja` partial that injects DaisyUI role-color overrides at request time ## Features - **HTMX Request Detection**: `request.state.htmx` available on every request (via `starlette-htmx` middleware). Properties: `.boosted`, `.target`, `.trigger`, `.trigger_name`, `.current_url`, `.prompt`. Use `require_htmx` dependency from `vibetuner.frontend.deps` to reject non-HTMX requests with 400 - **CRUD Factory**: `create_crud_routes()` generates list/create/read/update/delete endpoints for Beanie models with pagination, filtering, sorting, and search - **SSE Helpers**: `@sse_endpoint()` and `broadcast()` for real-time streaming with HTMX. Import from `vibetuner.sse`. Redis pub/sub for multi-worker support - **`@render` Decorator**: `@render("template.html.jinja")` eliminates `render_template()` boilerplate — route returns a dict, decorator handles rendering. Returns `Response` objects unchanged (escape hatch). Import from `vibetuner` - **Streaming HTML**: `render_template_stream()` returns a `StreamingResponse` using Jinja2's `generate()`, improving TTFB for large pages. Same context merging as `render_template()`. Import from `vibetuner` - **Block Rendering**: `render_template_block(template, block_name, request, ctx)` renders a single `{% block %}` for HTMX partials. `render_template_blocks()` renders multiple blocks for OOB swaps. No extra dependencies. Import from `vibetuner` - **Context kwarg**: `render_template*` accepts the user context positionally, as `ctx=`, or as `context=` (alias for `ctx=`). Passing both, or any unknown kwarg, raises `TypeError` — typos cannot silently render with an empty context - **`@cache` Decorator**: `@cache(expire=60)` caches route responses in Redis. Key derived from path + query params. Use `vary_on=lambda r: str(r.state.user.id)` for request-dependent keys (per-user, per-tenant). Disabled in debug mode (override with `force_caching=True`). No-op if Redis unavailable. `invalidate(path)` and `invalidate_pattern(path)` for cache busting. Import from `vibetuner.cache` - **`@cache_control` Decorator**: `@cache_control(max_age=300, public=True)` sets `Cache-Control` headers declaratively. Supports `public`, `private`, `no_cache`, `no_store`, `max_age`, `s_maxage`, `must_revalidate`, `stale_while_revalidate`, `immutable`. Import from `vibetuner.decorators` - **HTMX Response Helpers**: `hx_redirect()`, `hx_location()`, `hx_trigger()`, `hx_push_url()`, `hx_reswap()`, `hx_retarget()`, `hx_refresh()`, `hx_replace_url()`, `hx_trigger_after_settle()`, `hx_trigger_after_swap()`. Handles JSON serialization internally. Import from `vibetuner.htmx` - **Built-in Template Globals**: `request`, `language`, `DEBUG`, `now` (UTC datetime), `today` (ISO date string), `project` (`settings.project`), `brand` (`settings.brand`), `csp_nonce`, and `hotreload` are available in all templates automatically - **Skeleton Extension Points**: `base/skeleton.html.jinja` exposes blocks (`extra_head_links`, `extra_scripts`, `before_main`, `after_main`) and context variables (`color_scheme`, `canonical_url`, `font_preloads`) so projects can extend instead of wholesale-overriding the skeleton — upstream changes (CSP nonce, theming, etc.) flow through automatically - **Brand Configuration**: `BRAND_PRIMARY_COLOR`, `BRAND_BROWSER_THEME_COLOR`, `BRAND_EMAIL_BUTTON_COLOR` env vars drive favicon meta tags, the PWA manifest's `theme_color`/`background_color`, and the magic-link email button — surfaces where DaisyUI/CSS-variable theming can't reach (favicon meta is read before CSS runs; email clients ignore CSS variables). Accepts pydantic-Color inputs (named, `rgb()`, hex). For per-tenant in-page colors use `TenantTheme`; `BrandSettings` is deliberately app-level - **Encrypted Fields**: `EncryptedFieldsMixin` and `EncryptedStr` type for transparent Fernet encrypt-on-save / decrypt-on-load on any Beanie model field. Import from `vibetuner.models.mixins`. Requires `FIELD_ENCRYPTION_KEY` env var - **Template Context Providers**: `register_globals()` and `@register_context_provider` inject variables into every template render - **Per-Tenant Theming**: `TenantTheme` embedded model (`vibetuner.models.TenantTheme`) with eight optional `#rrggbb` fields for DaisyUI role / role-content colors plus `.overrides()` for the `{css_var: hex}` map. Wire it up with `register_tenant_theme_provider(getter)` from `vibetuner` — opt-in, runs on every render, fail-soft. Vibetuner's `base/skeleton.html.jinja` already includes `base/theme.html.jinja`, which emits a CSP-noncified `` block after `bundle.css`. `bundle.css` stays tenant-agnostic and cached - **i18n Primitives**: `vibetuner.i18n` ships `register_locale_resolver(getter, *, priority=0)` to inject custom selectors at the front of `LocaleMiddleware`'s chain (per-tenant locale becomes a one-liner), `set_request_language(request, code)` to update both the Babel context and `request.state.language` in one call, and `language_picker(display_locale=None)` returning `[{code, name}]` with names rendered in the current request's locale (browsing in Spanish gives "inglés / español / catalán"; never English-only). `language_picker` is also registered as a Jinja global so templates can call it directly without overriding any existing template variable - **Framework Translation Catalogs**: vibetuner ships compiled `.mo` files under `vibetuner/locales//LC_MESSAGES/messages.mo` (currently `en`, `ca`). `frontend/middleware.py` loads them before the project's own `locales/` so framework templates (`login.html.jinja`, `user/profile.html.jinja`, etc.) render in the active locale with no per-app extraction. App catalogs loaded after the framework override framework strings on collision via gettext domain merging. Add a new framework locale with `just new-framework-locale ` then `just compile-framework-locales` - **Service DI**: `get_email_service()`, `get_blob_service()`, `get_runtime_config()` FastAPI dependency wrappers - **Email Providers**: Pluggable transactional email via Resend (`MAIL_RESEND_API_KEY`), Mailjet (`MAIL_MAILJET_API_KEY` + `MAIL_MAILJET_API_SECRET`), or Cloudflare Email Service (`MAIL_CLOUDFLARE_API_TOKEN` + `MAIL_CLOUDFLARE_ACCOUNT_ID`). Auto-detected from available credentials; `MAIL_PROVIDER=resend|mailjet|cloudflare` to pick explicitly. Auto-detection priority: resend > mailjet > cloudflare - **CSP Nonce Auto-Injection**: `SecurityHeadersMiddleware` generates a unique CSP nonce per request and auto-injects it into all `