<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: RapidKit </title>
    <description>The latest articles on Forem by RapidKit  (@rapidkit).</description>
    <link>https://forem.com/rapidkit</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3639844%2Fd7e3b4b9-412a-4e84-b7b7-d2ac18c3a99a.png</url>
      <title>Forem: RapidKit </title>
      <link>https://forem.com/rapidkit</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rapidkit"/>
    <language>en</language>
    <item>
      <title>Stop Managing 10 Virtual Environments. Use a Workspace.</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Sat, 21 Feb 2026 07:56:28 +0000</pubDate>
      <link>https://forem.com/rapidkit/stop-managing-10-virtual-environments-use-a-workspace-49gk</link>
      <guid>https://forem.com/rapidkit/stop-managing-10-virtual-environments-use-a-workspace-49gk</guid>
      <description>&lt;p&gt;How RapidKit's workspace architecture eliminates environment drift, cuts setup time to minutes, and lets you manage FastAPI, NestJS, and Go services from a single shared environment.&lt;/p&gt;

&lt;p&gt;I used to manage backend projects like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/projects/
  auth-api/       ← Python 3.10, venv, poetry
  billing-api/    ← Python 3.11, venv, pip
  user-service/   ← Python 3.10, venv, poetry (different poetry version)
  ai-agent/       ← Python 3.11, conda (someone on the team liked conda)
  notifications/  ← NestJS (fine, no env problem here)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every project had its own environment. Every new service meant 20–30 minutes of setup. Every &lt;code&gt;git clone&lt;/code&gt; from a teammate ended in "it works on my machine."&lt;/p&gt;

&lt;p&gt;Sound familiar?&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fix: Shared Workspace Environment
&lt;/h2&gt;

&lt;p&gt;The concept is simple: &lt;strong&gt;one environment hosts multiple services.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-workspace/
├── .venv/                  ← shared Python env (~150 MB, once)
├── pyproject.toml          ← shared dependency config
├── .rapidkit-workspace     ← workspace marker
├── auth-api/               ← FastAPI project
├── billing-api/            ← FastAPI DDD project  
├── notifications/          ← NestJS project
└── ai-agent/               ← FastAPI + AI module
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;All services share the same Python version, the same virtualenv, the same tooling. But each service is independently deployable with its own &lt;code&gt;Dockerfile&lt;/code&gt;, &lt;code&gt;pyproject.toml&lt;/code&gt;, and CI pipeline.&lt;/p&gt;




&lt;h2&gt;
  
  
  From Zero to Multi-Service Backend
&lt;/h2&gt;

&lt;p&gt;Here's how fast this actually is with &lt;a href="https://getrapidkit.com" rel="noopener noreferrer"&gt;RapidKit&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Create the workspace&lt;/span&gt;
npx rapidkit create workspace my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace

&lt;span class="c"&gt;# 2. Scaffold services (pick your kits)&lt;/span&gt;
npx rapidkit create project fastapi.standard auth-api
npx rapidkit create project fastapi.ddd billing-api
npx rapidkit create project nestjs.standard notifications
npx rapidkit create project gofiber.standard high-perf-proxy

&lt;span class="c"&gt;# 3. Init all services at once (from workspace root)&lt;/span&gt;
npx rapidkit init

&lt;span class="c"&gt;# 4. Check everything&lt;/span&gt;
npx rapidkit doctor &lt;span class="nt"&gt;--workspace&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That last command gives you this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📊 Health Score:
   100% ████████████████████
   ✅ 12 passed | ⚠️ 0 warnings | ❌ 0 errors

System Tools:
✅ Python: Python 3.11.8
✅ Poetry: Poetry 2.3.1
✅ Go: Go 1.24.4
✅ RapidKit Core: 0.3.8

Projects:
✅ auth-api          FastAPI Standard  | Tests ✅ | Docker ✅ | Deps ✅
✅ billing-api       FastAPI DDD       | Tests ✅ | Docker ✅ | Deps ✅
✅ notifications     NestJS Standard   | Tests ✅ | Docker ✅ | Deps ✅
✅ high-perf-proxy   Go/Fiber Standard | Tests ✅ | Docker ✅ | Deps ✅
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One command. Full workspace health report.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Each Scaffolded Project Includes
&lt;/h2&gt;

&lt;p&gt;Every &lt;code&gt;rapidkit create project&lt;/code&gt; gives you a production-ready base:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;FastAPI Standard&lt;/th&gt;
&lt;th&gt;FastAPI DDD&lt;/th&gt;
&lt;th&gt;NestJS Standard&lt;/th&gt;
&lt;th&gt;Go/Fiber Standard&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Clean Architecture&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ DDD layers&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker + Compose&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅ multi-stage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Actions CI&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests&lt;/td&gt;
&lt;td&gt;✅ pytest&lt;/td&gt;
&lt;td&gt;✅ pytest&lt;/td&gt;
&lt;td&gt;✅ Jest&lt;/td&gt;
&lt;td&gt;✅ Go test&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linting&lt;/td&gt;
&lt;td&gt;✅ ruff&lt;/td&gt;
&lt;td&gt;✅ ruff&lt;/td&gt;
&lt;td&gt;✅ ESLint&lt;/td&gt;
&lt;td&gt;✅ golangci-lint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.env handling&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Health endpoint&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Makefile&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Zero config. All baked in.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Module System: Composable Features
&lt;/h2&gt;

&lt;p&gt;Once your project exists, add features with one command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;auth-api
rapidkit add module auth          &lt;span class="c"&gt;# JWT/session auth&lt;/span&gt;
rapidkit add module db_postgres   &lt;span class="c"&gt;# async SQLAlchemy + Alembic&lt;/span&gt;
rapidkit add module redis         &lt;span class="c"&gt;# caching layer&lt;/span&gt;
rapidkit add module rate_limiting &lt;span class="c"&gt;# route-level rate limits&lt;/span&gt;
rapidkit add module observability &lt;span class="c"&gt;# Prometheus metrics + tracing&lt;/span&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;billing-api
rapidkit add module auth          &lt;span class="c"&gt;# same auth module, same interface&lt;/span&gt;
rapidkit add module stripe        &lt;span class="c"&gt;# Stripe webhooks + billing logic&lt;/span&gt;

&lt;span class="nb"&gt;cd &lt;/span&gt;ai-agent
rapidkit add module ai_assistant  &lt;span class="c"&gt;# multi-provider AI (OpenAI, local)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;27+ modules available.&lt;/strong&gt; Each module:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adds pre-configured code in the right layers&lt;/li&gt;
&lt;li&gt;Updates &lt;code&gt;pyproject.toml&lt;/code&gt; / &lt;code&gt;package.json&lt;/code&gt; automatically&lt;/li&gt;
&lt;li&gt;Includes tests&lt;/li&gt;
&lt;li&gt;Follows the same clean architecture conventions&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Live Example: AI Workspace
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;my-ai-workspace&lt;/code&gt; in &lt;a href="https://github.com/getrapidkit/rapidkit-examples" rel="noopener noreferrer"&gt;rapidkit-examples&lt;/a&gt; has two services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ai-agent&lt;/code&gt; — FastAPI with &lt;code&gt;ai_assistant&lt;/code&gt; module (multi-provider: OpenAI, echo, support)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ai-agent-nest&lt;/code&gt; — NestJS equivalent
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone and run the example&lt;/span&gt;
git clone https://github.com/getrapidkit/rapidkit-examples
&lt;span class="nb"&gt;cd &lt;/span&gt;rapidkit-examples/my-ai-workspace

&lt;span class="c"&gt;# One command to init everything&lt;/span&gt;
npx rapidkit init

&lt;span class="c"&gt;# Run the AI agent&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;ai-agent &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit dev

&lt;span class="c"&gt;# Test it&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8000/ai/assistant/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"prompt": "What is RapidKit?", "provider": "echo"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Works without an OpenAI key — falls back to local providers automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  The VS Code Extension: Workspace Without the Terminal
&lt;/h2&gt;

&lt;p&gt;If CLI isn't your primary workflow, the &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;RapidKit VS Code Extension&lt;/a&gt; gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workspace Explorer tree&lt;/strong&gt; — all services visible at a glance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-click service creation&lt;/strong&gt; — no &lt;code&gt;npx&lt;/code&gt; needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Module browser&lt;/strong&gt; — search, preview, install from the UI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Live health indicators&lt;/strong&gt; — real-time service status&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrated doctor output&lt;/strong&gt; — health checks without leaving the editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Open workspace folder → see all services → click to create/manage. That's it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Matters for Scaling
&lt;/h2&gt;

&lt;p&gt;The workspace model pays off exponentially as you grow:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Services&lt;/th&gt;
&lt;th&gt;Traditional (separate envs)&lt;/th&gt;
&lt;th&gt;Workspace&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;30 min setup&lt;/td&gt;
&lt;td&gt;2 min setup&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;90 min + env drift&lt;/td&gt;
&lt;td&gt;5 min, zero drift&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;150 min + conflict debugging&lt;/td&gt;
&lt;td&gt;8 min, single health check&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Week of onboarding per engineer&lt;/td&gt;
&lt;td&gt;1 day onboarding for all services&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Onboarding a new engineer to the entire workspace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;workspace-repo&amp;gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace
npx rapidkit init  &lt;span class="c"&gt;# installs shared env + all project deps&lt;/span&gt;
npx rapidkit doctor &lt;span class="nt"&gt;--workspace&lt;/span&gt;  &lt;span class="c"&gt;# ✅ everything green&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Done. One command. Full environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Workspace = one venv, many services&lt;/strong&gt; — no environment drift, consistent tooling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;npx rapidkit create project &amp;lt;kit&amp;gt; &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/strong&gt; — production-ready service in under 2 minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;rapidkit add module &amp;lt;slug&amp;gt;&lt;/code&gt;&lt;/strong&gt; — features composed consistently across services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;npx rapidkit doctor --workspace&lt;/code&gt;&lt;/strong&gt; — full workspace health in one command&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supports FastAPI, FastAPI DDD, NestJS, Go/Fiber&lt;/strong&gt; — mixed-language workspaces supported&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code Extension&lt;/strong&gt; — visual interface for the full workflow&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit create workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;→ &lt;a href="https://getrapidkit.com" rel="noopener noreferrer"&gt;getrapidkit.com&lt;/a&gt;&lt;br&gt;
→ &lt;a href="https://github.com/getrapidkit/rapidkit-examples" rel="noopener noreferrer"&gt;Examples repo&lt;/a&gt;&lt;br&gt;
→ &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;VS Code Extension&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you dealt with environment drift in a multi-service backend? What was your solution? Drop it in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>rapidkit</category>
      <category>devtools</category>
      <category>backend</category>
      <category>python</category>
    </item>
    <item>
      <title>Build a Production-Ready FastAPI E-Commerce API with RapidKit (Step-by-Step)</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Tue, 17 Feb 2026 07:44:56 +0000</pubDate>
      <link>https://forem.com/rapidkit/build-a-production-ready-fastapi-e-commerce-api-with-rapidkit-step-by-step-llm</link>
      <guid>https://forem.com/rapidkit/build-a-production-ready-fastapi-e-commerce-api-with-rapidkit-step-by-step-llm</guid>
      <description>&lt;h2&gt;
  
  
  Let's Build Something Real
&lt;/h2&gt;

&lt;p&gt;Not a hello-world demo. A &lt;strong&gt;real FastAPI project&lt;/strong&gt; you can deploy.&lt;/p&gt;

&lt;p&gt;We'll build a &lt;strong&gt;Product Management API&lt;/strong&gt; with:&lt;br&gt;
• Authentication&lt;br&gt;
• PostgreSQL database&lt;br&gt;
• Redis caching&lt;br&gt;
• Email notifications&lt;br&gt;
• Production deployment&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's begin.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Before We Begin: Three Ways to Create Projects
&lt;/h2&gt;
&lt;h3&gt;
  
  
  🎯 Approach 1: Workspace-First (Recommended)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace
rapidkit create project fastapi.standard product-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Teams, multiple services, production&lt;/p&gt;


&lt;h3&gt;
  
  
  🚀 Approach 2: Direct Project Creation
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit create project fastapi.standard product-api
&lt;span class="nb"&gt;cd &lt;/span&gt;product-api
npx rapidkit init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Single project, learning, prototyping&lt;/p&gt;


&lt;h3&gt;
  
  
  🎨 Approach 3: VS Code Extension
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install extension&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl+Shift+P&lt;/code&gt; → "RapidKit: Create Project"&lt;/li&gt;
&lt;li&gt;Choose FastAPI&lt;/li&gt;
&lt;li&gt;Enter name&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt; Visual learners, GUI preference&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;We'll use Approach 1 (workspace)&lt;/strong&gt; for this tutorial.&lt;/p&gt;


&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You need:&lt;br&gt;
• Node.js 20+&lt;br&gt;
• Python 3.10+&lt;br&gt;
• Docker (for PostgreSQL/Redis)&lt;/p&gt;

&lt;p&gt;That's it. RapidKit handles the rest.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 1: Create Workspace and Project
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create workspace&lt;/span&gt;
npx rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace

&lt;span class="c"&gt;# Create FastAPI project&lt;/span&gt;
rapidkit create project fastapi.standard product-api
&lt;span class="nb"&gt;cd &lt;/span&gt;product-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;What you get:&lt;/strong&gt;&lt;br&gt;
• Clean &lt;code&gt;src/&lt;/code&gt; architecture&lt;br&gt;
• Health check endpoint (&lt;code&gt;/health&lt;/code&gt;)&lt;br&gt;
• Testing setup (pytest)&lt;br&gt;
• Docker configs&lt;br&gt;
• CI/CD templates&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 2: Initialize Project
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;This installs:&lt;/strong&gt;&lt;br&gt;
• Poetry (if needed)&lt;br&gt;
• All dependencies&lt;br&gt;
• Development tools&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then start the server:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO: Uvicorn running on http://127.0.0.1:8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Visit:&lt;/strong&gt; &lt;a href="http://localhost:8000/docs" rel="noopener noreferrer"&gt;http://localhost:8000/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You see &lt;strong&gt;Swagger UI&lt;/strong&gt; with &lt;code&gt;/health&lt;/code&gt; endpoint.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Add Configuration Module
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module settings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Settings module provides:&lt;/strong&gt;&lt;br&gt;
• Multi-source config (&lt;code&gt;.env&lt;/code&gt;, env vars, CLI)&lt;br&gt;
• Type-safe with Pydantic&lt;br&gt;
• Environment-specific overrides&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create &lt;code&gt;.env&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;APP_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;Product API
&lt;span class="nv"&gt;APP_ENV&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;development
&lt;span class="nv"&gt;LOG_LEVEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;INFO
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Health check now shows:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"healthy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"modules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Add Database (PostgreSQL)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module db_postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Update &lt;code&gt;.env&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;POSTGRES_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;localhost
&lt;span class="nv"&gt;POSTGRES_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5432
&lt;span class="nv"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;myuser
&lt;span class="nv"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mypass
&lt;span class="nv"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;productdb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Start PostgreSQL:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt; postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The module provides:&lt;/strong&gt;&lt;br&gt;
• Async SQLAlchemy setup&lt;br&gt;
• Connection pooling&lt;br&gt;
• Health checks&lt;br&gt;
• Alembic migrations&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test connection:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8000/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"healthy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"modules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"db_postgres"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5: Create Product Model
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/app/models/product.py&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Boolean&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;sqlalchemy.ext.declarative&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;declarative_base&lt;/span&gt;

&lt;span class="n"&gt;Base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;declarative_base&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Base&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;__tablename__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;products&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;primary_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;stock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Column&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run migration:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit db migrate &lt;span class="s2"&gt;"Create products table"&lt;/span&gt;
rapidkit db upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 6: Add Redis Caching
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Update &lt;code&gt;.env&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;REDIS_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;redis://localhost:6379
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Start Redis:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt; redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use for caching:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.modules.redis&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;get_redis&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_product_cached&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;get_redis&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;cached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;product:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cached&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Fetch from DB
&lt;/span&gt;    &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch_from_db&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Cache for 5 minutes
&lt;/span&gt;    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;product:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 7: Add Authentication
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module auth_core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;br&gt;
• PBKDF2 password hashing&lt;br&gt;
• JWT token generation&lt;br&gt;
• Token validation middleware&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create user:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.modules.auth_core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;hash_password&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;create_token&lt;/span&gt;

&lt;span class="c1"&gt;# Hash password
&lt;/span&gt;&lt;span class="n"&gt;hashed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;hash_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;secure123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Store in DB
&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;hashed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;# Generate token
&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_token&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Protected endpoint:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.modules.auth_core&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;require_auth&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/products&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@require_auth&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ProductCreate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;current_user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_current_user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Only authenticated users can create
&lt;/span&gt;    &lt;span class="n"&gt;new_product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_product&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 8: Add Email Module
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Update &lt;code&gt;.env&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SMTP_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;smtp.gmail.com
&lt;span class="nv"&gt;SMTP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;587
&lt;span class="nv"&gt;SMTP_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-email@gmail.com
&lt;span class="nv"&gt;SMTP_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your-app-password
&lt;span class="nv"&gt;SMTP_FROM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;noreply@productapi.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Send email:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.modules.email&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;send_email&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;send_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;customer@example.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;subject&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Product Added to Cart&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Your product is ready!&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 9: Add Security Headers &amp;amp; CORS
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module cors
rapidkit add module security_headers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Update &lt;code&gt;.env&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;CORS_ORIGINS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:3000,https://yourapp.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Your API now has:&lt;/strong&gt;&lt;br&gt;
• CSP, HSTS, X-Frame-Options&lt;br&gt;
• Origin whitelisting&lt;br&gt;
• Credential support&lt;br&gt;
• Preflight handling&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 10: Add Logging
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module logging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;br&gt;
• Structured JSON logs&lt;br&gt;
• Correlation IDs&lt;br&gt;
• Multi-sink (console, file, HTTP)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logs look like:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-02-14T10:30:00Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"level"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INFO"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Product created"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"correlation_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"abc123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"product_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 11: Run Tests
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;===== test session starts =====
collected 24 items

tests/test_products.py ........
tests/test_auth.py ....
tests/test_cache.py ....
tests/test_health.py ....

===== 24 passed in 3.2s =====
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Every module includes tests.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 12: Deploy
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Build Docker image:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker build &lt;span class="nt"&gt;-t&lt;/span&gt; product-api &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Run container:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8000:8000 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;POSTGRES_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;db.example.com &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;REDIS_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;redis://cache.example.com &lt;span class="se"&gt;\&lt;/span&gt;
  product-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Or use GitHub Actions&lt;/strong&gt; (already configured in &lt;code&gt;.github/workflows/&lt;/code&gt;).&lt;/p&gt;




&lt;h2&gt;
  
  
  Project Structure (Final)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;product-api/
├── src/
│   ├── app/
│   │   ├── main.py
│   │   ├── models/
│   │   │   └── product.py
│   │   ├── routes/
│   │   │   └── products.py
│   │   └── modules/
│   │       ├── settings/
│   │       ├── db_postgres/
│   │       ├── redis/
│   │       ├── auth_core/
│   │       ├── email/
│   │       ├── cors/
│   │       ├── security_headers/
│   │       └── logging/
│   └── tests/
├── docker-compose.yml
├── Dockerfile
├── .env
└── pyproject.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What You Built
&lt;/h2&gt;

&lt;p&gt;✅ Product CRUD API&lt;br&gt;&lt;br&gt;
✅ PostgreSQL database&lt;br&gt;&lt;br&gt;
✅ Redis caching&lt;br&gt;&lt;br&gt;
✅ JWT authentication&lt;br&gt;&lt;br&gt;
✅ Email notifications&lt;br&gt;&lt;br&gt;
✅ CORS protection&lt;br&gt;&lt;br&gt;
✅ Security headers&lt;br&gt;&lt;br&gt;
✅ Structured logging&lt;br&gt;&lt;br&gt;
✅ Docker deployment&lt;br&gt;&lt;br&gt;
✅ CI/CD ready&lt;br&gt;&lt;br&gt;
✅ Tests passing&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time spent:&lt;/strong&gt; ~2 hours&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Lines written:&lt;/strong&gt; ~200&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Lines generated:&lt;/strong&gt; ~3,000&lt;/p&gt;


&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Modules are composable&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module X
rapidkit add module Y
&lt;span class="c"&gt;# They work together automatically&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Everything is configurable&lt;/strong&gt;&lt;br&gt;
All settings via &lt;code&gt;.env&lt;/code&gt; — no code changes needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Health checks included&lt;/strong&gt;&lt;br&gt;
Every module reports health at &lt;code&gt;/health&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Tests included&lt;/strong&gt;&lt;br&gt;
Every module brings its own tests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Standard FastAPI code&lt;/strong&gt;&lt;br&gt;
No lock-in. Modify anything. It's your code.&lt;/p&gt;


&lt;h2&gt;
  
  
  🧩 Explore More Modules
&lt;/h2&gt;

&lt;p&gt;This tutorial used &lt;strong&gt;8 modules&lt;/strong&gt;, but RapidKit offers &lt;strong&gt;27 free modules&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication &amp;amp; Security (9):&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;auth_core&lt;/code&gt;, &lt;code&gt;api_keys&lt;/code&gt;, &lt;code&gt;oauth&lt;/code&gt;, &lt;code&gt;passwordless&lt;/code&gt;, &lt;code&gt;session&lt;/code&gt;, &lt;code&gt;rbac&lt;/code&gt;, &lt;code&gt;cors&lt;/code&gt;, &lt;code&gt;security_headers&lt;/code&gt;, &lt;code&gt;rate_limiting&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database &amp;amp; Caching (4):&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;db_postgres&lt;/code&gt;, &lt;code&gt;db_mongodb&lt;/code&gt;, &lt;code&gt;db_mysql&lt;/code&gt;, &lt;code&gt;redis&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payments &amp;amp; E-commerce (3):&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;stripe_payment&lt;/code&gt;, &lt;code&gt;paypal_payment&lt;/code&gt;, &lt;code&gt;cart&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Communication (2):&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;email&lt;/code&gt;, &lt;code&gt;email_templates&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Business (3):&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;storage&lt;/code&gt; (S3/MinIO), &lt;code&gt;deployment&lt;/code&gt;, &lt;code&gt;observability_core&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Essentials (4):&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;settings&lt;/code&gt;, &lt;code&gt;logging&lt;/code&gt;, &lt;code&gt;celery&lt;/code&gt;, &lt;code&gt;users_core&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI (1):&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;ai_recommender&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't know which module?&lt;/strong&gt;&lt;br&gt;
🤖 Use AI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit modules recommend &lt;span class="s2"&gt;"I need user authentication and email"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://dev.tolink"&gt;Read full AI guide →&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 Clone Example Projects
&lt;/h2&gt;

&lt;p&gt;RapidKit VS Code Extension connects to real production-style workspaces:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Quickstart Product API&lt;/strong&gt; (&lt;code&gt;quickstart-workspace/product-api&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;E-Commerce API&lt;/strong&gt; (&lt;code&gt;quickstart-workspace/ecommerce-api&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AI Agent Workspace&lt;/strong&gt; (&lt;code&gt;my-ai-workspace&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SaaS Starter Workspace&lt;/strong&gt; (&lt;code&gt;saas-starter-workspace&lt;/code&gt;)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Clone from VS Code:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Welcome Panel → &lt;strong&gt;Example Workspaces&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select workspace&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;rapidkit init &amp;amp;&amp;amp; rapidkit dev&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Clone from terminal:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/getrapidkit/rapidkit-examples
&lt;span class="nb"&gt;cd &lt;/span&gt;rapidkit-examples/quickstart-workspace/ecommerce-api
&lt;span class="nb"&gt;source&lt;/span&gt; .rapidkit/activate
rapidkit init
rapidkit dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  E-Commerce Flow (Visual Summary)
&lt;/h2&gt;

&lt;p&gt;If you run &lt;code&gt;quickstart-workspace/ecommerce-api&lt;/code&gt;, this is the core payment lifecycle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stateDiagram-v2
  [*] --&amp;gt; Cart
  Cart --&amp;gt; Confirmed: POST /checkout
  Confirmed --&amp;gt; Paid: POST /payments/intents/{id}/confirm
  Confirmed --&amp;gt; Paid: webhook payment.succeeded
  Confirmed --&amp;gt; PaymentFailed: webhook payment.failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the request sequence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sequenceDiagram
  participant C as Client
  participant A as ecommerce-api
  participant P as Payment Provider (Mock)

  C-&amp;gt;&amp;gt;A: Add items to cart
  C-&amp;gt;&amp;gt;A: POST /checkout
  A--&amp;gt;&amp;gt;C: order.status=confirmed

  C-&amp;gt;&amp;gt;A: POST /payments/intents
  C-&amp;gt;&amp;gt;A: POST /payments/intents/{id}/confirm
  A--&amp;gt;&amp;gt;C: order.status=paid

  P-&amp;gt;&amp;gt;A: POST /webhooks/payments
  A--&amp;gt;&amp;gt;P: 202 accepted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Next: Build a &lt;strong&gt;NestJS microservice&lt;/strong&gt; and see how it compares to FastAPI.&lt;/p&gt;

&lt;p&gt;After that: New AI tracks (support triage, provider failover, cost control).&lt;/p&gt;




&lt;h3&gt;
  
  
  Learn More
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;a href="https://www.getrapidkit.com" rel="noopener noreferrer"&gt;getrapidkit.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;a href="https://www.npmjs.com/package/rapidkit" rel="noopener noreferrer"&gt;npm: rapidkit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐍 &lt;a href="https://pypi.org/project/rapidkit-core/" rel="noopener noreferrer"&gt;PyPI: rapidkit-core&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧩 &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;VS Code Extension&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;You just built a production API.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now ship it.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  rapidkit #fastapi #tutorial #python #backend #api #postgresql #redis #docker #beginners
&lt;/h1&gt;

</description>
      <category>webdev</category>
      <category>backend</category>
      <category>fastapi</category>
      <category>rapidkit</category>
    </item>
    <item>
      <title>Build Production SaaS: Code Walkthrough</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Mon, 16 Feb 2026 08:18:49 +0000</pubDate>
      <link>https://forem.com/rapidkit/build-production-saas-code-walkthrough-4c7c</link>
      <guid>https://forem.com/rapidkit/build-production-saas-code-walkthrough-4c7c</guid>
      <description>&lt;p&gt;Most tutorials show you &lt;strong&gt;how to run&lt;/strong&gt; commands.&lt;br&gt;&lt;br&gt;
This one shows you &lt;strong&gt;how the code works&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We'll build and dissect a 4-service SaaS backend with real implementation patterns used in production.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📦 &lt;strong&gt;Get the code:&lt;/strong&gt; &lt;a href="https://github.com/getrapidkit/rapidkit-examples/tree/main/saas-starter-workspace" rel="noopener noreferrer"&gt;saas-starter-workspace&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  What We're Building
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;4 microservices with clear separation:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;saas-api&lt;/code&gt; (FastAPI) — Product API&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;saas-admin&lt;/code&gt; (FastAPI) — Admin ops&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;saas-nest&lt;/code&gt; (NestJS) — Polyglot service&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;saas-webhooks&lt;/code&gt; (FastAPI) — Billing events + replay&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Key features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dual auth (JWT + session cookies)&lt;/li&gt;
&lt;li&gt;Webhook signature verification&lt;/li&gt;
&lt;li&gt;Event replay for billing corrections&lt;/li&gt;
&lt;li&gt;DDD structure with module injection&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python3 &lt;span class="nt"&gt;--version&lt;/span&gt;  &lt;span class="c"&gt;# 3.10+&lt;/span&gt;
node &lt;span class="nt"&gt;--version&lt;/span&gt;     &lt;span class="c"&gt;# 20+&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;poetry
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; rapidkit
git clone https://github.com/getrapidkit/rapidkit-examples.git
&lt;span class="nb"&gt;cd &lt;/span&gt;rapidkit-examples/saas-starter-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  💡 Faster Setup: RapidKit VS Code Extension
&lt;/h3&gt;

&lt;p&gt;Skip manual cloning. Install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;RapidKit VS Code Extension&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you get:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clone workspaces from GitHub with one click (Welcome Page → Example Workspaces)&lt;/li&gt;
&lt;li&gt;Download &amp;amp; import workspaces directly&lt;/li&gt;
&lt;li&gt;Run/test projects from the sidebar&lt;/li&gt;
&lt;li&gt;Install modules via GUI&lt;/li&gt;
&lt;li&gt;Integrated terminal with RapidKit commands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Install:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nt"&gt;--install-extension&lt;/span&gt; rapidkit.rapidkit-vscode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open Command Palette (&lt;code&gt;Cmd/Ctrl+Shift+P&lt;/code&gt;) → &lt;strong&gt;RapidKit: Import Workspace&lt;/strong&gt; → done.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Pattern: DDD with Injection Markers
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Project structure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;saas-api/src/
├── main.py              # Entry point with injection markers
├── app/main.py          # FastAPI factory
├── routing/
│   └── saas.py          # Business logic (485 lines)
└── modules/free/        # RapidKit modules
    ├── auth/core/       # Password hashing + JWT
    ├── auth/session/    # Cookie sessions
    ├── users/users_core/
    └── security/rate_limiting/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Entry point pattern (&lt;code&gt;main.py&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@asynccontextmanager&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AsyncIterator&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="c1"&gt;# &amp;lt;&amp;lt;&amp;lt;inject:startup&amp;gt;&amp;gt;&amp;gt; — modules add startup hooks here
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt;
    &lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# &amp;lt;&amp;lt;&amp;lt;inject:shutdown&amp;gt;&amp;gt;&amp;gt; — cleanup hooks
&lt;/span&gt;        &lt;span class="k"&gt;pass&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create_app&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;saas-api&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;lifespan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# &amp;lt;&amp;lt;&amp;lt;inject:routes&amp;gt;&amp;gt;&amp;gt; — modules mount routes here
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this works:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Modules inject code at generation time&lt;/li&gt;
&lt;li&gt;Clean separation of concerns&lt;/li&gt;
&lt;li&gt;Easy to add/remove features&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Code Deep Dive 1: Authentication Flow
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Register endpoint (&lt;code&gt;routing/saas.py&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@router.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/auth/register&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;201&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RegisterRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;users_service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UsersService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_users_service&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;auth_runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AuthCoreRuntime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_auth_core_runtime&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;rate_limit_dependency&lt;/span&gt;&lt;span class="p"&gt;()),&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Hash password (PBKDF2, 100K iterations)
&lt;/span&gt;    &lt;span class="n"&gt;password_hash&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash_password&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Create user in database
&lt;/span&gt;    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;user_dto&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;UserCreateDTO&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;password_hash&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;password_hash&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;full_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;created_user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;users_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_dto&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;UserEmailConflictError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;409&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Email already registered&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Issue JWT token
&lt;/span&gt;    &lt;span class="n"&gt;token_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;created_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;created_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;access_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;issue_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 4. Create session + set cookie
&lt;/span&gt;    &lt;span class="n"&gt;session_runtime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_get_session_runtime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;session_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_session&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;created_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;_set_session_cookie&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session_runtime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;created_user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model_dump&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;access_token&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bearer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern breakdown:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;PBKDF2 hashing:&lt;/strong&gt; 100K iterations prevents brute force&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service layer:&lt;/strong&gt; Business logic isolated from HTTP&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dual auth:&lt;/strong&gt; JWT (stateless) + session (server-side validation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limiting:&lt;/strong&gt; Dependency injection pattern&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Code Deep Dive 2: Authentication Resolution
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;How we resolve users from JWT OR cookies:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_get_current_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;users_service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UsersService&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;auth_runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AuthCoreRuntime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;session_runtime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SessionRuntime&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;UserDTO&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;auth_header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;authorization&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Strategy 1: JWT Bearer Token
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;auth_header&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;auth_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;startswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bearer &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;bearer_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth_header&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;auth_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bearer_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sub&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Strategy 2: Session Cookie
&lt;/span&gt;    &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;session_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;session_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;401&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Authentication required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session_runtime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify_session_token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;session_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;

    &lt;span class="c1"&gt;# Fetch user from database
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UserDTO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_entity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;users_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why dual auth?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mobile apps → JWT (stateless, offline validation)&lt;/li&gt;
&lt;li&gt;Web browsers → Cookies (server-side revocation)&lt;/li&gt;
&lt;li&gt;Single function handles both&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Usage in protected routes:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@router.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/auth/me&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UsersService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_users_service&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AuthCoreRuntime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_auth_core_runtime&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SessionRuntime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_get_session_runtime&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_get_current_user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;model_dump&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Code Deep Dive 3: Webhook Processing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Signature verification (&lt;code&gt;saas-webhooks/routing/webhooks.py&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Verify Stripe webhook signature using HMAC-SHA256.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_parse_signature_header&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="c1"&gt;# Reconstruct: "{timestamp}.{body}"
&lt;/span&gt;    &lt;span class="n"&gt;signed_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;expected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;secret&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;signed_payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="n"&gt;hashlib&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha256&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;hexdigest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Constant-time comparison (prevents timing attacks)
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;hmac&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compare_digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ingestion endpoint:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@router.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/stripe&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;202&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;receive_webhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;StripeWebhookRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;background_tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BackgroundTasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# 1. Verify signature
&lt;/span&gt;    &lt;span class="n"&gt;raw_body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stripe-signature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="nf"&gt;_verify_signature&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;WEBHOOK_SECRET&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Invalid signature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 2. Check idempotency
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;_EVENTS&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;duplicate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;event_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;# 3. Persist log
&lt;/span&gt;    &lt;span class="n"&gt;_EVENTS&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;WebhookLogEntry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;queued&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;received_at&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;_utc_now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# 4. Queue background processing
&lt;/span&gt;    &lt;span class="n"&gt;background_tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_process_event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;event_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this pattern?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Signature first → reject fakes immediately&lt;/li&gt;
&lt;li&gt;Idempotency → Stripe sends duplicates&lt;/li&gt;
&lt;li&gt;Background tasks → don't block response&lt;/li&gt;
&lt;li&gt;Logs → audit trail for billing events&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Code Deep Dive 4: Webhook Replay
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Critical for billing correctness:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@router.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/replay/{event_id}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;replay_event&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;background_tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;BackgroundTasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Reprocess failed event without calling Stripe.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_EVENTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;HTTPException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;404&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Event not found&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replay_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;replay_queued&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

    &lt;span class="c1"&gt;# Reconstruct payload from stored data
&lt;/span&gt;    &lt;span class="n"&gt;replay_payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;StripeWebhookRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;event_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Queue for processing
&lt;/span&gt;    &lt;span class="n"&gt;background_tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_process_event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;replay_payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;replay_accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;replay_count&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;replay_count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When you need replay:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handler had a bug → fix code, replay events&lt;/li&gt;
&lt;li&gt;Database was down → replay after recovery&lt;/li&gt;
&lt;li&gt;Need to backfill subscription states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Production upgrade:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;_EVENTS&lt;/code&gt; dict with PostgreSQL&lt;/li&gt;
&lt;li&gt;Add exponential backoff for retries&lt;/li&gt;
&lt;li&gt;Implement dead-letter queue&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Code Deep Dive 5: NestJS Implementation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Auth service (&lt;code&gt;saas-nest/src/auth/auth.service.ts&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;usersByEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UserRecord&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;tokens&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usersByEmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email already registered&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRecord&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`user_&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;passwordHash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;usersByEmail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;issueToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;publicUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;access_token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;token_type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bearer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;createHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sha256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;raw&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;digest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;issueToken&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;randomBytes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tokens&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Controller:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auth&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AuthController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;authService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AuthService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;register&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CONFLICT&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;me&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nf"&gt;me&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;Headers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extractBearer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;authorization&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Auth required&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;UNAUTHORIZED&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;authService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;me&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Comparison with FastAPI version:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Same flow: hash → store → issue token&lt;/li&gt;
&lt;li&gt;NestJS: TypeScript types + dependency injection&lt;/li&gt;
&lt;li&gt;FastAPI: Async/await + Pydantic validation&lt;/li&gt;
&lt;li&gt;Both: Service pattern isolates business logic&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Run the Complete System
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Terminal 1 — Product API:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;saas-api &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; poetry shell &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit dev
&lt;span class="c"&gt;# → http://127.0.0.1:8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Terminal 2 — Admin API:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;saas-admin &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; poetry shell &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit dev &lt;span class="nt"&gt;--port&lt;/span&gt; 8001
&lt;span class="c"&gt;# → http://127.0.0.1:8001&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Terminal 3 — NestJS:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;saas-nest &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit dev &lt;span class="nt"&gt;--port&lt;/span&gt; 8002
&lt;span class="c"&gt;# → http://127.0.0.1:8002&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Terminal 4 — Webhooks:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;saas-webhooks &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; poetry shell &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit dev &lt;span class="nt"&gt;--port&lt;/span&gt; 8003
&lt;span class="c"&gt;# → http://127.0.0.1:8003&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Test the Implementation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Auth flow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="c1"&gt;# Register
&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://127.0.0.1:8000/api/auth/register&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;email&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;dev@example.com&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;password&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;SecurePass123!&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;access_token&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# Get profile
&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Authorization&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Bearer &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;http://127.0.0.1:8000/api/auth/me&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Webhook flow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Send event&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8003/api/webhooks/stripe &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"id":"evt_test","type":"customer.subscription.updated","data":{}}'&lt;/span&gt;

&lt;span class="c"&gt;# View logs&lt;/span&gt;
curl http://127.0.0.1:8003/api/webhooks/logs | jq

&lt;span class="c"&gt;# Replay&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8003/api/webhooks/replay/evt_test
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Key Patterns You Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Injection Marker System&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# &amp;lt;&amp;lt;&amp;lt;inject:startup&amp;gt;&amp;gt;&amp;gt; — modules contribute code here
# &amp;lt;&amp;lt;&amp;lt;inject:routes&amp;gt;&amp;gt;&amp;gt; — dynamic route mounting
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Service Layer Pattern&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Controller → calls → Service → calls → Repository
# Keeps business logic testable and framework-independent
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Dependency Injection&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;service&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_service&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Depends&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_auth&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# FastAPI resolves dependencies automatically
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Background Processing&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;background_tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;process_event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;status&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;accepted&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;  &lt;span class="c1"&gt;# Immediate response
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Dual Authentication&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Check Bearer token first, fall back to session cookie
# Enables mobile (JWT) + web (session) clients
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Production Hardening
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before going live:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Replace in-memory storage:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Current: _EVENTS = {}
# Production: PostgreSQL with SQLAlchemy
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Add retry logic:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_retries&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Implement dead-letter queue:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;max_retries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;send_to_dlq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Add observability:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structured logging with request IDs&lt;/li&gt;
&lt;li&gt;APM (Sentry/DataDog)&lt;/li&gt;
&lt;li&gt;Prometheus metrics&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What You Built
&lt;/h2&gt;

&lt;p&gt;✅ &lt;strong&gt;Multi-service architecture&lt;/strong&gt; (4 services, independent scaling)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Dual authentication&lt;/strong&gt; (JWT + session cookies)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Secure webhooks&lt;/strong&gt; (signature verification + replay)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;DDD structure&lt;/strong&gt; (clean separation of concerns)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Polyglot support&lt;/strong&gt; (FastAPI + NestJS coexist)&lt;br&gt;&lt;br&gt;
✅ &lt;strong&gt;Production patterns&lt;/strong&gt; (background tasks, rate limiting, error handling)  &lt;/p&gt;

&lt;p&gt;This is the foundation real SaaS companies use to process millions in ARR.&lt;/p&gt;




&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;Want &lt;strong&gt;Part 2 - Production Deployment&lt;/strong&gt;?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose orchestration&lt;/li&gt;
&lt;li&gt;PostgreSQL + Redis setup&lt;/li&gt;
&lt;li&gt;CI/CD with GitHub Actions&lt;/li&gt;
&lt;li&gt;Kubernetes manifests&lt;/li&gt;
&lt;li&gt;Secrets management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Drop a comment if interested 👇&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/getrapidkit/rapidkit-examples/tree/main/saas-starter-workspace" rel="noopener noreferrer"&gt;Example Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;RapidKit VS Code Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://getrapidkit.com/docs" rel="noopener noreferrer"&gt;RapidKit Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fastapi.tiangolo.com" rel="noopener noreferrer"&gt;FastAPI Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.nestjs.com" rel="noopener noreferrer"&gt;NestJS Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Found this useful? Follow for more production engineering patterns.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>microservices</category>
      <category>saas</category>
      <category>rapidkit</category>
    </item>
    <item>
      <title>The Hidden Cost of Backend Boilerplate (And How to Eliminate It)</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Sun, 15 Feb 2026 07:39:17 +0000</pubDate>
      <link>https://forem.com/rapidkit/the-hidden-cost-of-backend-boilerplate-and-how-to-eliminate-it-4c01</link>
      <guid>https://forem.com/rapidkit/the-hidden-cost-of-backend-boilerplate-and-how-to-eliminate-it-4c01</guid>
      <description>&lt;h2&gt;
  
  
  Everyone Counts the Same Cost
&lt;/h2&gt;

&lt;p&gt;Ask any backend developer:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"How long to start a new API project?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Answer:&lt;br&gt;
&lt;em&gt;"30 minutes with a template."&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;em&gt;"A few hours from scratch."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But that's not the real cost.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's just &lt;strong&gt;Day 1&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Real Cost Shows Up Later
&lt;/h2&gt;

&lt;p&gt;Let me show you what actually happens.&lt;/p&gt;


&lt;h2&gt;
  
  
  Week 1: The Setup
&lt;/h2&gt;

&lt;p&gt;You start a new FastAPI project.&lt;/p&gt;

&lt;p&gt;You copy your "starter template":&lt;br&gt;
• Project structure&lt;br&gt;
• Docker configs&lt;br&gt;
• CI/CD workflows&lt;br&gt;
• Auth boilerplate&lt;br&gt;
• Database setup&lt;br&gt;
• Logging config&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time:&lt;/strong&gt; 2 hours (not bad!)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you don't notice:&lt;/strong&gt;&lt;br&gt;
• JWT v1 from 6 months ago (now there's v2)&lt;br&gt;
• Database pool settings from different project&lt;br&gt;
• Logging format doesn't match team's new standard&lt;br&gt;
• Docker compose has hardcoded values from old project&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost so far:&lt;/strong&gt; 2 hours + unknown future bugs&lt;/p&gt;


&lt;h2&gt;
  
  
  Week 3: The Divergence
&lt;/h2&gt;

&lt;p&gt;Your teammate starts another project.&lt;/p&gt;

&lt;p&gt;They &lt;strong&gt;copy YOUR template&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But make "improvements":&lt;br&gt;
• Different folder structure (&lt;code&gt;src/&lt;/code&gt; vs &lt;code&gt;app/&lt;/code&gt;)&lt;br&gt;
• Different error handling&lt;br&gt;
• Different env variable naming&lt;br&gt;
• Updated packages (breaking changes!)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now you have &lt;strong&gt;two projects that look similar but work differently&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;When you fix a bug in Project A, do you remember to fix it in Project B?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; Code duplication + inconsistency tax&lt;/p&gt;


&lt;h2&gt;
  
  
  Month 2: The Onboarding
&lt;/h2&gt;

&lt;p&gt;A new developer joins.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You:&lt;/strong&gt; "Just look at user-api to understand our structure."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New Dev:&lt;/strong&gt; &lt;em&gt;(Looks at user-api, then payment-api)&lt;/em&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;New Dev:&lt;/strong&gt; "These structure auth differently. Which is correct?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You:&lt;/strong&gt; "Uh... let me check."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; Confusion + lost productivity + rework&lt;/p&gt;


&lt;h2&gt;
  
  
  Month 4: The Maintenance Nightmare
&lt;/h2&gt;

&lt;p&gt;You discover a security issue in auth logic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Question:&lt;/strong&gt; Which projects have this issue?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Answer:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Search codebase (30 minutes)&lt;/li&gt;
&lt;li&gt;Find 6 projects with copied auth&lt;/li&gt;
&lt;li&gt;Each has slightly different implementation&lt;/li&gt;
&lt;li&gt;Fix takes 4 hours (not 30 minutes)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; 4+ hours + risk you missed one&lt;/p&gt;


&lt;h2&gt;
  
  
  Month 6: The "Which Version?" Problem
&lt;/h2&gt;

&lt;p&gt;You have 8 APIs now:&lt;br&gt;
• 3 use Pydantic v1&lt;br&gt;
• 4 use Pydantic v2&lt;br&gt;
• 1 nobody knows&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Templates capture a &lt;strong&gt;snapshot in time&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;They don't evolve.&lt;/p&gt;

&lt;p&gt;Each copy drifts further from the source.&lt;/p&gt;


&lt;h2&gt;
  
  
  The Hidden Costs (Quantified)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Setup cost&lt;/strong&gt; (what you measure):&lt;br&gt;
• Template: 2 hours&lt;br&gt;
• From scratch: 6 hours&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Drift cost&lt;/strong&gt; (what you miss):&lt;br&gt;
• Fixing bugs across 8 copies: 4 hours × 8 = 32 hours&lt;br&gt;
• Onboarding confusion: 2 hours per developer × 5 devs = 10 hours&lt;br&gt;
• "Which version?" debugging: 6 hours&lt;br&gt;
• Architectural inconsistency: Ongoing pain&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real cost:&lt;/strong&gt;&lt;br&gt;
• Initial: 2 hours&lt;br&gt;
• Ongoing: 48+ hours over 6 months&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;That's 24× the initial cost.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Problem Isn't Templates
&lt;/h2&gt;

&lt;p&gt;Templates are great for:&lt;br&gt;
• UI components&lt;br&gt;
• Boilerplate-free tools (like Swagger)&lt;br&gt;
• One-time setups&lt;/p&gt;

&lt;p&gt;Templates fail for:&lt;br&gt;
• Evolving codebases&lt;br&gt;
• Team consistency&lt;br&gt;
• Bug fixes and updates&lt;br&gt;
• Architectural standards&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Because once you copy a template, you're on your own.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What If You Could Eliminate Drift?
&lt;/h2&gt;

&lt;p&gt;Imagine:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a project&lt;/li&gt;
&lt;li&gt;A bug is found in auth logic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One command updates all projects&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;No searching, no manual fixes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is what &lt;strong&gt;RapidKit modules&lt;/strong&gt; solve.&lt;/p&gt;


&lt;h2&gt;
  
  
  How RapidKit Changes This
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Traditional approach:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Copy template&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; starter-template/ new-api/
&lt;span class="nb"&gt;cd &lt;/span&gt;new-api

&lt;span class="c"&gt;# Modify everything&lt;/span&gt;
&lt;span class="c"&gt;# (Hope you remember what to change)&lt;/span&gt;

&lt;span class="c"&gt;# 6 months later: bug found in auth&lt;/span&gt;
&lt;span class="c"&gt;# Fix manually in 8 projects&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;RapidKit approach:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create project&lt;/span&gt;
rapidkit create project fastapi.standard new-api
&lt;span class="nb"&gt;cd &lt;/span&gt;new-api

&lt;span class="c"&gt;# Add modules&lt;/span&gt;
rapidkit add module auth_core
rapidkit add module db_postgres
rapidkit add module logging

&lt;span class="c"&gt;# 6 months later: auth bug fixed in module&lt;/span&gt;
rapidkit upgrade
&lt;span class="c"&gt;# ↳ Fixed across all projects&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Difference: Managed vs Copied
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Templates:&lt;/strong&gt;&lt;br&gt;
• Copied code&lt;br&gt;
• No connection to source&lt;br&gt;
• Manual updates&lt;br&gt;
• Drift inevitable&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RapidKit Modules:&lt;/strong&gt;&lt;br&gt;
• Versioned modules&lt;br&gt;
• Tracked installations&lt;br&gt;
• Automatic updates&lt;br&gt;
• Consistency enforced&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Think:&lt;/strong&gt;&lt;br&gt;
• Templates = copy-paste code&lt;br&gt;
• Modules = npm packages for backend&lt;/p&gt;


&lt;h2&gt;
  
  
  Real Example: Auth Bug Fix
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; Security vulnerability in JWT validation&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Template approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify affected projects (30 min)&lt;/li&gt;
&lt;li&gt;Fix project 1 (30 min)&lt;/li&gt;
&lt;li&gt;Fix project 2 (30 min)&lt;/li&gt;
&lt;li&gt;Fix project 3 (30 min)&lt;/li&gt;
&lt;li&gt;...repeat for 8 projects&lt;/li&gt;
&lt;li&gt;Test each (2 hours)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Total:&lt;/strong&gt; 6+ hours&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;RapidKit approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fix auth_core module&lt;/li&gt;
&lt;li&gt;Release v0.1.5&lt;/li&gt;
&lt;li&gt;Run in each project:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   rapidkit upgrade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Module updates automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Total:&lt;/strong&gt; 30 minutes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Saved:&lt;/strong&gt; 5.5 hours (per bug!)&lt;/p&gt;


&lt;h2&gt;
  
  
  The Compounding Effect
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;After 1 year:&lt;/strong&gt;&lt;br&gt;
• 12 bug fixes in shared modules&lt;br&gt;
• 5.5 hours saved × 12 = &lt;strong&gt;66 hours saved&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After 2 years:&lt;/strong&gt;&lt;br&gt;
• 24 bug fixes&lt;br&gt;
• &lt;strong&gt;132 hours saved&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plus:&lt;/strong&gt;&lt;br&gt;
• Zero onboarding confusion&lt;br&gt;
• Zero "which version?" problems&lt;br&gt;
• Zero architectural drift&lt;/p&gt;


&lt;h2&gt;
  
  
  But Isn't This Lock-In?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;RapidKit generates &lt;strong&gt;standard FastAPI/NestJS code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You can:&lt;br&gt;
• Modify any file&lt;br&gt;
• Remove RapidKit entirely&lt;br&gt;
• Continue without it&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You own the code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;RapidKit just &lt;strong&gt;manages the boring parts&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  What About Customization?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Templates:&lt;/strong&gt; Everything is customizable (because everything is yours)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RapidKit:&lt;/strong&gt; Everything is customizable too:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Modify generated code&lt;/li&gt;
&lt;li&gt;RapidKit tracks your changes&lt;/li&gt;
&lt;li&gt;When upgrading, it:
• Shows diffs
• Preserves your customizations
• Merges updates safely&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Best of both worlds:&lt;/strong&gt;&lt;br&gt;
• Evolution without drift&lt;br&gt;
• Customization without chaos&lt;/p&gt;


&lt;h2&gt;
  
  
  The Mental Model Shift
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Old way:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;"Copy this template and make it yours."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;New way:&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;"Install these modules and add your features."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Old way:&lt;/strong&gt; Start by &lt;strong&gt;deleting/modifying&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;New way:&lt;/strong&gt; Start by &lt;strong&gt;building features&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create two projects with templates:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Project 1&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; template/ api-1/
&lt;span class="nb"&gt;cd &lt;/span&gt;api-1
&lt;span class="c"&gt;# Spend 2 hours customizing&lt;/span&gt;

&lt;span class="c"&gt;# Project 2&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; template/ api-2/
&lt;span class="nb"&gt;cd &lt;/span&gt;api-2
&lt;span class="c"&gt;# Spend 2 hours customizing&lt;/span&gt;

&lt;span class="c"&gt;# 3 months later: find a bug in template&lt;/span&gt;
&lt;span class="c"&gt;# Now fix it manually in both&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create two projects with RapidKit:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Project 1&lt;/span&gt;
rapidkit create project fastapi.standard api-1
&lt;span class="nb"&gt;cd &lt;/span&gt;api-1
rapidkit add module auth_core db_postgres

&lt;span class="c"&gt;# Project 2&lt;/span&gt;
rapidkit create project fastapi.standard api-2
&lt;span class="nb"&gt;cd &lt;/span&gt;api-2
rapidkit add module auth_core db_postgres

&lt;span class="c"&gt;# 3 months later: bug fixed in auth_core&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;api-1 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit upgrade
&lt;span class="nb"&gt;cd &lt;/span&gt;api-2 &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit upgrade
&lt;span class="c"&gt;# Done.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Real Cost of Boilerplate
&lt;/h2&gt;

&lt;p&gt;It's not the initial setup time.&lt;/p&gt;

&lt;p&gt;It's:&lt;br&gt;
• &lt;strong&gt;Drift&lt;/strong&gt; (projects become inconsistent)&lt;br&gt;
• &lt;strong&gt;Duplication&lt;/strong&gt; (fix same bugs multiple times)&lt;br&gt;
• &lt;strong&gt;Confusion&lt;/strong&gt; (teammates don't know which is canonical)&lt;br&gt;
• &lt;strong&gt;Maintenance&lt;/strong&gt; (updates take forever)&lt;br&gt;
• &lt;strong&gt;Onboarding&lt;/strong&gt; (new devs lost in inconsistency)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RapidKit eliminates all of these.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Next article: &lt;strong&gt;"Your First FastAPI Project with RapidKit"&lt;/strong&gt; — a complete tutorial building a real API.&lt;/p&gt;




&lt;h3&gt;
  
  
  Learn More
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;a href="https://www.getrapidkit.com" rel="noopener noreferrer"&gt;getrapidkit.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;a href="https://www.npmjs.com/package/rapidkit" rel="noopener noreferrer"&gt;npm: rapidkit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐍 &lt;a href="https://pypi.org/project/rapidkit-core/" rel="noopener noreferrer"&gt;PyPI: rapidkit-core&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧩 &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;VS Code Extension&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Stop copying templates.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start managing modules.&lt;/p&gt;

</description>
      <category>rapidkit</category>
      <category>backend</category>
      <category>productivity</category>
      <category>architecture</category>
    </item>
    <item>
      <title>From Zero to Production API in 5 Minutes</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Sat, 14 Feb 2026 20:04:33 +0000</pubDate>
      <link>https://forem.com/rapidkit/from-zero-to-production-api-in-5-minutes-2ehl</link>
      <guid>https://forem.com/rapidkit/from-zero-to-production-api-in-5-minutes-2ehl</guid>
      <description>&lt;h2&gt;
  
  
  Let's Stop Talking. Let's Build.
&lt;/h2&gt;

&lt;p&gt;Enough theory. We're building a &lt;strong&gt;real, production-ready FastAPI project&lt;/strong&gt; from absolute zero.&lt;/p&gt;

&lt;p&gt;Not a toy example. Not a template.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timer starts now.&lt;/strong&gt; ⏱️&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;Source Code:&lt;/strong&gt; &lt;a href="https://github.com/getrapidkit/rapidkit-examples/tree/main/quickstart-workspace" rel="noopener noreferrer"&gt;github.com/getrapidkit/rapidkit-examples/tree/main/quickstart-workspace&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Minute 0:00 — Prerequisites Check
&lt;/h2&gt;

&lt;p&gt;You need:&lt;br&gt;
• Node.js 20+&lt;br&gt;
• Python 3.10+&lt;br&gt;
• 5 minutes&lt;/p&gt;

&lt;p&gt;That's it.&lt;/p&gt;

&lt;p&gt;RapidKit handles:&lt;br&gt;
• Poetry (auto-installed)&lt;br&gt;
• Docker (configs provided)&lt;br&gt;
• Dependencies (auto-managed)&lt;/p&gt;


&lt;h2&gt;
  
  
  Minute 0:30 — Create the Workspace
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Workspace-based approach&lt;/strong&gt; (recommended for multiple projects):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit quickstart-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;quickstart-workspace
npx rapidkit create project fastapi.standard product-api
&lt;span class="nb"&gt;cd &lt;/span&gt;product-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you get:&lt;/strong&gt;&lt;br&gt;
• Clean &lt;code&gt;src/&lt;/code&gt; architecture&lt;br&gt;
• Health check endpoint&lt;br&gt;
• Docker &amp;amp; docker-compose ready&lt;br&gt;
• CI/CD templates (GitHub Actions)&lt;br&gt;
• Testing setup (pytest)&lt;br&gt;
• Environment management (&lt;code&gt;.env.example&lt;/code&gt;)&lt;br&gt;
• Makefile for common tasks&lt;br&gt;
• Shared &lt;code&gt;.venv&lt;/code&gt; for all workspace projects&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Generated code&lt;/strong&gt;, not templates.&lt;/p&gt;


&lt;h2&gt;
  
  
  Minute 1:00 — Install Dependencies
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Activate workspace environment&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .rapidkit/activate

&lt;span class="c"&gt;# Initialize project&lt;/span&gt;
rapidkit init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Detects workspace environment&lt;/li&gt;
&lt;li&gt;Installs Poetry (if needed)&lt;/li&gt;
&lt;li&gt;Uses shared workspace &lt;code&gt;.venv/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Installs all project dependencies&lt;/li&gt;
&lt;li&gt;Sets up pre-commit hooks&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Poetry detected
✓ Using workspace virtualenv
✓ Installing dependencies
✓ Project ready!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Minute 1:30 — First Run
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO: Uvicorn running on http://127.0.0.1:8000
INFO: Application startup complete.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Open browser:&lt;/strong&gt; &lt;a href="http://localhost:8000/docs" rel="noopener noreferrer"&gt;http://localhost:8000/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You see &lt;strong&gt;Swagger UI&lt;/strong&gt; with health endpoints:&lt;br&gt;
• &lt;code&gt;GET /health&lt;/code&gt; — Overall health check&lt;br&gt;
• &lt;code&gt;GET /api/health/livez&lt;/code&gt; — Liveness probe&lt;br&gt;
• &lt;code&gt;GET /api/health/readyz&lt;/code&gt; — Readiness probe&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Your API is running.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Minute 2:00 — Add Essential Modules
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module settings
rapidkit add module auth_core  
rapidkit add module logging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Settings module:&lt;/strong&gt;&lt;br&gt;
• Multi-source config (&lt;code&gt;.env&lt;/code&gt;, env vars, YAML)&lt;br&gt;
• Type-safe with Pydantic&lt;br&gt;
• Environment-specific overrides&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Auth Core module:&lt;/strong&gt;&lt;br&gt;
• PBKDF2 password hashing&lt;br&gt;
• HMAC token signing&lt;br&gt;
• Secure credential management&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Logging module:&lt;/strong&gt;&lt;br&gt;
• Structured JSON logs&lt;br&gt;
• Request/correlation tracking&lt;br&gt;
• Configurable log levels&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check health endpoints:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"healthy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-02-14T..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"modules"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"auth_core"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"healthy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"settings"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"healthy"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Minute 2:30 — Add Database
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module db_postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What you get:&lt;/strong&gt;&lt;br&gt;
• Async &amp;amp; sync SQLAlchemy engines&lt;br&gt;
• Connection pooling with configurable limits&lt;br&gt;
• Health checks with connection testing&lt;br&gt;
• Alembic migrations ready&lt;br&gt;
• Docker Compose with Postgres service&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Environment configured in &lt;code&gt;.env&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;RAPIDKIT_DB_POSTGRES_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgresql://postgres:postgres@localhost:5432/app_db
&lt;span class="nv"&gt;RAPIDKIT_DB_POSTGRES_TEST_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;postgresql://postgres:postgres@localhost:5433/app_db_test
&lt;span class="nv"&gt;RAPIDKIT_DB_POSTGRES_POOL_SIZE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10
&lt;span class="nv"&gt;RAPIDKIT_DB_POSTGRES_MAX_OVERFLOW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;20
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Start database:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker-compose up &lt;span class="nt"&gt;-d&lt;/span&gt; postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check health:&lt;/strong&gt;&lt;br&gt;
&lt;a href="http://localhost:8000/api/health/module/postgres" rel="noopener noreferrer"&gt;http://localhost:8000/api/health/module/postgres&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
---

## Minute 3:00 — Add Redis Caching

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
rapidkit add module redis&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Redis features:**
• Async Redis client with connection pooling
• Automatic retry logic with exponential backoff
• Health monitoring with connection testing
• Configurable TTL and preconnection

**Environment configured in `.env`:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
REDIS_URL=redis://localhost:6379/0&lt;br&gt;
REDIS_HOST=localhost&lt;br&gt;
REDIS_PORT=6379&lt;br&gt;
REDIS_DB=0&lt;br&gt;
CACHE_TTL=3600&lt;br&gt;
REDIS_CONNECT_RETRIES=3&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Start Redis:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
docker-compose up -d redis&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Check health:**
http://localhost:8000/api/health/module/redis

---

## Minute 3:30 — Add Security &amp;amp; Middleware

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
rapidkit add module cors&lt;br&gt;
rapidkit add module security_headers&lt;br&gt;
rapidkit add module middleware&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**CORS:**
• Whitelist origins for production
• Credential support enabled
• Preflight request handling

**Security Headers:**
• CSP, HSTS, X-Frame-Options configured
• Production-ready secure defaults

**Middleware:**
• Request ID tracking
• Response time recording
• Custom middleware support

**Your API now has enterprise-grade security.**

---

## Minute 4:00 — Add Deployment Config

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
rapidkit add module deployment&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Deployment features:**
• Production-ready Dockerfile (multi-stage builds)
• Docker Compose with all services
• GitHub Actions CI/CD workflows
• Makefile with common tasks
• Health check integration
• Environment-based configuration

---

## Minute 4:30 — Run Tests

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
rapidkit test&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;===== test session starts =====&lt;br&gt;
collected 15 items&lt;/p&gt;

&lt;p&gt;tests/test_health.py ✓✓✓✓&lt;br&gt;
tests/test_auth_core.py ✓✓✓&lt;br&gt;
tests/test_db.py ✓✓✓✓&lt;br&gt;
tests/test_redis.py ✓✓&lt;br&gt;
tests/test_integration.py ✓✓&lt;/p&gt;

&lt;p&gt;===== 15 passed in 3.2s =====&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**All modules have tests included automatically.**

---

## Minute 5:00 — Deploy

**Using Makefile commands:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;/p&gt;
&lt;h1&gt;
  
  
  Build Docker image
&lt;/h1&gt;

&lt;p&gt;make docker-build&lt;/p&gt;
&lt;h1&gt;
  
  
  Run with docker-compose (all services)
&lt;/h1&gt;

&lt;p&gt;make docker-up&lt;/p&gt;
&lt;h1&gt;
  
  
  Or manual Docker build
&lt;/h1&gt;

&lt;p&gt;docker build -t product-api .&lt;br&gt;
docker run -p 8000:8000 --env-file .env product-api&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Production deployment:**
• GitHub Actions workflows (auto-generated by deployment module)
• Multi-stage Dockerfile (optimized for production)
• Docker Compose with all services
• Health checks integrated
• Environment-based configuration

**Your API is production-ready.**

---

## ⏱️ Timer: 5:00

**What you built:**
✅ Workspace-based FastAPI project with clean architecture  
✅ JWT Authentication (register, login, refresh)  
✅ Database (PostgreSQL with async + sync engines)  
✅ Caching (Redis with retry logic)  
✅ Security (CORS + security headers)  
✅ Middleware (request tracking)  
✅ Logging (structured JSON with correlation IDs)  
✅ Configuration (multi-source with type safety)  
✅ Tests (passing with 15 test cases)  
✅ Docker (production-ready multi-stage builds)  
✅ CI/CD (GitHub Actions workflows)

**Lines of code written by you:** ~60 (configs)  
**Lines of code generated:** ~2,500+

---

## Project Structure

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;quickstart-workspace/&lt;br&gt;
├── .rapidkit/&lt;br&gt;
│   ├── activate                 # Workspace activation script&lt;br&gt;
│   └── .venv/                   # Shared virtual environment&lt;br&gt;
├── product-api/&lt;br&gt;
│   ├── src/&lt;br&gt;
│   │   ├── main.py              # FastAPI app entrypoint&lt;br&gt;
│   │   ├── cli.py               # CLI commands&lt;br&gt;
│   │   ├── health/              # Health check routes&lt;br&gt;
│   │   ├── routing/             # API routes&lt;br&gt;
│   │   └── modules/             # Installed modules&lt;br&gt;
│   │       ├── settings/&lt;br&gt;
│   │       ├── auth_core/&lt;br&gt;
│   │       ├── db_postgres/&lt;br&gt;
│   │       ├── redis/&lt;br&gt;
│   │       ├── cors/&lt;br&gt;
│   │       ├── security_headers/&lt;br&gt;
│   │       ├── logging/&lt;br&gt;
│   │       ├── deployment/&lt;br&gt;
│   │       └── middleware/&lt;br&gt;
│   ├── tests/                   # Tests for all modules&lt;br&gt;
│   ├── docker-compose.yml       # Postgres + Redis services&lt;br&gt;
│   ├── Dockerfile               # Production multi-stage image&lt;br&gt;
│   ├── pyproject.toml           # Project dependencies&lt;br&gt;
│   ├── .env.example             # Environment template&lt;br&gt;
│   └── Makefile                 # Common development tasks&lt;br&gt;
└── README.md                    # Workspace documentation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Every module:**
• Has its own directory
• Brings tests
• Updates health endpoint
• Configurable via `.env`

---

## What Makes This Different?

**Templates give you:**
• Example files
• You modify everything
• No upgrade path

**RapidKit gives you:**
• Production code
• Working integrations
• Upgradable modules
• Health checks included
• Tests included

**Key difference:**

Templates = **delete and modify**  
RapidKit = **add and build**

---

## Next Steps

**Add more features:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;/p&gt;
&lt;h1&gt;
  
  
  Email sending
&lt;/h1&gt;

&lt;p&gt;rapidkit add module email&lt;/p&gt;
&lt;h1&gt;
  
  
  Background tasks
&lt;/h1&gt;

&lt;p&gt;rapidkit add module celery&lt;/p&gt;
&lt;h1&gt;
  
  
  File storage
&lt;/h1&gt;

&lt;p&gt;rapidkit add module storage&lt;/p&gt;
&lt;h1&gt;
  
  
  Observability
&lt;/h1&gt;

&lt;p&gt;rapidkit add module observability_core&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Each module integrates cleanly** — working together seamlessly.

---

## Troubleshooting: Health Check

**Something not working?**

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
npx rapidkit doctor&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Checks:**
• Python version
• Poetry installation
• RapidKit Core version
• Dependencies status

**Example output:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Python: Python 3.10.19&lt;br&gt;
✅ Poetry: Poetry 2.3.2&lt;br&gt;
✅ pipx: pipx 1.8.0&lt;br&gt;
✅ RapidKit Core: RapidKit Core 0.3.2&lt;br&gt;
   • Global (pipx): /home/user/.local/bin/rapidkit -&amp;gt; 0.3.2&lt;/p&gt;

&lt;p&gt;✅ All required tools are installed!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Instant diagnosis.** For detailed project checks, use `rapidkit doctor --workspace`.

---

## Try It Yourself

**Clone the example:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
git clone &lt;a href="https://github.com/getrapidkit/rapidkit-examples.git" rel="noopener noreferrer"&gt;https://github.com/getrapidkit/rapidkit-examples.git&lt;/a&gt;&lt;br&gt;
cd rapidkit-examples/quickstart-workspace/product-api&lt;br&gt;
source ../.rapidkit/activate&lt;br&gt;
rapidkit init&lt;br&gt;
rapidkit dev&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
**Or create from scratch:**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
bash&lt;br&gt;
time npx rapidkit create workspace my-workspace&lt;br&gt;
cd my-workspace&lt;br&gt;
time npx rapidkit create project fastapi.standard my-api&lt;br&gt;
cd my-api&lt;br&gt;
source ../.rapidkit/activate&lt;br&gt;
time rapidkit init&lt;br&gt;
time rapidkit dev&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


**Challenge:** Can you beat 5 minutes?

---

## FAQs

**Q: Is this production-ready?**  
Yes. Companies use generated projects in production.

**Q: Can I customize the code?**  
Yes. It's your code. Modify anything. RapidKit tracks changes and helps merge updates.

**Q: What if I add a module later?**  
RapidKit integrates it cleanly, preserving your custom code.

**Q: Do I need to learn RapidKit patterns?**  
No. It's **standard FastAPI code**. If you know FastAPI, you know this code.

---

## What's Next?

Next article: **"The Hidden Cost of Backend Boilerplate"** — why "just use a template" isn't good enough.

---

### Learn More

* 🌐 [getrapidkit.com](https://www.getrapidkit.com)
* 📦 [npm: rapidkit](https://www.npmjs.com/package/rapidkit)
* 🐍 [PyPI: rapidkit-core](https://pypi.org/project/rapidkit-core/)
* 🧩 [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode)
* 📂 [GitHub: rapidkit-examples](https://github.com/getrapidkit/rapidkit-examples)

---

**You just built a production-ready API in 5 minutes.**

Now go ship something.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

</description>
      <category>rapidkit</category>
      <category>quickstart</category>
      <category>python</category>
      <category>fastapi</category>
    </item>
    <item>
      <title>Workspace-First Development: Why It Changes Everything</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Sat, 14 Feb 2026 18:57:40 +0000</pubDate>
      <link>https://forem.com/rapidkit/workspace-first-development-why-it-changes-everything-565f</link>
      <guid>https://forem.com/rapidkit/workspace-first-development-why-it-changes-everything-565f</guid>
      <description>&lt;h3&gt;
  
  
  The Problem Nobody Talks About
&lt;/h3&gt;

&lt;p&gt;You're building a modern backend. Not one API. &lt;strong&gt;Several:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication service&lt;/li&gt;
&lt;li&gt;User management API&lt;/li&gt;
&lt;li&gt;Payment gateway&lt;/li&gt;
&lt;li&gt;Notification service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Microservices done right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Then why does it feel so painful?&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  The Hidden Tax of Multiple Services
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Day 1:&lt;/strong&gt; Create first service (3 hours)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Day 3:&lt;/strong&gt; Copy-paste for second service → already diverging&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Week 2:&lt;/strong&gt; 4 services with different structures&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Month 2:&lt;/strong&gt; New developer: "Which service is the reference?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The real problems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4 separate virtualenvs (600MB each = 2.4GB)&lt;/li&gt;
&lt;li&gt;Inconsistent structure across services&lt;/li&gt;
&lt;li&gt;Version conflicts (Pydantic v1 or v2?)&lt;/li&gt;
&lt;li&gt;20-step onboarding guide&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This is what workspaces solve.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What Is a Workspace?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;shared environment&lt;/strong&gt; for multiple backend projects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-workspace/
├── .venv/                     # Shared Python env
├── auth-service/              # FastAPI
├── user-api/                  # FastAPI
├── payment-gateway/           # NestJS
└── notification-service/      # FastAPI
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Create it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add projects:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit create project fastapi.standard auth-service
rapidkit create project nestjs.standard payment-gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One Python environment for all projects&lt;/li&gt;
&lt;li&gt;Consistent structure&lt;/li&gt;
&lt;li&gt;One CLI for everything&lt;/li&gt;
&lt;li&gt;Auto-tracked registry&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Why This Matters: Real Numbers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Traditional Approach (4 services):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup: 3 hours × 4 = 12 hours&lt;/li&gt;
&lt;li&gt;Disk: 600MB × 4 = 2.4GB&lt;/li&gt;
&lt;li&gt;Onboarding: 4-6 hours reading docs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workspace Approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup: 5 minutes (workspace) + 2 minutes × 4 = 13 minutes&lt;/li&gt;
&lt;li&gt;Disk: 150MB (shared) + 400MB (projects) = 550MB&lt;/li&gt;
&lt;li&gt;Onboarding: 2 minutes (clone + &lt;code&gt;./bootstrap.sh&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Workspace saves you: 77% time, 77% disk space&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  How It Works: The Magic of Shared Environments
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create workspace:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Behind the scenes:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creates &lt;code&gt;.rapidkit-workspace&lt;/code&gt; marker&lt;/li&gt;
&lt;li&gt;Installs Poetry&lt;/li&gt;
&lt;li&gt;Creates shared &lt;code&gt;.venv/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Installs &lt;code&gt;rapidkit-core&lt;/code&gt; (the Python engine)&lt;/li&gt;
&lt;li&gt;Registers workspace in &lt;code&gt;~/.rapidkit/workspaces.json&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Add projects:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit create project fastapi.standard api-one
rapidkit create project nestjs.standard api-two
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Each project gets:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Own &lt;code&gt;.venv/&lt;/code&gt; for project dependencies (~100MB)&lt;/li&gt;
&lt;li&gt;Access to workspace's rapidkit-core&lt;/li&gt;
&lt;li&gt;Consistent structure&lt;/li&gt;
&lt;li&gt;Independent configs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Command routing:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Inside workspace:&lt;/span&gt;
rapidkit &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;span class="c"&gt;# ↳ Uses workspace .venv/bin/rapidkit&lt;/span&gt;

&lt;span class="c"&gt;# Inside project:&lt;/span&gt;
rapidkit dev
&lt;span class="c"&gt;# ↳ Launches project's FastAPI/NestJS server&lt;/span&gt;

&lt;span class="c"&gt;# Outside workspace:&lt;/span&gt;
npx rapidkit dev
&lt;span class="c"&gt;# ↳ Uses npm bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Three Ways to Start
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1️⃣ Workspace (Recommended)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace
rapidkit create project fastapi.standard api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Auto prerequisites, multi-project, disk efficient&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Use when:&lt;/strong&gt; 2+ projects, team development, production&lt;/p&gt;


&lt;h3&gt;
  
  
  2️⃣ Direct Project
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit create project fastapi.standard api
&lt;span class="nb"&gt;cd &lt;/span&gt;api
npx rapidkit init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Fastest for single project&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Use when:&lt;/strong&gt; Quick prototype, learning&lt;/p&gt;


&lt;h3&gt;
  
  
  3️⃣ VS Code Extension
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install extension&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl+Shift+P&lt;/code&gt; → "RapidKit: Create Workspace"&lt;/li&gt;
&lt;li&gt;Visual project creation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; GUI, visual discovery&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Use when:&lt;/strong&gt; New to RapidKit, team onboarding&lt;/p&gt;


&lt;h2&gt;
  
  
  💾 Export Your Workspace: Share &amp;amp; Backup
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Export:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit workspace &lt;span class="nb"&gt;export&lt;/span&gt;
&lt;span class="c"&gt;# or: Right-click workspace in VS Code → Export&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; ZIP file (1-10MB) with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All projects + configs&lt;/li&gt;
&lt;li&gt;Poetry lockfile&lt;/li&gt;
&lt;li&gt;Smart exclusions (no &lt;code&gt;node_modules&lt;/code&gt;, &lt;code&gt;.venv&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Import:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Extract ZIP&lt;/span&gt;
./bootstrap.sh
&lt;span class="c"&gt;# Done in 2 minutes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Use cases:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Team onboarding:&lt;/strong&gt; Share entire backend in one file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Disaster recovery:&lt;/strong&gt; Restore from backup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Experimentation:&lt;/strong&gt; Export before refactor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Traditional onboarding:&lt;/strong&gt; 4+ hours&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Workspace import:&lt;/strong&gt; 2 minutes ✅&lt;/p&gt;


&lt;h2&gt;
  
  
  🩺 Workspace Health &amp;amp; Upgrades
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Check health:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit doctor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✅ Python 3.11.5
✅ Poetry 1.7.0
✅ RapidKit Core v0.11.0
✅ 4 projects registered
⚠️  auth-service: missing dependencies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Check updates:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit check updates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VS Code shows &lt;strong&gt;orange "Upgrade Available"&lt;/strong&gt; button when new version is released.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real Example: SaaS Backend
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create workspace:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit saas-backend
&lt;span class="nb"&gt;cd &lt;/span&gt;saas-backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add services:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit create project fastapi.ddd auth-service
rapidkit create project nestjs.standard api-gateway
rapidkit create project fastapi.standard jobs-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;VS Code sidebar:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📁 SaaS Backend
 ├── 🐍 auth-service
 ├── 🟦 api-gateway
 └── 🐍 jobs-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;One click to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start any service&lt;/li&gt;
&lt;li&gt;Run tests&lt;/li&gt;
&lt;li&gt;Install modules&lt;/li&gt;
&lt;li&gt;Check health&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Developer Experience Benefits
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Instant Discoverability&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone company/backend-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;backend-workspace
code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;New developer sees all services, identical structure, ready to run.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Consistent Commands&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;auth-service
rapidkit dev

&lt;span class="nb"&gt;cd&lt;/span&gt; ../api-gateway
rapidkit dev      &lt;span class="c"&gt;# Same command, different framework&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Shared Updates&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;auth-service
rapidkit add module logging

&lt;span class="nb"&gt;cd&lt;/span&gt; ../api-gateway
rapidkit add module logging   &lt;span class="c"&gt;# Same version, instant&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Workspace Strategies
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Monolithic (all projects):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;company-backend/
├── auth-service/
├── user-api/
├── payment-api/
└── 10 more services/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Domain-Separated (recommended):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;company-auth/          # Workspace
├── auth-service/
└── user-api/

company-payments/      # Workspace
├── payment-api/
└── billing-service/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Hybrid:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;core-platform/         # Workspace for core services
├── auth/
├── users/
└── payments/

tools/                 # Standalone utilities
├── migration-script/
└── data-import/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  When NOT to Use Workspaces
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use standalone when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single quick prototype&lt;/li&gt;
&lt;li&gt;Learning RapidKit&lt;/li&gt;
&lt;li&gt;Unrelated projects&lt;/li&gt;
&lt;li&gt;Maximum control needed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use workspace when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2+ related projects&lt;/li&gt;
&lt;li&gt;Team development&lt;/li&gt;
&lt;li&gt;Production environments&lt;/li&gt;
&lt;li&gt;Consistent architecture matters&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Hidden Superpower: Team Onboarding
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Traditional:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone repos (4+)&lt;/li&gt;
&lt;li&gt;Read 10-page guide&lt;/li&gt;
&lt;li&gt;Install Python, Node, Docker, Poetry&lt;/li&gt;
&lt;li&gt;Create virtualenvs&lt;/li&gt;
&lt;li&gt;Configure .env files&lt;/li&gt;
&lt;li&gt;Fix dependency conflicts&lt;/li&gt;
&lt;li&gt;Debug for 2 hours&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Time:&lt;/strong&gt; 4-6 hours&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Workspace:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download ZIP&lt;/li&gt;
&lt;li&gt;Extract&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;./bootstrap.sh&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Time:&lt;/strong&gt; 2 minutes&lt;/p&gt;

&lt;p&gt;Everything works. No questions. No debugging.&lt;/p&gt;




&lt;h2&gt;
  
  
  This Changes How Teams Collaborate
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Before workspaces:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Works on my machine"&lt;/li&gt;
&lt;li&gt;Week-long onboarding&lt;/li&gt;
&lt;li&gt;Inconsistent structures&lt;/li&gt;
&lt;li&gt;Version conflicts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;With workspaces:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identical environments&lt;/li&gt;
&lt;li&gt;2-minute onboarding&lt;/li&gt;
&lt;li&gt;Enforced consistency&lt;/li&gt;
&lt;li&gt;One source of truth&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create workspace&lt;/span&gt;
npx rapidkit demo-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;demo-workspace

&lt;span class="c"&gt;# Add two projects&lt;/span&gt;
rapidkit create project fastapi.standard api-one
rapidkit create project nestjs.standard api-two

&lt;span class="c"&gt;# Open in VS Code&lt;/span&gt;
code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sidebar shows both projects&lt;/li&gt;
&lt;li&gt;Health check (pulse icon)&lt;/li&gt;
&lt;li&gt;Install modules visually&lt;/li&gt;
&lt;li&gt;See tracking in action&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Comparison: Workspace vs Direct
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Workspace&lt;/th&gt;
&lt;th&gt;Direct&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Auto&lt;/td&gt;
&lt;td&gt;⚠️ Manual&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-Project&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Excellent&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Disk Usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Efficient&lt;/td&gt;
&lt;td&gt;⚠️ Wasteful&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup Time&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;🟢 Fast&lt;/td&gt;
&lt;td&gt;🟡 Slow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team-Friendly&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;⚠️ Moderate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;🟢 Easy&lt;/td&gt;
&lt;td&gt;🟡 Medium&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2+ related projects → Workspace&lt;/li&gt;
&lt;li&gt;Single prototype → Direct&lt;/li&gt;
&lt;li&gt;Not sure? → Workspace (you can ignore it)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Next article: &lt;strong&gt;"From Zero to Production API in 5 Minutes"&lt;/strong&gt; — we build a real deployable API with timer running.&lt;/p&gt;

&lt;p&gt;After that: New AI-focused tracks (support triage, provider failover, cost control).&lt;/p&gt;




&lt;h3&gt;
  
  
  Learn More
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;a href="https://www.getrapidkit.com" rel="noopener noreferrer"&gt;getrapidkit.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;a href="https://www.npmjs.com/package/rapidkit" rel="noopener noreferrer"&gt;npm: rapidkit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐍 &lt;a href="https://pypi.org/project/rapidkit-core/" rel="noopener noreferrer"&gt;PyPI: rapidkit-core&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧩 &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;VS Code Extension&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rapidkit</category>
      <category>microservices</category>
      <category>workspace</category>
      <category>devops</category>
    </item>
    <item>
      <title>Build Your First AI Agent with NestJS + RapidKit in 10 Minutes</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Thu, 12 Feb 2026 12:16:50 +0000</pubDate>
      <link>https://forem.com/rapidkit/build-your-first-ai-agent-with-nestjs-rapidkit-in-10-minutes-38m5</link>
      <guid>https://forem.com/rapidkit/build-your-first-ai-agent-with-nestjs-rapidkit-in-10-minutes-38m5</guid>
      <description>&lt;p&gt;Adding AI features to NestJS usually takes much longer than it should.&lt;/p&gt;

&lt;p&gt;With RapidKit, you can scaffold a production-style AI assistant module in minutes.&lt;/p&gt;




&lt;h2&gt;
  
  
  What You Build
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AI assistant endpoints in NestJS&lt;/li&gt;
&lt;li&gt;Provider abstraction (&lt;code&gt;echo&lt;/code&gt; by default)&lt;/li&gt;
&lt;li&gt;Optional OpenAI provider via environment&lt;/li&gt;
&lt;li&gt;Completion + stream APIs&lt;/li&gt;
&lt;li&gt;Support ticket endpoint with urgency classification&lt;/li&gt;
&lt;li&gt;Health + Swagger visibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Source code:&lt;/strong&gt; &lt;a href="https://github.com/getrapidkit/rapidkit-examples/tree/main/my-ai-workspace/ai-agent-nest" rel="noopener noreferrer"&gt;https://github.com/getrapidkit/rapidkit-examples/tree/main/my-ai-workspace/ai-agent-nest&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 20+&lt;/li&gt;
&lt;li&gt;npm 10+&lt;/li&gt;
&lt;li&gt;Python 3.10+&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1) Create workspace and project
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-ai-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-ai-workspace
rapidkit create project nestjs.standard ai-agent-nest
&lt;span class="nb"&gt;cd &lt;/span&gt;ai-agent-nest
rapidkit init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  2) Add AI Assistant module
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit add module ai_assistant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;src/modules/free/ai/ai_assistant/ai_assistant.module.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/modules/free/ai/ai_assistant/ai_assistant.controller.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/modules/free/ai/ai_assistant/ai_assistant.service.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;src/modules/free/ai/ai_assistant/ai_assistant.validation.ts&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3) Register module in &lt;code&gt;src/modules/index.ts&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;For latest &lt;code&gt;ai_assistant&lt;/code&gt; module versions this is injected automatically.&lt;br&gt;
If you use an older generated project and routes are missing, add this entry to &lt;code&gt;optionalModules&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;registerOptionalModule&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./free/ai/ai_assistant&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;AiAssistantModule&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;ModuleRef&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4) Run app
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8013 npm run start:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or via RapidKit wrapper:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit dev &lt;span class="nt"&gt;-p&lt;/span&gt; 8013
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To auto-register OpenAI provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;your_key &lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8013 npm run start:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  5) Verify endpoints
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://127.0.0.1:8013/health
curl http://127.0.0.1:8013/ai/assistant/providers
curl http://127.0.0.1:8013/ai/assistant/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Providers response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"echo"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Completion test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8013/ai/assistant/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"prompt":"What is RapidKit?","provider":"echo"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[echo] What is RapidKit?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latencyMs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stream test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8013/ai/assistant/stream &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"prompt":"Give me a deployment checklist","provider":"echo"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cache clear:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; DELETE http://127.0.0.1:8013/ai/assistant/cache
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Support ticket parity endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8013/support/ticket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"message":"Customer cannot complete payment"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ticket_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TKT-12345"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"urgency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ai_response"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[echo] Customer cannot complete payment"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"next_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"escalate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6) Open API docs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;http://127.0.0.1:8013/docs&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why this setup is useful
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fast baseline for real backend teams&lt;/li&gt;
&lt;li&gt;Clear module boundaries for scaling&lt;/li&gt;
&lt;li&gt;Easy to swap provider strategy later&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FastAPI parity now exists in this example for the support-ticket flow and optional OpenAI path.&lt;/p&gt;

&lt;p&gt;If you want, next step is adding OpenAI provider + retry/fallback in this same NestJS codebase.&lt;/p&gt;

</description>
      <category>rapidkit</category>
      <category>ai</category>
      <category>agents</category>
      <category>nestjs</category>
    </item>
    <item>
      <title>Workspace-First Development: Why It Changes Everything</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Wed, 11 Feb 2026 20:39:31 +0000</pubDate>
      <link>https://forem.com/rapidkit/workspace-first-development-why-it-changes-everything-kal</link>
      <guid>https://forem.com/rapidkit/workspace-first-development-why-it-changes-everything-kal</guid>
      <description>&lt;h3&gt;
  
  
  The Problem Nobody Talks About
&lt;/h3&gt;

&lt;p&gt;You're building a modern backend.&lt;/p&gt;

&lt;p&gt;Not one API. Several.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An authentication service&lt;/li&gt;
&lt;li&gt;A user management API&lt;/li&gt;
&lt;li&gt;A payment gateway&lt;/li&gt;
&lt;li&gt;A notification service&lt;/li&gt;
&lt;li&gt;Maybe a few more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each service is small. Each service is focused.&lt;/p&gt;

&lt;p&gt;That's &lt;strong&gt;microservices done right&lt;/strong&gt;, right?&lt;/p&gt;

&lt;p&gt;Then why does it feel &lt;strong&gt;so painful&lt;/strong&gt;?&lt;/p&gt;




&lt;h3&gt;
  
  
  The Hidden Tax of Multiple Services
&lt;/h3&gt;

&lt;p&gt;Here's what actually happens:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Day 1:&lt;/strong&gt; Create the first service&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;30 minutes to set up the project&lt;/li&gt;
&lt;li&gt;1 hour to configure Docker and CI&lt;/li&gt;
&lt;li&gt;2 hours to wire up auth, database, logging&lt;/li&gt;
&lt;li&gt;Finally start coding features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Day 3:&lt;/strong&gt; Need a second service&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Copy the first project as a template&lt;/li&gt;
&lt;li&gt;Change names, ports, configs&lt;/li&gt;
&lt;li&gt;Fix inconsistencies from the copy-paste&lt;/li&gt;
&lt;li&gt;Realize you're already diverging from the first service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Week 2:&lt;/strong&gt; Now you have 4 services&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each has a slightly different structure&lt;/li&gt;
&lt;li&gt;Each has its own Python virtualenv (600MB each)&lt;/li&gt;
&lt;li&gt;Each has its own dependencies (and version conflicts)&lt;/li&gt;
&lt;li&gt;Each has its own way of doing logging, error handling, and config&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Month 2:&lt;/strong&gt; A new developer joins&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Which service should I look at as reference?"&lt;/li&gt;
&lt;li&gt;"Why do these three services structure models differently?"&lt;/li&gt;
&lt;li&gt;"Do we use Pydantic v1 or v2?"&lt;/li&gt;
&lt;li&gt;"Which .env file is the source of truth?"&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  This Is What "Consistency at Scale" Really Means
&lt;/h3&gt;

&lt;p&gt;It's not about code style.&lt;br&gt;
It's not about linting rules.&lt;/p&gt;

&lt;p&gt;It's about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Structure:&lt;/strong&gt; Every service follows the same architecture&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tooling:&lt;/strong&gt; One environment, one CLI, one workflow&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies:&lt;/strong&gt; Shared Python environment across all services&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Discovery:&lt;/strong&gt; Every service is automatically tracked and accessible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is what &lt;strong&gt;RapidKit Workspaces&lt;/strong&gt; solve.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Is a Workspace?
&lt;/h2&gt;

&lt;p&gt;A workspace is a &lt;strong&gt;shared environment&lt;/strong&gt; for multiple backend projects.&lt;/p&gt;

&lt;p&gt;Think of it like a monorepo, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each project is independent (no forced sharing)&lt;/li&gt;
&lt;li&gt;Each project can use FastAPI or NestJS (or both)&lt;/li&gt;
&lt;li&gt;One Python environment powers all Python projects&lt;/li&gt;
&lt;li&gt;All projects are auto-tracked in a registry&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In practice:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-workspace/
├── .rapidkit-workspace        # Workspace marker
├── .venv/                     # Shared Python environment
├── poetry.lock                # Locked dependencies
├── auth-service/              # FastAPI project
├── user-api/                  # FastAPI project
├── payment-gateway/           # NestJS project
└── notification-service/      # FastAPI project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;One command to create it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;One command to add projects:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit create project fastapi.standard auth-service
rapidkit create project nestjs.standard payment-gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All FastAPI projects share the same &lt;code&gt;.venv&lt;/code&gt; (~150MB once, not 600MB four times)&lt;/li&gt;
&lt;li&gt;All projects are tracked in &lt;code&gt;~/.rapidkit/workspaces.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;VS Code extension auto-discovers everything&lt;/li&gt;
&lt;li&gt;RapidKit Core version is consistent across all projects&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Why This Matters: Real Numbers
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Scenario:&lt;/strong&gt; You're building 5 microservices for a SaaS app.&lt;/p&gt;

&lt;h4&gt;
  
  
  Without Workspaces (Traditional Approach)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;5 separate virtualenvs:&lt;/strong&gt; ~750MB of duplicated Python packages&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5 independent setups:&lt;/strong&gt; ~30 minutes × 5 = 2.5 hours&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;5 different dependency versions:&lt;/strong&gt; Debugging nightmare&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No central tracking:&lt;/strong&gt; Manual documentation required&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onboarding time:&lt;/strong&gt; 3-4 days for a new developer&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  With Workspaces (RapidKit Approach)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;1 shared virtualenv:&lt;/strong&gt; ~150MB total&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1 workspace setup:&lt;/strong&gt; ~2 minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Consistent dependencies:&lt;/strong&gt; One &lt;code&gt;poetry.lock&lt;/code&gt; for all Python projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-tracked registry:&lt;/strong&gt; VS Code shows all projects instantly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Onboarding time:&lt;/strong&gt; 1 day (open workspace, see everything)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Savings:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;600MB disk space&lt;/li&gt;
&lt;li&gt;2+ hours of setup time&lt;/li&gt;
&lt;li&gt;Countless hours of debugging version conflicts&lt;/li&gt;
&lt;li&gt;2-3 days of onboarding per developer&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How It Works: The Magic of Shared Environments
&lt;/h2&gt;

&lt;p&gt;When you create a workspace, RapidKit:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Creates a Poetry-managed Python environment&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   .venv/
   ├── bin/
   │   ├── python3
   │   ├── rapidkit   &lt;span class="c"&gt;# CLI available globally in workspace&lt;/span&gt;
   │   └── ...
   ├── lib/
   │   └── python3.11/site-packages/
   │       └── rapidkit_core/   &lt;span class="c"&gt;# Shared engine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Installs RapidKit Core once&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   poetry add rapidkit-core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Provides activation scripts&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   &lt;span class="nb"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;poetry &lt;span class="nb"&gt;env &lt;/span&gt;info &lt;span class="nt"&gt;--path&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;/bin/activate"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Tracks everything in a registry&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;~/.rapidkit/workspaces.json&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"workspaces"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/home/user/my-workspace"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="nl"&gt;"projects"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"auth-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"framework"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fastapi"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"framework"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fastapi"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
           &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"payment-gateway"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"framework"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"nestjs"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
         &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
       &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Every tool reads this registry:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VS Code extension shows your workspaces in the sidebar&lt;/li&gt;
&lt;li&gt;CLI knows which projects exist&lt;/li&gt;
&lt;li&gt;Commands auto-complete project names&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Under the Hood: How Workspace Environments Work
&lt;/h2&gt;

&lt;p&gt;Understanding workspace mechanics helps you make the right choice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Isolation Model
&lt;/h3&gt;

&lt;p&gt;When you run &lt;code&gt;npx rapidkit my-workspace&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-workspace/
├── .venv/                    # Workspace virtualenv (Poetry-managed)
│   ├── bin/
│   │   ├── python3          # Python interpreter
│   │   ├── poetry           # Poetry CLI
│   │   └── rapidkit         # RapidKit Core CLI
│   └── lib/
│       └── python3.10/site-packages/
│           └── rapidkit_core/   # Core engine installed here
├── pyproject.toml            # Workspace Poetry config
├── poetry.lock               # Locked Core version
└── README.md

# After creating projects:
my-workspace/
├── .venv/                    # Workspace env (shared Core)
├── auth-service/
│   └── .venv/               # Project env (project deps only)
├── user-service/
│   └── .venv/               # Project env (project deps only)
└── payment-service/
    └── .venv/               # Project env (project deps only)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Benefits of This Architecture
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Command Resolution:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Inside workspace (any subdirectory)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;rapidkit create project fastapi.standard api
&lt;span class="c"&gt;# ↳ Uses workspace .venv/bin/rapidkit (shared Core)&lt;/span&gt;

&lt;span class="c"&gt;# Outside workspace&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npx rapidkit create project fastapi.standard api
&lt;span class="c"&gt;# ↳ Downloads and uses temporary npm bridge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Disk Efficiency:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workspace &lt;code&gt;.venv/&lt;/code&gt;: ~150MB (rapidkit-core + Poetry deps)&lt;/li&gt;
&lt;li&gt;Each project &lt;code&gt;.venv/&lt;/code&gt;: ~100MB (FastAPI, SQLAlchemy, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total for 4 projects:&lt;/strong&gt; 150MB + (4 × 100MB) = 550MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Without workspace:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each project: ~150MB (rapidkit-core) + 100MB (deps) = 250MB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total for 4 projects:&lt;/strong&gt; 4 × 250MB = 1000MB&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Savings:&lt;/strong&gt; 450MB (45%)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Version Consistency:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# All projects use same Core version&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;auth-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit &lt;span class="nt"&gt;--version&lt;/span&gt;
RapidKit Core 0.3.0

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ../user-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit &lt;span class="nt"&gt;--version&lt;/span&gt;  
RapidKit Core 0.3.0  &lt;span class="c"&gt;# Same version!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Upgrade Scenarios:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Upgrade Core for entire workspace&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace
poetry update rapidkit-core
&lt;span class="c"&gt;# ↳ All projects instantly use new version&lt;/span&gt;

&lt;span class="c"&gt;# Upgrade individual project dependencies&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;auth-service
poetry update fastapi
&lt;span class="c"&gt;# ↳ Only affects this project&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Global Install Alternative
&lt;/h3&gt;

&lt;p&gt;Instead of workspace, you can install Core globally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# With pipx (recommended - isolated)&lt;/span&gt;
pipx &lt;span class="nb"&gt;install &lt;/span&gt;rapidkit-core

&lt;span class="c"&gt;# Or with pip (system-wide)&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;rapidkit-core

&lt;span class="c"&gt;# Now rapidkit is available everywhere&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;rapidkit &lt;span class="nt"&gt;--version&lt;/span&gt;
RapidKit Core 0.3.0

&lt;span class="nv"&gt;$ &lt;/span&gt;rapidkit create project fastapi.standard api
&lt;span class="c"&gt;# ↳ Uses global installation&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ No workspace needed for single projects&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;rapidkit&lt;/code&gt; available system-wide&lt;/li&gt;
&lt;li&gt;⚠️ All projects use same global Core version&lt;/li&gt;
&lt;li&gt;⚠️ Upgrading affects all projects simultaneously&lt;/li&gt;
&lt;li&gt;⚠️ No per-workspace version pinning&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Three Ways to Start: Which One Should You Choose?
&lt;/h2&gt;

&lt;p&gt;RapidKit gives you flexibility. Here's how each approach compares:&lt;/p&gt;

&lt;h3&gt;
  
  
  1️⃣ Workspace Creation (Recommended)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace
rapidkit create project fastapi.standard api
&lt;span class="nb"&gt;cd &lt;/span&gt;api
rapidkit init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; rapidkit dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple services (microservices)&lt;/li&gt;
&lt;li&gt;Team environments&lt;/li&gt;
&lt;li&gt;Production projects&lt;/li&gt;
&lt;li&gt;Long-term maintenance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Prerequisites auto-installed (Python, Poetry, RapidKit Core)&lt;/li&gt;
&lt;li&gt;✅ Shared rapidkit-core in workspace virtualenv&lt;/li&gt;
&lt;li&gt;✅ Each project gets its own &lt;code&gt;.venv/&lt;/code&gt; but shares Core&lt;/li&gt;
&lt;li&gt;✅ &lt;code&gt;rapidkit&lt;/code&gt; command uses workspace environment (faster)&lt;/li&gt;
&lt;li&gt;✅ VS Code extension auto-discovers workspace&lt;/li&gt;
&lt;li&gt;✅ Consistent Core version across all projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setup time:&lt;/strong&gt; 2 minutes (first time), instant for additional projects&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Disk:&lt;/strong&gt; Workspace &lt;code&gt;.venv/&lt;/code&gt; ~150MB (once) + each project &lt;code&gt;.venv/&lt;/code&gt; ~100MB&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Complexity:&lt;/strong&gt; Low (everything automated)&lt;/p&gt;


&lt;h3&gt;
  
  
  2️⃣ Direct Project Creation
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Outside any workspace&lt;/span&gt;
npx rapidkit create project fastapi.standard api
&lt;span class="nb"&gt;cd &lt;/span&gt;api
npx rapidkit init
npx rapidkit dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single service&lt;/li&gt;
&lt;li&gt;Quick prototypes&lt;/li&gt;
&lt;li&gt;Learning RapidKit&lt;/li&gt;
&lt;li&gt;Temporary experiments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚠️ Requires Python 3.10+ and Poetry pre-installed&lt;/li&gt;
&lt;li&gt;⚠️ Each project gets its own virtualenv (~150MB each)&lt;/li&gt;
&lt;li&gt;⚠️ No automatic dependency synchronization&lt;/li&gt;
&lt;li&gt;✅ Faster initial setup (no workspace overhead)&lt;/li&gt;
&lt;li&gt;✅ Good for experimentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setup time:&lt;/strong&gt; 5 minutes (if prerequisites exist)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Disk per project:&lt;/strong&gt; ~150MB (separate virtualenv)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Complexity:&lt;/strong&gt; Medium (manual prerequisite management)&lt;/p&gt;


&lt;h3&gt;
  
  
  3️⃣ Python Core Direct
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install globally&lt;/span&gt;
pipx &lt;span class="nb"&gt;install &lt;/span&gt;rapidkit-core
&lt;span class="c"&gt;# Or: pip install rapidkit-core&lt;/span&gt;

&lt;span class="c"&gt;# Create project&lt;/span&gt;
rapidkit create project fastapi.standard api
&lt;span class="nb"&gt;cd &lt;/span&gt;api
rapidkit init
rapidkit dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Best for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Advanced users&lt;/li&gt;
&lt;li&gt;CI/CD pipelines&lt;/li&gt;
&lt;li&gt;Custom tooling&lt;/li&gt;
&lt;li&gt;Docker environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Trade-offs:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;⚠️ Full manual Python environment management&lt;/li&gt;
&lt;li&gt;⚠️ No workspace features&lt;/li&gt;
&lt;li&gt;⚠️ No npm bridge benefits&lt;/li&gt;
&lt;li&gt;✅ Maximum control over environment&lt;/li&gt;
&lt;li&gt;✅ Good for automation scripts&lt;/li&gt;
&lt;li&gt;✅ Minimal dependencies (Python only)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Setup time:&lt;/strong&gt; Varies (depends on your environment)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Disk per project:&lt;/strong&gt; ~150MB (separate virtualenv)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Complexity:&lt;/strong&gt; High (manual everything)&lt;/p&gt;


&lt;h3&gt;
  
  
  Visual Approach: VS Code Extension
&lt;/h3&gt;

&lt;p&gt;All three approaches integrate with VS Code extension:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;RapidKit extension&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Use Command Palette:

&lt;ul&gt;
&lt;li&gt;"RapidKit: Create Workspace" (Approach 1)&lt;/li&gt;
&lt;li&gt;"RapidKit: Create Project" (Approach 2)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Browse modules visually&lt;/li&gt;
&lt;li&gt;Check setup status&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Perfect for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Visual learners&lt;/li&gt;
&lt;li&gt;GUI preference&lt;/li&gt;
&lt;li&gt;Team onboarding&lt;/li&gt;
&lt;li&gt;Non-terminal workflows&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Comparison Matrix
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Workspace&lt;/th&gt;
&lt;th&gt;Direct&lt;/th&gt;
&lt;th&gt;Python Core&lt;/th&gt;
&lt;th&gt;VS Code&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auto Prerequisites&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;⚠️ Partial&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Shared Virtualenv&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ (workspace)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Multi-Project Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Excellent&lt;/td&gt;
&lt;td&gt;⚠️ Manual&lt;/td&gt;
&lt;td&gt;⚠️ Manual&lt;/td&gt;
&lt;td&gt;✅ Excellent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Disk Efficiency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ High&lt;/td&gt;
&lt;td&gt;⚠️ Medium&lt;/td&gt;
&lt;td&gt;⚠️ Medium&lt;/td&gt;
&lt;td&gt;✅ High&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Setup Complexity&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;🟢 Low&lt;/td&gt;
&lt;td&gt;🟡 Medium&lt;/td&gt;
&lt;td&gt;🔴 High&lt;/td&gt;
&lt;td&gt;🟢 Low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team-Friendly&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;⚠️ Moderate&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CI/CD Ready&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;⚠️ GUI only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;🟢 Easy&lt;/td&gt;
&lt;td&gt;🟡 Medium&lt;/td&gt;
&lt;td&gt;🔴 Steep&lt;/td&gt;
&lt;td&gt;🟢 Easiest&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h3&gt;
  
  
  Real Scenario: Building a SaaS Backend
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Task:&lt;/strong&gt; Create 4 microservices (auth, users, payments, notifications)&lt;/p&gt;
&lt;h4&gt;
  
  
  Approach 1: Workspace
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-saas
&lt;span class="nb"&gt;cd &lt;/span&gt;my-saas
rapidkit create project fastapi.standard auth-service
rapidkit create project fastapi.standard user-service
rapidkit create project fastapi.standard payment-service
rapidkit create project fastapi.standard notification-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workspace &lt;code&gt;.venv/&lt;/code&gt; with rapidkit-core (~150MB)&lt;/li&gt;
&lt;li&gt;Each project has own &lt;code&gt;.venv/&lt;/code&gt; (~100MB each = 400MB total)&lt;/li&gt;
&lt;li&gt;Total: ~550MB (vs 600MB+ without workspace)&lt;/li&gt;
&lt;li&gt;Setup time: 5 minutes&lt;/li&gt;
&lt;li&gt;All services use same RapidKit Core version&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rapidkit&lt;/code&gt; command (no npx) uses workspace environment&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  Approach 2: Direct (Individual Projects)
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit create project fastapi.standard auth-service
&lt;span class="nb"&gt;cd &lt;/span&gt;auth-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npx rapidkit init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ..

npx rapidkit create project fastapi.standard user-service
&lt;span class="nb"&gt;cd &lt;/span&gt;user-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npx rapidkit init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ..

npx rapidkit create project fastapi.standard payment-service
&lt;span class="nb"&gt;cd &lt;/span&gt;payment-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npx rapidkit init &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ..

npx rapidkit create project fastapi.standard notification-service
&lt;span class="nb"&gt;cd &lt;/span&gt;notification-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npx rapidkit init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Four separate virtualenvs (~600MB total)&lt;/li&gt;
&lt;li&gt;Each has its own rapidkit-core installation&lt;/li&gt;
&lt;li&gt;Setup time: 20+ minutes&lt;/li&gt;
&lt;li&gt;Potential Core version conflicts between projects&lt;/li&gt;
&lt;li&gt;Must use &lt;code&gt;npx rapidkit&lt;/code&gt; for every command&lt;/li&gt;
&lt;/ul&gt;


&lt;h4&gt;
  
  
  Approach 3: Python Core
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;rapidkit-core
rapidkit create project fastapi.standard auth-service
&lt;span class="nb"&gt;cd &lt;/span&gt;auth-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; poetry &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ..

rapidkit create project fastapi.standard user-service
&lt;span class="nb"&gt;cd &lt;/span&gt;user-service &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; poetry &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; ..
&lt;span class="c"&gt;# ...repeat for remaining services&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Four virtualenvs (~600MB total)&lt;/li&gt;
&lt;li&gt;Each project manages its own environment&lt;/li&gt;
&lt;li&gt;Setup time: 25+ minutes&lt;/li&gt;
&lt;li&gt;Full manual control (good for experts)&lt;/li&gt;
&lt;li&gt;Requires global rapidkit-core installation&lt;/li&gt;
&lt;li&gt;No npm bridge benefits (no &lt;code&gt;npx&lt;/code&gt; workflow)&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Our Recommendation: Start with Workspace
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;For 90% of use cases, workspace approach wins:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Handles prerequisites automatically&lt;/li&gt;
&lt;li&gt;Scales effortlessly (add projects instantly)&lt;/li&gt;
&lt;li&gt;Team-friendly (consistent environments)&lt;/li&gt;
&lt;li&gt;Disk-efficient (shared virtualenv)&lt;/li&gt;
&lt;li&gt;Production-ready (used by real companies)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Switch to Direct/Core when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single prototype project&lt;/li&gt;
&lt;li&gt;Experimenting with RapidKit&lt;/li&gt;
&lt;li&gt;Custom CI/CD requirements&lt;/li&gt;
&lt;li&gt;Need maximum control&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  This Is What "Consistency at Scale" Really Means
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Planning to build 2+ related projects? → Workspace&lt;/li&gt;
&lt;li&gt;Just trying RapidKit? → Standalone&lt;/li&gt;
&lt;li&gt;Not sure? → Workspace (you can always ignore it)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  Real-World Example: SaaS Backend
&lt;/h2&gt;

&lt;p&gt;Let's build a complete SaaS backend in a workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create workspace&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit saas-backend
&lt;span class="nb"&gt;cd &lt;/span&gt;saas-backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2: Create core services&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Authentication &amp;amp; user management&lt;/span&gt;
rapidkit create project fastapi.ddd auth-service
rapidkit add module auth &lt;span class="nt"&gt;--project&lt;/span&gt; auth-service
rapidkit add module users.core &lt;span class="nt"&gt;--project&lt;/span&gt; auth-service

&lt;span class="c"&gt;# Main API gateway&lt;/span&gt;
rapidkit create project nestjs.standard api-gateway

&lt;span class="c"&gt;# Background jobs service&lt;/span&gt;
rapidkit create project fastapi.standard jobs-service
rapidkit add module celery &lt;span class="nt"&gt;--project&lt;/span&gt; jobs-service

&lt;span class="c"&gt;# Notification service&lt;/span&gt;
rapidkit create project fastapi.standard notifications
rapidkit add module email &lt;span class="nt"&gt;--project&lt;/span&gt; notifications
rapidkit add module notifications.unified &lt;span class="nt"&gt;--project&lt;/span&gt; notifications
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Open in VS Code&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VS Code sidebar now shows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📁 SaaS Backend (Workspace)
 ├── 🐍 auth-service (FastAPI)
 ├── 🟦 api-gateway (NestJS)
 ├── 🐍 jobs-service (FastAPI)
 └── 🐍 notifications (FastAPI)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;One click to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start any service's dev server&lt;/li&gt;
&lt;li&gt;Run tests across all services&lt;/li&gt;
&lt;li&gt;Install modules visually&lt;/li&gt;
&lt;li&gt;Check workspace health&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Developer Experience Benefits
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Instant Discoverability
&lt;/h3&gt;

&lt;p&gt;New developer joins your team:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone company/backend-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;backend-workspace
code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;VS Code opens. They see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All 8 microservices in the sidebar&lt;/li&gt;
&lt;li&gt;Project structure is &lt;strong&gt;identical&lt;/strong&gt; across services&lt;/li&gt;
&lt;li&gt;Modules are documented in each project's README&lt;/li&gt;
&lt;li&gt;Docker Compose is already configured&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;No documentation needed.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  2. Consistent Commands
&lt;/h3&gt;

&lt;p&gt;Every project, same commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;auth-service
rapidkit dev      &lt;span class="c"&gt;# Start dev server&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; ../api-gateway
rapidkit dev      &lt;span class="c"&gt;# Start dev server&lt;/span&gt;

&lt;span class="nb"&gt;cd&lt;/span&gt; ../jobs-service
rapidkit &lt;span class="nb"&gt;test&lt;/span&gt;     &lt;span class="c"&gt;# Run tests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;No learning curve between services.&lt;/strong&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  3. Shared Module Updates
&lt;/h3&gt;

&lt;p&gt;You add a new logging module to one service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;auth-service
rapidkit add module logging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;RapidKit Core is shared across the workspace.&lt;/p&gt;

&lt;p&gt;Now every developer on every project can use the same module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; ../api-gateway
rapidkit add module logging   &lt;span class="c"&gt;# Same version, instant install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;No "which version did we use?" questions.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Advanced: Workspace Strategies
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Strategy 1: Monolithic Workspace
&lt;/h3&gt;

&lt;p&gt;All company projects in one workspace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;company-backend/
├── auth-service/
├── user-api/
├── payment-api/
├── notification-service/
├── analytics-api/
└── admin-api/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Maximum consistency&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Large workspace&lt;/p&gt;


&lt;h3&gt;
  
  
  Strategy 2: Domain-Separated Workspaces
&lt;/h3&gt;

&lt;p&gt;One workspace per domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;company-auth/
├── auth-service/
└── user-api/

company-payments/
├── payment-api/
└── billing-service/

company-operations/
├── notification-service/
└── analytics-api/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Smaller workspaces, clear boundaries&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Requires more setup&lt;/p&gt;


&lt;h3&gt;
  
  
  Strategy 3: Hybrid (Recommended)
&lt;/h3&gt;

&lt;p&gt;Core services in a workspace, utilities standalone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;core-platform/       # Workspace
├── auth-service/
├── user-api/
└── payment-api/

tools/
├── migration-script/    # Standalone
└── data-import/         # Standalone
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Best of both worlds&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Requires discipline&lt;/p&gt;


&lt;h2&gt;
  
  
  Workspace Anti-Patterns to Avoid
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ❌ Anti-Pattern 1: Mixing Unrelated Projects
&lt;/h3&gt;

&lt;p&gt;Don't put your company backend and personal blog in the same workspace.&lt;/p&gt;

&lt;p&gt;Workspaces are for &lt;strong&gt;related projects&lt;/strong&gt;, not all projects.&lt;/p&gt;


&lt;h3&gt;
  
  
  ❌ Anti-Pattern 2: Never Using Standalone
&lt;/h3&gt;

&lt;p&gt;Workspaces are powerful, but not always necessary.&lt;/p&gt;

&lt;p&gt;Quick prototype? Use standalone:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit create project fastapi.standard quick-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ❌ Anti-Pattern 3: Ignoring the Registry
&lt;/h3&gt;

&lt;p&gt;RapidKit auto-tracks workspaces in &lt;code&gt;~/.rapidkit/workspaces.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Don't manually edit this file — let RapidKit manage it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hidden Superpower: Team Onboarding
&lt;/h2&gt;

&lt;p&gt;This is where workspaces really shine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Traditional onboarding:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone repo&lt;/li&gt;
&lt;li&gt;Read 10-page setup guide&lt;/li&gt;
&lt;li&gt;Install Python 3.11 (or was it 3.10?)&lt;/li&gt;
&lt;li&gt;Create virtualenv&lt;/li&gt;
&lt;li&gt;Install dependencies (pray no conflicts)&lt;/li&gt;
&lt;li&gt;Set up .env files (which template?)&lt;/li&gt;
&lt;li&gt;Install Docker&lt;/li&gt;
&lt;li&gt;Configure IDE&lt;/li&gt;
&lt;li&gt;Finally run the project (if lucky)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Time:&lt;/strong&gt; 4-6 hours (or 2 days if unlucky)&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Workspace onboarding:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone workspace repo&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;./bootstrap.sh&lt;/code&gt; (installs Poetry, activates env)&lt;/li&gt;
&lt;li&gt;Open VS Code: &lt;code&gt;code .&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Time:&lt;/strong&gt; 5 minutes&lt;/p&gt;

&lt;p&gt;Everything else is automatic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python environment is ready&lt;/li&gt;
&lt;li&gt;Dependencies are locked&lt;/li&gt;
&lt;li&gt;All projects are visible&lt;/li&gt;
&lt;li&gt;Structure is consistent&lt;/li&gt;
&lt;li&gt;Commands work immediately&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;Create a workspace and see the difference:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create workspace&lt;/span&gt;
npx rapidkit demo-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;demo-workspace

&lt;span class="c"&gt;# Add two projects&lt;/span&gt;
rapidkit create project fastapi.standard api-one
rapidkit create project nestjs.standard api-two

&lt;span class="c"&gt;# Open in VS Code&lt;/span&gt;
code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now try:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Browse projects in the sidebar&lt;/li&gt;
&lt;li&gt;Check workspace health (pulse icon)&lt;/li&gt;
&lt;li&gt;Install a module to one project&lt;/li&gt;
&lt;li&gt;See how everything is tracked&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;In the next article, we'll build a &lt;strong&gt;production API from scratch in 5 minutes&lt;/strong&gt; — no shortcuts, no hand-waving.&lt;/p&gt;

&lt;p&gt;You'll see exactly what you get, why the structure matters, and how to deploy it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Learn More
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🌐 &lt;a href="https://www.getrapidkit.com" rel="noopener noreferrer"&gt;getrapidkit.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;a href="https://www.npmjs.com/package/rapidkit" rel="noopener noreferrer"&gt;npm: rapidkit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐍 &lt;a href="https://pypi.org/project/rapidkit-core/" rel="noopener noreferrer"&gt;PyPI: rapidkit-core&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧩 &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;VS Code Extension&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>rapidkit</category>
      <category>workspace</category>
      <category>microservices</category>
      <category>devops</category>
    </item>
    <item>
      <title>Build Your First AI Agent with RapidKit in 10 Minutes</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Tue, 10 Feb 2026 21:37:22 +0000</pubDate>
      <link>https://forem.com/rapidkit/build-your-first-ai-agent-with-rapidkit-in-10-minutes-3dj6</link>
      <guid>https://forem.com/rapidkit/build-your-first-ai-agent-with-rapidkit-in-10-minutes-3dj6</guid>
      <description>&lt;h3&gt;
  
  
  The Problem with AI Integration
&lt;/h3&gt;

&lt;p&gt;You want to add AI to your FastAPI backend.&lt;/p&gt;

&lt;p&gt;What usually happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install 5 different packages (openai, anthropic, langchain, etc.)&lt;/li&gt;
&lt;li&gt;Write wrapper code for each provider&lt;/li&gt;
&lt;li&gt;Handle streaming, caching, retries manually&lt;/li&gt;
&lt;li&gt;Debug configuration hell&lt;/li&gt;
&lt;li&gt;Spend 2 days integrating what should take 10 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;There's a better way.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What We're Building
&lt;/h2&gt;

&lt;p&gt;A production-ready &lt;strong&gt;AI Assistant Service&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Multiple AI providers (Echo, Template, OpenAI-ready)&lt;/li&gt;
&lt;li&gt;✅ Chat completions API&lt;/li&gt;
&lt;li&gt;✅ Streaming responses&lt;/li&gt;
&lt;li&gt;✅ Conversation history&lt;/li&gt;
&lt;li&gt;✅ Response caching&lt;/li&gt;
&lt;li&gt;✅ Health monitoring&lt;/li&gt;
&lt;li&gt;✅ Provider switching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time to build:&lt;/strong&gt; 10 minutes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Lines of custom code:&lt;/strong&gt; ~50&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Source code:&lt;/strong&gt; &lt;a href="https://github.com/getrapidkit/rapidkit-examples/tree/main/my-ai-workspace" rel="noopener noreferrer"&gt;https://github.com/getrapidkit/rapidkit-examples/tree/main/my-ai-workspace&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Published article links:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Medium: &lt;a href="https://rapidkit.medium.com/build-your-first-ai-agent-with-rapidkit-in-10-minutes-f38a6a12088d" rel="noopener noreferrer"&gt;https://rapidkit.medium.com/build-your-first-ai-agent-with-rapidkit-in-10-minutes-f38a6a12088d&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Dev.to: &lt;a href="https://dev.to/rapidkit/build-your-first-ai-agent-with-rapidkit-in-10-minutes-3dj6"&gt;https://dev.to/rapidkit/build-your-first-ai-agent-with-rapidkit-in-10-minutes-3dj6&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's start.&lt;/p&gt;


&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js 20+ (&lt;code&gt;node --version&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Python 3.10+ (&lt;code&gt;python3 --version&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A terminal&lt;/li&gt;
&lt;li&gt;(Optional) OpenAI API key for real AI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time:&lt;/strong&gt; 1 minute to verify&lt;/p&gt;


&lt;h2&gt;
  
  
  Minute 0-2: Create Workspace and Project
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Create workspace (handles Python/Poetry setup automatically)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-ai-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prompts you'll see:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;? Author name: developer
? Select Python version: 3.10
? Install method: 🎯 Poetry (Recommended)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What happens:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates workspace directory&lt;/li&gt;
&lt;li&gt;Installs Poetry if needed&lt;/li&gt;
&lt;li&gt;Creates virtualenv in workspace root&lt;/li&gt;
&lt;li&gt;Installs rapidkit-core&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Create FastAPI project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;my-ai-workspace
rapidkit create project fastapi.standard ai-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Prompts:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Project name: ai-agent
Install essential modules? Y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Initialize project&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;ai-agent
rapidkit init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Your structure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-ai-workspace/
├── .venv/                  # Workspace virtualenv
├── pyproject.toml
└── ai-agent/
    ├── .venv/             # Project virtualenv
    ├── src/
    │   ├── main.py
    │   └── modules/
    ├── tests/
    └── pyproject.toml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Minute 2-3: Add AI Assistant Module
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit add module ai_assistant
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What gets installed:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
├── modules/
│   └── free/
│       └── ai/
│           └── ai_assistant/
│               ├── ai_assistant.py          # Runtime engine
│               ├── ai_assistant_types.py    # Type definitions
│               └── routers/
│                   └── ai/
│                       └── ai_assistant.py  # FastAPI routes
└── health/
    └── ai_assistant.py                      # Health endpoint

tests/
└── modules/
    └── free/
        └── integration/
            └── ai/
                └── ai_assistant/
                    └── test_ai_assistant_integration.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Components:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Runtime (&lt;code&gt;ai_assistant.py&lt;/code&gt;):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provider management&lt;/li&gt;
&lt;li&gt;Chat completion logic&lt;/li&gt;
&lt;li&gt;Streaming support&lt;/li&gt;
&lt;li&gt;Conversation history&lt;/li&gt;
&lt;li&gt;Response caching&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Routes (&lt;code&gt;routers/ai/ai_assistant.py&lt;/code&gt;):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;POST /ai/assistant/completions&lt;/code&gt; — Get completions&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /ai/assistant/stream&lt;/code&gt; — Stream responses&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /ai/assistant/providers&lt;/code&gt; — List providers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /ai/assistant/cache/clear&lt;/code&gt; — Clear cache&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GET /ai/assistant/health&lt;/code&gt; — Health check&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Types (&lt;code&gt;ai_assistant_types.py&lt;/code&gt;):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AssistantMessage&lt;/code&gt; — Message structure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AssistantResponse&lt;/code&gt; — Response structure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ProviderConfig&lt;/code&gt; — Provider configuration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AiAssistantConfig&lt;/code&gt; — Runtime config&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Minute 3-4: Configure Providers
&lt;/h2&gt;

&lt;p&gt;Create &lt;code&gt;config/ai_assistant.yaml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# AI Assistant Configuration&lt;/span&gt;
&lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="c1"&gt;# Echo Provider (for testing)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo&lt;/span&gt;
    &lt;span class="na"&gt;provider_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;prefix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[AI]&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
      &lt;span class="na"&gt;suffix&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;(powered&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;by&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Echo)"&lt;/span&gt;
      &lt;span class="na"&gt;mirror_context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="c1"&gt;# Template Provider (pre-defined responses)&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;support&lt;/span&gt;
    &lt;span class="na"&gt;provider_type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;template&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;responses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Thank&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;you&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;for&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;contacting&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;support.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{prompt}"&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;understand&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;your&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;concern&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;about&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{prompt}.&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;Let&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;me&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;help."&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Based&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;on&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'{context}',&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;regarding&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{prompt},&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;here's&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;what&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;I&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;suggest..."&lt;/span&gt;

  &lt;span class="c1"&gt;# OpenAI Provider (ready for real AI)&lt;/span&gt;
  &lt;span class="c1"&gt;# - name: openai&lt;/span&gt;
  &lt;span class="c1"&gt;#   provider_type: openai&lt;/span&gt;
  &lt;span class="c1"&gt;#   enabled: false&lt;/span&gt;
  &lt;span class="c1"&gt;#   options:&lt;/span&gt;
  &lt;span class="c1"&gt;#     api_key: ${OPENAI_API_KEY}&lt;/span&gt;
  &lt;span class="c1"&gt;#     model: gpt-4&lt;/span&gt;
  &lt;span class="c1"&gt;#     temperature: 0.7&lt;/span&gt;

&lt;span class="na"&gt;default_provider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;echo&lt;/span&gt;
&lt;span class="na"&gt;conversation_window&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
&lt;span class="na"&gt;cache_enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="na"&gt;request_timeout_seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Provider Types Explained:&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Echo Provider
&lt;/h3&gt;

&lt;p&gt;Perfect for testing. Echoes back your prompt with optional prefix/suffix.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Example response:
# Input: "Hello"
# Output: "[AI] Hello (powered by Echo)"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Template Provider
&lt;/h3&gt;

&lt;p&gt;Returns pre-configured responses in rotation. Great for FAQ bots.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# First request: "How do I reset password?"
# Response: "Thank you for contacting support. How do I reset password?"
# 
# Second request: "Where is my order?"
# Response: "I understand your concern about Where is my order?. Let me help."
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  OpenAI Provider (Real AI)
&lt;/h3&gt;

&lt;p&gt;Integrates with OpenAI API. You'll implement this in advanced section.&lt;/p&gt;




&lt;h2&gt;
  
  
  Minute 4-5: Integrate into FastAPI
&lt;/h2&gt;

&lt;p&gt;Update &lt;code&gt;src/main.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;FastAPI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;src.modules.free.ai.ai_assistant.routers.ai.ai_assistant&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;register_ai_assistant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;build_config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Load config from YAML
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config/ai_assistant.yaml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;config_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safe_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI Agent API&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0.0&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;description&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Production AI Assistant powered by RapidKit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Register AI Assistant
&lt;/span&gt;&lt;span class="nf"&gt;register_ai_assistant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@app.get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;message&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI Agent API is running&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;endpoints&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;completions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/ai/assistant/completions&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;stream&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/ai/assistant/stream&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;providers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/ai/assistant/providers&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;health&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/ai/assistant/health&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Install PyYAML:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry add pyyaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Minute 5-6: Test Basic Functionality
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Start the server:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Server output:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INFO:     Uvicorn running on http://127.0.0.1:8000
INFO:     Application startup complete.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Open browser:&lt;/strong&gt; &lt;a href="http://localhost:8000/docs" rel="noopener noreferrer"&gt;http://localhost:8000/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll see Swagger UI with AI endpoints!&lt;/p&gt;




&lt;h2&gt;
  
  
  Minute 6-7: Test Echo Provider
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;List available providers:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8000/ai/assistant/providers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"echo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"support"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test echo completion:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/ai/assistant/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "What is RapidKit?",
    "provider": "echo"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[AI] What is RapidKit? (powered by Echo)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.234&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prompt_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"completion_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"metadata"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Minute 7-8: Test Template Provider
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/ai/assistant/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "How do I reset my password?",
    "provider": "support"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"support"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Thank you for contacting support. How do I reset my password?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.156&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prompt_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"completion_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test with conversation context:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/ai/assistant/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "Follow up question",
    "provider": "support",
    "context": [
      {"role": "user", "content": "I forgot my password"},
      {"role": "assistant", "content": "I can help reset your password"}
    ]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response includes context:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"support"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Based on 'I forgot my password | I can help reset your password', regarding Follow up question, here's what I suggest..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.189&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Minute 8-9: Test Streaming
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/ai/assistant/stream &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "Tell me about AI agents",
    "provider": "echo"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response streams word by word:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[AI] Tell me about AI agents (powered by Echo)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;With Python client:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;http://localhost:8000/ai/assistant/stream&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;prompt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Explain RapidKit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;provider&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;echo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;iter_content&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decode_unicode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flush&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Minute 9-10: Test Caching
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;First request (not cached):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/ai/assistant/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "What is caching?",
    "provider": "echo"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.245&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Second identical request (cached):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Same request again&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/ai/assistant/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "What is caching?",
    "provider": "echo"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.245&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Notice:&lt;/strong&gt; &lt;code&gt;cached: true&lt;/code&gt; and same latency (from cache, not recomputed)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clear cache:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/ai/assistant/cache/clear
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Health Monitoring
&lt;/h2&gt;

&lt;p&gt;Check AI assistant health:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8000/ai/assistant/health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"vendor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ai_assistant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.1.7"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"runtime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ai_assistant"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"providers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.245&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"details"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"prefix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"[AI] "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"suffix"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;" (powered by Echo)"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"mirror_context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"support"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;0.189&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"details"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"responses"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cache_entries"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"history_length"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2026-02-10T10:30:00"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ok"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key metrics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provider status and latency&lt;/li&gt;
&lt;li&gt;Cache hit count&lt;/li&gt;
&lt;li&gt;Conversation history length&lt;/li&gt;
&lt;li&gt;Overall health status&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Advanced: Add OpenAI Provider
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Install OpenAI SDK&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry add openai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Create custom provider&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;src/modules/free/ai/ai_assistant/providers/openai_provider.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;OpenAI provider implementation.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Iterable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Mapping&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Sequence&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;src.modules.free.ai.ai_assistant.ai_assistant&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ChatProvider&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;src.modules.free.ai.ai_assistant.ai_assistant_types&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AssistantMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;ProviderStatus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;OpenAIProvider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;OpenAI chat completion provider.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-3.5-turbo&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_temperature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temperature&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;api_key&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_last_latency_ms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;conversation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AssistantMessage&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mapping&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Generate completion using OpenAI API.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;conversation&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_temperature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_temperature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;conversation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AssistantMessage&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Mapping&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Iterable&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Stream completion tokens from OpenAI.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;conversation&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

        &lt;span class="n"&gt;stream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_temperature&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;settings&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_temperature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;delta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;note_latency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;latency_ms&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Record latency for health metrics.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_last_latency_ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;latency_ms&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;health&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;ProviderStatus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Return provider health status.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ProviderStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ok&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;latency_ms&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_last_latency_ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_model&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_temperature&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Register OpenAI provider&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;src/main.py&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;src.modules.free.ai.ai_assistant.routers.ai.ai_assistant&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;register_ai_assistant&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;src.modules.free.ai.ai_assistant.providers.openai_provider&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAIProvider&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;
&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;config/ai_assistant.yaml&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;config_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yaml&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safe_load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;AI Agent API&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Register assistant
&lt;/span&gt;&lt;span class="n"&gt;assistant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;register_ai_assistant&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;config_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Add OpenAI provider manually
&lt;/span&gt;&lt;span class="n"&gt;openai_provider&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;OpenAIProvider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;gpt-4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;temperature&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;register_provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;openai_provider&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_default_provider&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;OPENAI_API_KEY&lt;/code&gt; is not set, keep &lt;code&gt;echo&lt;/code&gt;/&lt;code&gt;support&lt;/code&gt; as default so local/demo flows still work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Set API key&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"sk-..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Test real AI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8000/ai/assistant/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "prompt": "Explain RapidKit in one sentence",
    "provider": "openai"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response (real GPT-4):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"content"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"RapidKit is a developer toolkit that accelerates backend API development by providing pre-built modules, workspace management, and production-ready templates for FastAPI and NestJS frameworks."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1247.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"cached"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"usage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prompt_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"completion_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"total_tokens"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;38&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Real-World Use Case: Customer Support Agent
&lt;/h2&gt;

&lt;p&gt;Let's build a customer support AI agent:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Create &lt;code&gt;src/agents/support_agent.py&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Customer support AI agent.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Sequence&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;src.modules.free.ai.ai_assistant.ai_assistant&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AiAssistant&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;src.modules.free.ai.ai_assistant.ai_assistant_types&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;AssistantMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;AssistantResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SupportAgent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;AI-powered customer support agent.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;AiAssistant&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_assistant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assistant&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_system_prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;You are a helpful customer support agent.
Be concise, friendly, and solution-oriented.
If you don&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;t know the answer, escalate to human support.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_ticket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;customer_message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ticket_history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Sequence&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;AssistantMessage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AssistantResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Process customer support ticket.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="nc"&gt;AssistantMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_system_prompt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ticket_history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ticket_history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;customer_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# or "support" for template
&lt;/span&gt;            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;classify_urgency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Classify ticket urgency using AI.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Classify urgency (low/medium/high): &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;settings&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;temperature&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;  &lt;span class="c1"&gt;# More deterministic
&lt;/span&gt;        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Add route in &lt;code&gt;src/main.py&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;fastapi&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;src.agents.support_agent&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SupportAgent&lt;/span&gt;

&lt;span class="nd"&gt;@app.post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/support/ticket&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_support_ticket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;assistant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ai_assistant&lt;/span&gt;
    &lt;span class="n"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SupportAgent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Classify urgency
&lt;/span&gt;    &lt;span class="n"&gt;urgency&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;classify_urgency&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Generate response
&lt;/span&gt;    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle_ticket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ticket_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;TKT-12345&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;urgency&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;urgency&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ai_response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;latency_ms&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;latency_ms&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;next_action&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;escalate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;urgency&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;monitor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test support agent:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s2"&gt;"http://localhost:8000/support/ticket?message=My%20payment%20failed"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Response:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ticket_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TKT-12345"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"urgency"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"high"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ai_response"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"I understand your payment failed. Let me help you resolve this. Can you provide your order ID and the error message you received?"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"latency_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1156.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"next_action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"escalate"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What You Built
&lt;/h2&gt;

&lt;p&gt;A production-ready AI Agent API with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Multi-provider AI assistant (Echo, Template, OpenAI)&lt;/li&gt;
&lt;li&gt;✅ Chat completion endpoint&lt;/li&gt;
&lt;li&gt;✅ Streaming responses&lt;/li&gt;
&lt;li&gt;✅ Conversation context handling&lt;/li&gt;
&lt;li&gt;✅ Response caching (instant cache hits)&lt;/li&gt;
&lt;li&gt;✅ Health monitoring with metrics&lt;/li&gt;
&lt;li&gt;✅ Provider switching at runtime&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Advanced Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Custom OpenAI integration&lt;/li&gt;
&lt;li&gt;✅ Customer support agent&lt;/li&gt;
&lt;li&gt;✅ Urgency classification&lt;/li&gt;
&lt;li&gt;✅ Ticket routing logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Production Ready:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Type-safe with Pydantic models&lt;/li&gt;
&lt;li&gt;✅ Health checks for monitoring&lt;/li&gt;
&lt;li&gt;✅ Performance metrics (latency, cache hits)&lt;/li&gt;
&lt;li&gt;✅ Error handling&lt;/li&gt;
&lt;li&gt;✅ Async/streaming support&lt;/li&gt;
&lt;li&gt;✅ Integration tests included&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Total time:&lt;/strong&gt; 10 minutes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Custom code:&lt;/strong&gt; ~50 lines&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Everything else:&lt;/strong&gt; Generated by RapidKit&lt;/p&gt;


&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;
&lt;h3&gt;
  
  
  1. Provider-Agnostic Design
&lt;/h3&gt;

&lt;p&gt;Switch AI providers without changing your code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Use OpenAI
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;openai&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Switch to Anthropic (when you add it)
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anthropic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Fallback to template
&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assistant&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;support&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Built-in Production Features
&lt;/h3&gt;

&lt;p&gt;No need to implement yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Conversation history tracking&lt;/li&gt;
&lt;li&gt;Response caching (faster + cheaper)&lt;/li&gt;
&lt;li&gt;Streaming support&lt;/li&gt;
&lt;li&gt;Health monitoring&lt;/li&gt;
&lt;li&gt;Performance metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Module Architecture Benefits
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;ai_assistant&lt;/code&gt; module follows RapidKit's standard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;module.yaml&lt;/code&gt; — Version and metadata&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;templates/&lt;/code&gt; — FastAPI and NestJS variants&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docs/usage.md&lt;/code&gt; — Usage guide&lt;/li&gt;
&lt;li&gt;Health endpoints built-in&lt;/li&gt;
&lt;li&gt;Testing included&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Extensibility
&lt;/h3&gt;

&lt;p&gt;Easy to add providers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Implement &lt;code&gt;ChatProvider&lt;/code&gt; protocol&lt;/li&gt;
&lt;li&gt;Register with &lt;code&gt;assistant.register_provider()&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Done&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Example providers you can add:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Anthropic Claude&lt;/li&gt;
&lt;li&gt;Google PaLM&lt;/li&gt;
&lt;li&gt;Azure OpenAI&lt;/li&gt;
&lt;li&gt;Cohere&lt;/li&gt;
&lt;li&gt;Local models (Ollama, LM Studio)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Enhance your AI agent:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add authentication:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   rapidkit add module auth_core
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add database for chat history:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   rapidkit add module db_postgres
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add Redis for distributed caching:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   rapidkit add module redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add observability:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   rapidkit add module observability
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deploy:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker build &lt;span class="nt"&gt;-t&lt;/span&gt; ai-agent &lt;span class="nb"&gt;.&lt;/span&gt;
   docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8000:8000 ai-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Module Customization
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Override configuration via environment:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;RAPIDKIT_AI_ASSISTANT_LOG_LEVEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;DEBUG
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;RAPIDKIT_AI_ASSISTANT_TIMEOUT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;RAPIDKIT_AI_ASSISTANT_FEATURE_FLAG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Custom overrides in &lt;code&gt;overrides.py&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;See &lt;code&gt;/src/modules/free/ai/ai_assistant/overrides.py&lt;/code&gt; for runtime hooks.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Run integration tests:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test specific module:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;poetry run pytest tests/modules/free/integration/ai/ai_assistant/ &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Module verification:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit modules status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Provider Not Found
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ProviderNotFoundError: Provider 'openai' is not registered
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Check provider is registered in config or manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  Timeout Errors
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TimeoutError: Request exceeded 30 seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Increase timeout:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;request_timeout_seconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;60&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  OpenAI API Errors
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authentication Error: Invalid API key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Check environment variable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$OPENAI_API_KEY&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Learn More
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;📁 &lt;a href="https://github.com/getrapidkit/rapidkit-examples/tree/main/my-ai-workspace" rel="noopener noreferrer"&gt;Tutorial source workspace&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📰 &lt;a href="https://rapidkit.medium.com/build-your-first-ai-agent-with-rapidkit-in-10-minutes-f38a6a12088d" rel="noopener noreferrer"&gt;Published on Medium&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📰 &lt;a href="https://dev.to/rapidkit/build-your-first-ai-agent-with-rapidkit-in-10-minutes-3dj6"&gt;Published on Dev.to&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;a href="https://www.getrapidkit.com" rel="noopener noreferrer"&gt;RapidKit Website&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;a href="https://www.npmjs.com/package/rapidkit" rel="noopener noreferrer"&gt;npm Package&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐍 &lt;a href="https://pypi.org/project/rapidkit-core/" rel="noopener noreferrer"&gt;PyPI Package&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧩 &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;VS Code Extension&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📚 &lt;a href="https://docs.rapidkit.top/modules/ai_assistant" rel="noopener noreferrer"&gt;AI Assistant Module Docs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;You just built a production AI agent in 10 minutes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now scale it.&lt;/p&gt;

</description>
      <category>rapidkit</category>
      <category>opensource</category>
      <category>ai</category>
      <category>openai</category>
    </item>
    <item>
      <title>The RapidKit Ecosystem: Three Tools, One Vision</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Tue, 10 Feb 2026 13:13:55 +0000</pubDate>
      <link>https://forem.com/rapidkit/the-rapidkit-ecosystem-three-tools-one-vision-3604</link>
      <guid>https://forem.com/rapidkit/the-rapidkit-ecosystem-three-tools-one-vision-3604</guid>
      <description>&lt;h3&gt;
  
  
  You Don't Need Another Framework
&lt;/h3&gt;

&lt;p&gt;You need a &lt;strong&gt;workflow&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Backend development in 2026 isn't about picking the right web framework.&lt;br&gt;
FastAPI is mature. NestJS is mature.&lt;/p&gt;

&lt;p&gt;The problem isn't &lt;strong&gt;building APIs&lt;/strong&gt;.&lt;br&gt;
The problem is the &lt;strong&gt;everything else&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up projects consistently&lt;/li&gt;
&lt;li&gt;Managing dependencies across services&lt;/li&gt;
&lt;li&gt;Organizing code in a way that scales&lt;/li&gt;
&lt;li&gt;Onboarding new developers without friction&lt;/li&gt;
&lt;li&gt;Maintaining multiple APIs without chaos&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where most teams struggle.&lt;/p&gt;

&lt;p&gt;And this is what &lt;strong&gt;RapidKit&lt;/strong&gt; was built to solve.&lt;/p&gt;


&lt;h3&gt;
  
  
  One Problem, Three Tools
&lt;/h3&gt;

&lt;p&gt;RapidKit isn't a monolithic framework.&lt;br&gt;
It's an &lt;strong&gt;ecosystem&lt;/strong&gt; of three focused tools that work together seamlessly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;RapidKit Core&lt;/strong&gt; (Python Engine)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RapidKit CLI&lt;/strong&gt; (npm Package)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;RapidKit for VS Code&lt;/strong&gt; (Extension)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each tool solves a specific part of the workflow.&lt;br&gt;
Together, they eliminate the friction in modern backend development.&lt;/p&gt;


&lt;h2&gt;
  
  
  1️⃣ RapidKit Core: The Brain
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Python&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Install:&lt;/strong&gt; &lt;code&gt;pip/pipx install rapidkit-core&lt;/code&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Role:&lt;/strong&gt; Project generation, module management, and architecture enforcement&lt;/p&gt;

&lt;p&gt;This is where the real work happens.&lt;/p&gt;

&lt;p&gt;RapidKit Core is a Python-powered engine that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generates FastAPI and NestJS projects with clean architecture&lt;/li&gt;
&lt;li&gt;Manages 27+ plug-and-play modules (auth, databases, caching, logging, etc.)&lt;/li&gt;
&lt;li&gt;Maintains project structure and tracks file changes&lt;/li&gt;
&lt;li&gt;Handles dependency resolution and environment setup&lt;/li&gt;
&lt;li&gt;Powers the CLI and VS Code extension behind the scenes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rapidkit create project fastapi.standard my-api
rapidkit add module settings
rapidkit add module auth_core
rapidkit add module db_postgres
rapidkit add module redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In four commands, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A production-ready FastAPI project&lt;/li&gt;
&lt;li&gt;Multi-source configuration management&lt;/li&gt;
&lt;li&gt;PBKDF2 password hashing + HMAC token signing&lt;/li&gt;
&lt;li&gt;PostgreSQL with async SQLAlchemy and connection pooling&lt;/li&gt;
&lt;li&gt;Redis caching with retry logic&lt;/li&gt;
&lt;li&gt;Docker and health endpoints included&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Module System:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;27+ free modules across 13 categories&lt;/li&gt;
&lt;li&gt;Uniform architecture: every module has &lt;code&gt;module.yaml&lt;/code&gt;, &lt;code&gt;docs/usage.md&lt;/code&gt;, and &lt;code&gt;generate.py&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Framework variants: each module supports FastAPI and NestJS&lt;/li&gt;
&lt;li&gt;Environment overrides: &lt;code&gt;RAPIDKIT_&amp;lt;MODULE&amp;gt;_&amp;lt;SETTING&amp;gt;&lt;/code&gt; pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Generation Workflow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.yaml → generate.py → vendor artifacts → framework plugin → project files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No templates. No boilerplate copy-paste. Just &lt;strong&gt;generated, version-tracked code&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2️⃣ RapidKit CLI: The Bridge
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Language:&lt;/strong&gt; Node.js (TypeScript)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Install:&lt;/strong&gt; &lt;code&gt;npm install -g rapidkit&lt;/code&gt; (or use &lt;code&gt;npx&lt;/code&gt;)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Role:&lt;/strong&gt; Developer-friendly interface and workspace orchestration&lt;/p&gt;

&lt;p&gt;The CLI is your primary interface with RapidKit.&lt;/p&gt;

&lt;p&gt;It bridges the gap between your terminal and the Python engine, handling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workspace creation and management&lt;/li&gt;
&lt;li&gt;Project lifecycle commands (&lt;code&gt;init&lt;/code&gt;, &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Environment detection (Python, Node, Poetry, etc.)&lt;/li&gt;
&lt;li&gt;Command delegation to projects or Core&lt;/li&gt;
&lt;li&gt;Cross-platform compatibility (Windows, Linux, macOS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why Node.js?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because most developers already have Node installed.&lt;/p&gt;

&lt;p&gt;You don't need to think about Python environments or Poetry setup — the CLI handles it automatically when you create a workspace.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example workflow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a workspace (sets up Python environment)&lt;/span&gt;
npx rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace

&lt;span class="c"&gt;# Create projects&lt;/span&gt;
rapidkit create project fastapi.standard api-gateway
rapidkit create project nestjs.standard user-service

&lt;span class="c"&gt;# Start developing&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;api-gateway
rapidkit dev  &lt;span class="c"&gt;# Starts FastAPI server at :8000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLI is smart:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inside workspace directory?&lt;/strong&gt; Uses workspace &lt;code&gt;.venv/bin/rapidkit&lt;/code&gt; (shared Core)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outside workspace?&lt;/strong&gt; Uses npm bridge to invoke Core&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inside a project?&lt;/strong&gt; Detects &lt;code&gt;.rapidkit/&lt;/code&gt; and runs project commands (&lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Command &lt;code&gt;rapidkit&lt;/code&gt; (no npx)?&lt;/strong&gt; Looks for workspace virtualenv first, then global install&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3️⃣ RapidKit for VS Code: The Interface
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Platform:&lt;/strong&gt; VS Code Extension&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Install:&lt;/strong&gt; &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;VS Code Marketplace&lt;/a&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Role:&lt;/strong&gt; Visual project management and discovery&lt;/p&gt;

&lt;p&gt;Some developers prefer the command line.&lt;br&gt;
Others prefer a GUI.&lt;/p&gt;

&lt;p&gt;RapidKit for VS Code gives you both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Welcome Panel:&lt;/strong&gt; Central hub for workspaces and projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Module Browser:&lt;/strong&gt; Browse and install 27+ modules with one click&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Setup Status:&lt;/strong&gt; Verify your development environment (Python, CLI, Core)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Workspace Health:&lt;/strong&gt; Check any workspace for issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Project Creation:&lt;/strong&gt; Visual wizard for FastAPI/NestJS projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sidebar Integration:&lt;/strong&gt; All your workspaces and projects in one place&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open VS Code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl+Shift+P&lt;/code&gt; → "RapidKit: Create Project"&lt;/li&gt;
&lt;li&gt;Choose FastAPI or NestJS&lt;/li&gt;
&lt;li&gt;Enter project name&lt;/li&gt;
&lt;li&gt;Done.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your project is ready with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full project structure&lt;/li&gt;
&lt;li&gt;Dependencies configured&lt;/li&gt;
&lt;li&gt;Dev server ready to start&lt;/li&gt;
&lt;li&gt;API docs waiting at &lt;code&gt;/docs&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No terminal commands needed.&lt;/p&gt;


&lt;h3&gt;
  
  
  How They Work Together
&lt;/h3&gt;

&lt;p&gt;Here's the real power:&lt;/p&gt;

&lt;p&gt;Each tool handles what it's best at, but they're &lt;strong&gt;deeply integrated&lt;/strong&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Scenario 1: CLI-First Workflow
&lt;/h4&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create workspace via CLI&lt;/span&gt;
npx rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace

&lt;span class="c"&gt;# Create project via CLI&lt;/span&gt;
rapidkit create project fastapi.standard api

&lt;span class="c"&gt;# Open in VS Code&lt;/span&gt;
code &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; VS Code extension auto-discovers the workspace, shows all projects in the sidebar, and offers module installation via GUI.&lt;/p&gt;
&lt;h4&gt;
  
  
  Scenario 2: VS Code-First Workflow
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Open VS Code&lt;/li&gt;
&lt;li&gt;Use extension to create workspace&lt;/li&gt;
&lt;li&gt;Use extension to create projects&lt;/li&gt;
&lt;li&gt;Use extension to install modules&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt; Everything is tracked in &lt;code&gt;~/.rapidkit/workspaces.json&lt;/code&gt;. Open a terminal and &lt;code&gt;rapidkit&lt;/code&gt; commands work instantly.&lt;/p&gt;
&lt;h4&gt;
  
  
  Scenario 3: Mixed Workflow (Most Common)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Use CLI for fast project creation&lt;/li&gt;
&lt;li&gt;Use VS Code for module browsing and installation&lt;/li&gt;
&lt;li&gt;Use CLI for development commands (&lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;test&lt;/code&gt;, &lt;code&gt;build&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Use VS Code for health checks and workspace management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The ecosystem adapts to your workflow.&lt;/strong&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  RapidKit Modules: The Building Blocks
&lt;/h3&gt;

&lt;p&gt;RapidKit Core provides &lt;strong&gt;27+ production-ready modules&lt;/strong&gt; organized into 13 categories:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🔐 Authentication &amp;amp; Authorization&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;auth/core&lt;/code&gt; — PBKDF2 password hashing + HMAC tokens&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auth/api_keys&lt;/code&gt; — API key management&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auth/oauth&lt;/code&gt; — OAuth2 providers (Google, GitHub, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auth/session&lt;/code&gt; — Session management&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auth/passwordless&lt;/code&gt; — Magic link authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;💾 Database&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;database/db_postgres&lt;/code&gt; — Async/sync PostgreSQL with pooling&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;database/db_mongo&lt;/code&gt; — MongoDB integration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;database/db_sqlite&lt;/code&gt; — SQLite for prototyping&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚡ Caching &amp;amp; Performance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cache/redis&lt;/code&gt; — Async Redis with retry logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🔒 Security&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;security/cors&lt;/code&gt; — CORS middleware with whitelisting&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;security/headers&lt;/code&gt; — Security headers (CSP, HSTS, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;security/rate_limiting&lt;/code&gt; — Rate limiting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;📧 Communication&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;communication/email&lt;/code&gt; — Email sending&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;communication/notifications&lt;/code&gt; — Push notifications&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⚙️ Essentials&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;essentials/settings&lt;/code&gt; — Multi-source configuration&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;essentials/middleware&lt;/code&gt; — Custom middleware&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;essentials/logging&lt;/code&gt; — Structured logging&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;essentials/deployment&lt;/code&gt; — Deployment configs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;📊 Observability&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;observability/core&lt;/code&gt; — Metrics and tracing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;⏱️ Background Tasks&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;tasks/celery&lt;/code&gt; — Celery integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;👥 User Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;users/core&lt;/code&gt; — User models and CRUD&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;users/profiles&lt;/code&gt; — User profiles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Every module provides:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Framework variants (FastAPI + NestJS)&lt;/li&gt;
&lt;li&gt;✅ Health endpoint (&lt;code&gt;/api/health/module/&amp;lt;name&amp;gt;&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;✅ Environment-based configuration&lt;/li&gt;
&lt;li&gt;✅ Usage documentation (&lt;code&gt;docs/usage.md&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;✅ Testing setup&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Why Three Tools Instead of One?
&lt;/h3&gt;

&lt;p&gt;Because &lt;strong&gt;focus matters&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python Core:&lt;/strong&gt; Best for project generation and module logic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Node.js CLI:&lt;/strong&gt; Best for developer accessibility and environment detection&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code Extension:&lt;/strong&gt; Best for visual discovery and onboarding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trying to cram everything into one tool creates complexity.&lt;br&gt;
Separating concerns creates &lt;strong&gt;simplicity&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  Under the Hood: Architecture
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────┐
│       VS Code Extension                 │
│  (Visual interface &amp;amp; workspace manager) │
└────────────────┬────────────────────────┘
                 │
                 ▼
┌─────────────────────────────────────────┐
│          RapidKit CLI (npm)             │
│    (Command routing &amp;amp; delegation)       │
└────────────────┬────────────────────────┘
                 │
      ┏━━━━━━━━━┻━━━━━━━━━┓
      ▼                    ▼
┌──────────────┐   ┌──────────────────┐
│ Project CLI  │   │  RapidKit Core   │
│  (Launcher)  │   │ (Python Engine)  │
└──────────────┘   └──────────────────┘
      │                    │
      └─────────┬──────────┘
                ▼
      ┌──────────────────┐
      │ Generated Project│
      │ (FastAPI/NestJS) │
      └──────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Key insight:&lt;/strong&gt; The CLI and Extension never generate code directly. They delegate to &lt;strong&gt;RapidKit Core&lt;/strong&gt;, which ensures consistency across all entry points.&lt;/p&gt;


&lt;h3&gt;
  
  
  What This Means for You
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;If you're a solo developer:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the CLI for speed&lt;/li&gt;
&lt;li&gt;Use VS Code for discovery&lt;/li&gt;
&lt;li&gt;Pick what fits your workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you're on a team:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use VS Code for onboarding&lt;/li&gt;
&lt;li&gt;Use CLI for automation and CI/CD&lt;/li&gt;
&lt;li&gt;Use workspaces to enforce consistency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;If you're evaluating RapidKit:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with workspace creation (&lt;code&gt;npx rapidkit my-workspace&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Install VS Code extension to explore modules visually&lt;/li&gt;
&lt;li&gt;Try all three approaches and pick your favorite&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There's no lock-in. All three tools share the same project format.&lt;/p&gt;


&lt;h3&gt;
  
  
  The Vision: Invisible Infrastructure
&lt;/h3&gt;

&lt;p&gt;The goal isn't to make you think about RapidKit.&lt;/p&gt;

&lt;p&gt;The goal is to make you &lt;strong&gt;forget about boilerplate&lt;/strong&gt; and focus on building features.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core&lt;/strong&gt; generates the foundation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CLI&lt;/strong&gt; keeps you productive&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code&lt;/strong&gt; keeps you organized&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And behind the scenes, everything stays consistent, maintainable, and production-ready.&lt;/p&gt;


&lt;h3&gt;
  
  
  Try It Yourself
&lt;/h3&gt;

&lt;p&gt;Pick your entry point:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx rapidkit my-workspace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;VS Code:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;RapidKit extension&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Ctrl+Shift+P&lt;/code&gt; → "RapidKit: Create Workspace"&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Python directly:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Recommended: isolated install&lt;/span&gt;
pipx &lt;span class="nb"&gt;install &lt;/span&gt;rapidkit-core

&lt;span class="c"&gt;# Or: standard install&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;rapidkit-core

&lt;span class="c"&gt;# Create project&lt;/span&gt;
rapidkit create project fastapi.standard my-api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;💡 Recommendation:&lt;/strong&gt; Start with the &lt;strong&gt;workspace approach&lt;/strong&gt; (&lt;code&gt;npx rapidkit my-workspace&lt;/code&gt;) for the best experience — it handles all prerequisites automatically.&lt;/p&gt;

&lt;p&gt;All three paths lead to the same place: &lt;strong&gt;production-ready FastAPI and NestJS projects&lt;/strong&gt; in minutes.&lt;/p&gt;




&lt;h3&gt;
  
  
  Learn More
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;📦 &lt;strong&gt;npm CLI:&lt;/strong&gt; &lt;a href="https://www.npmjs.com/package/rapidkit" rel="noopener noreferrer"&gt;npmjs.com/package/rapidkit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐍 &lt;strong&gt;Python Core:&lt;/strong&gt; &lt;a href="https://pypi.org/project/rapidkit-core/" rel="noopener noreferrer"&gt;pypi.org/project/rapidkit-core&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧩 &lt;strong&gt;VS Code Extension:&lt;/strong&gt; &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;marketplace.visualstudio.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🌐 &lt;strong&gt;Website:&lt;/strong&gt; &lt;a href="https://www.getrapidkit.com" rel="noopener noreferrer"&gt;getrapidkit.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Next Article
&lt;/h3&gt;

&lt;p&gt;In the next post, we'll explore &lt;strong&gt;Workspace-First Development&lt;/strong&gt; — why organizing multiple projects in one environment changes everything for backend teams.&lt;/p&gt;

&lt;p&gt;Stay tuned.&lt;/p&gt;

</description>
      <category>rapidkit</category>
      <category>opensource</category>
      <category>api</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Stop Rewriting Backend Foundations: Introducing RapidKit</title>
      <dc:creator>RapidKit </dc:creator>
      <pubDate>Tue, 10 Feb 2026 09:13:12 +0000</pubDate>
      <link>https://forem.com/rapidkit/stop-rewriting-backend-foundations-introducing-rapidkit-48fg</link>
      <guid>https://forem.com/rapidkit/stop-rewriting-backend-foundations-introducing-rapidkit-48fg</guid>
      <description>&lt;h3&gt;
  
  
  We’ve All Been Here
&lt;/h3&gt;

&lt;p&gt;You start a new backend project.&lt;/p&gt;

&lt;p&gt;Not the first one. Not the tenth one either.&lt;/p&gt;

&lt;p&gt;And before you write a single line of business logic, you’re already doing the same things again:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setting up project structure&lt;/li&gt;
&lt;li&gt;Choosing (again) how to organize layers and modules&lt;/li&gt;
&lt;li&gt;Wiring authentication, configs, logging&lt;/li&gt;
&lt;li&gt;Creating Docker files, environments, CI configs&lt;/li&gt;
&lt;li&gt;Debating architecture decisions you’ve already solved before&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of this is new.&lt;br&gt;
None of this moves the product forward.&lt;/p&gt;

&lt;p&gt;Yet it happens &lt;strong&gt;every single time&lt;/strong&gt;.&lt;/p&gt;


&lt;h3&gt;
  
  
  Backend Projects Rarely Fail Because of Features
&lt;/h3&gt;

&lt;p&gt;They fail because the &lt;strong&gt;foundation&lt;/strong&gt; is rushed, inconsistent, or impossible to scale.&lt;/p&gt;

&lt;p&gt;Different projects, different structures.&lt;br&gt;
Different teams, different conventions.&lt;br&gt;
Onboarding takes weeks.&lt;br&gt;
Maintenance becomes painful.&lt;/p&gt;

&lt;p&gt;After repeating this cycle across multiple teams and projects, one question kept coming up:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Why are we still rebuilding backend foundations from scratch?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h3&gt;
  
  
  This Is Why We Built RapidKit
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;RapidKit&lt;/strong&gt; is an open-source framework designed to give backend teams a &lt;strong&gt;solid, production-ready starting point&lt;/strong&gt; — without locking them into rigid abstractions.&lt;/p&gt;

&lt;p&gt;It’s not a template.&lt;br&gt;
It’s not a starter repo.&lt;/p&gt;

&lt;p&gt;It’s a &lt;strong&gt;scaffolding system&lt;/strong&gt; that generates and manages real projects you can evolve over time.&lt;/p&gt;


&lt;h3&gt;
  
  
  What RapidKit Focuses On
&lt;/h3&gt;

&lt;p&gt;RapidKit is built around a few core ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistency over cleverness&lt;/strong&gt;&lt;br&gt;
Every project starts with the same clean, predictable structure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Workspace-first development&lt;/strong&gt;&lt;br&gt;
Manage multiple services in one shared environment — ideal for teams and microservices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modular architecture&lt;/strong&gt;&lt;br&gt;
Authentication, databases, caching, logging, observability — added when you need them, not before.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Production readiness by default&lt;/strong&gt;&lt;br&gt;
Docker, environment management, testing, and CI are part of the foundation, not afterthoughts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Framework flexibility&lt;/strong&gt;&lt;br&gt;
Build APIs with &lt;strong&gt;FastAPI (Python)&lt;/strong&gt; or &lt;strong&gt;NestJS (TypeScript)&lt;/strong&gt; using a unified workflow.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  A Quick Look
&lt;/h3&gt;

&lt;p&gt;Creating a new backend doesn’t require days of setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create a workspace&lt;/span&gt;
rapidkit my-workspace
&lt;span class="nb"&gt;cd &lt;/span&gt;my-workspace

&lt;span class="c"&gt;# Create a project&lt;/span&gt;
rapidkit create project fastapi.standard my-api

&lt;span class="c"&gt;# Add features as modules&lt;/span&gt;
rapidkit add module auth
rapidkit add module database.postgres

&lt;span class="c"&gt;# Start development&lt;/span&gt;
rapidkit dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In minutes, you get a clean, structured, production-ready API — ready to build real features.&lt;/p&gt;




&lt;h3&gt;
  
  
  Who Is RapidKit For?
&lt;/h3&gt;

&lt;p&gt;RapidKit is especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Teams building &lt;strong&gt;multiple backend services&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Startups that need to move fast &lt;strong&gt;without cutting corners&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Solo developers tired of rewriting boilerplate&lt;/li&gt;
&lt;li&gt;Companies that care about &lt;strong&gt;long-term maintainability&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Developers who value &lt;strong&gt;clean architecture and consistency&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s probably &lt;strong&gt;not&lt;/strong&gt; for projects that need a completely custom architecture from day one.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why This Is Just the Beginning
&lt;/h3&gt;

&lt;p&gt;This post is intentionally high-level.&lt;/p&gt;

&lt;p&gt;In upcoming articles, we’ll go deeper into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Workspace-first backend development&lt;/li&gt;
&lt;li&gt;How RapidKit’s module system works&lt;/li&gt;
&lt;li&gt;Designing scalable FastAPI projects&lt;/li&gt;
&lt;li&gt;Managing multiple services with shared tooling&lt;/li&gt;
&lt;li&gt;Writing your own RapidKit modules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RapidKit is evolving, and we’re building it openly.&lt;/p&gt;




&lt;h3&gt;
  
  
  Learn More
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;🌐 Website: &lt;a href="https://www.getrapidkit.com" rel="noopener noreferrer"&gt;https://www.getrapidkit.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 GitHub / Core Engine: &lt;a href="https://pypi.org/project/rapidkit-core/" rel="noopener noreferrer"&gt;https://pypi.org/project/rapidkit-core/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;📦 npm CLI: &lt;a href="https://www.npmjs.com/package/rapidkit" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/rapidkit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧩 VS Code Extension: &lt;a href="https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=rapidkit.rapidkit-vscode&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Final Thought
&lt;/h3&gt;

&lt;p&gt;Backend teams shouldn’t spend their energy reinventing foundations.&lt;/p&gt;

&lt;p&gt;They should spend it building products.&lt;/p&gt;

&lt;p&gt;That’s the problem RapidKit is trying to solve.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>rapidkit</category>
      <category>api</category>
      <category>python</category>
    </item>
  </channel>
</rss>
