<?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>DEV Community: Arun Yadav</title>
    <description>The latest articles on DEV Community by Arun Yadav (@itsdevcode).</description>
    <link>https://dev.to/itsdevcode</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4117982%2F5574f0ee-a19b-4ce6-bd55-52c21a7097e3.png</url>
      <title>DEV Community: Arun Yadav</title>
      <link>https://dev.to/itsdevcode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/itsdevcode"/>
    <language>en</language>
    <item>
      <title>PlanB: An AI That Challenges Your Plan Before Reality Does</title>
      <dc:creator>Arun Yadav</dc:creator>
      <pubDate>Sun, 04 Oct 2026 17:20:52 +0000</pubDate>
      <link>https://dev.to/itsdevcode/planb-an-ai-that-challenges-your-plan-before-reality-does-4gc2</link>
      <guid>https://dev.to/itsdevcode/planb-an-ai-that-challenges-your-plan-before-reality-does-4gc2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-weekend-2026-10-01"&gt;Hacktoberfest Weekend Challenge: Build for a Friend&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;p&gt;I have a friend who is good at making plans.&lt;/p&gt;

&lt;p&gt;But there is one problem: his plans usually depend on everything going right.&lt;/p&gt;

&lt;p&gt;The train arrives on time.&lt;br&gt;&lt;br&gt;
The internet works.&lt;br&gt;&lt;br&gt;
There is enough time.&lt;br&gt;&lt;br&gt;
Nothing unexpected happens.&lt;/p&gt;

&lt;p&gt;And that made me think:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What if AI didn't make Plan A for you, but instead helped you prepare for what could go wrong?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I built &lt;strong&gt;PlanB&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;PlanB is an AI-powered backup plan assistant built with &lt;strong&gt;Gemma&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You give PlanB the plan you already have. Instead of replacing it, PlanB looks at what your plan depends on and finds realistic things that could go wrong.&lt;/p&gt;

&lt;p&gt;For every risk, it gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Impact&lt;/li&gt;
&lt;li&gt;Warning signs&lt;/li&gt;
&lt;li&gt;Prevention&lt;/li&gt;
&lt;li&gt;A backup action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It also creates a &lt;strong&gt;Prepare Now&lt;/strong&gt; checklist, so you can take action before something goes wrong.&lt;/p&gt;

&lt;p&gt;But I wanted PlanB to handle something else too:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What happens when the problem has already happened?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's where &lt;strong&gt;Plan C&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;Tell PlanB what actually went wrong, and it uses your original plan, its earlier analysis, and the new situation to help you decide what to do next.&lt;/p&gt;

&lt;p&gt;The complete flow is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plan A → Find what could go wrong → Plan B → Something actually goes wrong → Plan C&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbm1qtzmxwo7rv1imyfzd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbm1qtzmxwo7rv1imyfzd.png" alt="PlanB home screen" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Let's take a real example.&lt;/p&gt;
&lt;h3&gt;
  
  
  Plan A
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Tomorrow I have a job interview in Delhi at 11 AM. My train leaves at 6 AM and I expect to reach Delhi by 9 AM.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;PlanB first understands the goal.&lt;/p&gt;

&lt;p&gt;Then it identifies things this plan depends on, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the train arriving with enough time before the interview&lt;/li&gt;
&lt;li&gt;reaching the station on time&lt;/li&gt;
&lt;li&gt;local transport being available in Delhi&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It then generates realistic risks, warning signs, prevention steps, and backup actions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx8uknukx2uuqykk2k3i1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx8uknukx2uuqykk2k3i1.png" alt="PlanB AI-generated risks and backup plans" width="800" height="637"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  But then reality changes...
&lt;/h3&gt;

&lt;p&gt;Suppose I tell PlanB:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;My train is running two hours late.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;PlanB doesn't start from zero.&lt;/p&gt;

&lt;p&gt;It already knows my original goal and the risks around it.&lt;/p&gt;

&lt;p&gt;It uses that context to create &lt;strong&gt;Plan C&lt;/strong&gt;, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immediate actions&lt;/li&gt;
&lt;li&gt;A revised plan&lt;/li&gt;
&lt;li&gt;Additional risks to watch for&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fov605m4kr768c0s8i4kk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fov605m4kr768c0s8i4kk.png" alt="PlanB Plan C recovery mode" width="800" height="652"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🌐 Live Demo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://planb-five-pink.vercel.app" rel="noopener noreferrer"&gt;https://planb-five-pink.vercel.app&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  🎥 Video Demo
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://youtu.be/xklFTVIHJAw" rel="noopener noreferrer"&gt;https://youtu.be/xklFTVIHJAw&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;PlanB is completely open source.&lt;/p&gt;
&lt;h3&gt;
  
  
  GitHub
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/itsdevcode/planb" rel="noopener noreferrer"&gt;https://github.com/itsdevcode/planb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I deliberately kept the architecture small and focused:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next.js Frontend
       ↓
FastAPI API
       ↓
PlannerService
       ↓
Gemma
       ↓
Pydantic Validation
       ↓
Structured Plan B / Plan C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no authentication, database, background queue, or unnecessary infrastructure in this MVP.&lt;/p&gt;

&lt;p&gt;For a weekend challenge, I wanted every part of the application to support the main idea.&lt;/p&gt;




&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Gemma is the core of PlanB
&lt;/h3&gt;

&lt;p&gt;Gemma isn't an extra chatbot added to the application.&lt;/p&gt;

&lt;p&gt;It powers the main reasoning behind both &lt;strong&gt;Plan B&lt;/strong&gt; and &lt;strong&gt;Plan C&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For Plan B, the backend asks Gemma to analyze the user's existing plan and return structured information.&lt;/p&gt;

&lt;p&gt;The response looks like this:&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;"summary"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"assumptions"&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="s2"&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;"risks"&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;"risk"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"impact"&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;"warning_signs"&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="s2"&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;"prevention"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"backup"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"prepare_now"&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="s2"&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;One important decision I made while designing the prompt was to focus on &lt;strong&gt;realistic problems instead of extreme ones&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, I don't want PlanB to say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your train could crash.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I want it to say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your train could be delayed enough that you miss the interview.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;PlanB should help people prepare, not make them afraid.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Plan C
&lt;/h3&gt;

&lt;p&gt;Plan C gives Gemma three important pieces of context:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The original Plan A&lt;/li&gt;
&lt;li&gt;The Plan B analysis&lt;/li&gt;
&lt;li&gt;What actually went wrong&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Gemma then generates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immediate actions&lt;/li&gt;
&lt;li&gt;A revised plan&lt;/li&gt;
&lt;li&gt;Additional risks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means Plan C isn't just a new unrelated AI response. It continues from the context PlanB already understands.&lt;/p&gt;

&lt;h3&gt;
  
  
  Structured AI Output with Pydantic
&lt;/h3&gt;

&lt;p&gt;I didn't want the frontend to depend on unpredictable AI text.&lt;/p&gt;

&lt;p&gt;The FastAPI backend validates Gemma's output using Pydantic models.&lt;/p&gt;

&lt;p&gt;For example:&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;class&lt;/span&gt; &lt;span class="nc"&gt;Risk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;impact&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Literal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&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;medium&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;high&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;warning_signs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&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;prevention&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;backup&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the model response doesn't match the expected structure, the application doesn't blindly treat it as valid data.&lt;/p&gt;

&lt;p&gt;This gives the AI layer a clear contract with the rest of the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Backend
&lt;/h3&gt;

&lt;p&gt;The backend is built with &lt;strong&gt;FastAPI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are two main endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /api/v1/plans/analyze
POST /api/v1/plans/recover
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;/analyze&lt;/code&gt; takes Plan A and creates the Plan B analysis.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/recover&lt;/code&gt; takes the original context plus what went wrong and creates Plan C.&lt;/p&gt;

&lt;p&gt;The backend is deployed on &lt;strong&gt;Render&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;p&gt;The frontend is built with &lt;strong&gt;Next.js&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I kept the user flow intentionally simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Describe Plan A
      ↓
Analyze Plan
      ↓
Understand the Goal
      ↓
Find Assumptions
      ↓
Find Possible Problems
      ↓
Prepare Now
      ↓
Something Went Wrong
      ↓
Build Plan C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend is deployed on Vercel.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing
&lt;/h3&gt;

&lt;p&gt;I also added automated tests for the main API behavior.&lt;/p&gt;

&lt;p&gt;Gemma calls are mocked in the test suite, so tests can verify the application contract without making real AI requests.&lt;/p&gt;

&lt;p&gt;The MVP tests cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Health endpoint&lt;/li&gt;
&lt;li&gt;Successful Plan B analysis&lt;/li&gt;
&lt;li&gt;Invalid Plan A validation&lt;/li&gt;
&lt;li&gt;Successful Plan C recovery&lt;/li&gt;
&lt;li&gt;Invalid recovery input&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Current result:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  One Bug Taught Me an Important Lesson
&lt;/h3&gt;

&lt;p&gt;During development, Gemma sometimes returned an incomplete response.&lt;/p&gt;

&lt;p&gt;At first, it looked like the AI or JSON validation was broken.&lt;/p&gt;

&lt;p&gt;The real problem was much simpler.&lt;/p&gt;

&lt;p&gt;I had configured an output token limit that was too small for the structured response I was asking Gemma to generate.&lt;/p&gt;

&lt;p&gt;Removing that unnecessary restriction fixed the problem.&lt;/p&gt;

&lt;p&gt;It reminded me that building an AI application isn't just about writing a prompt.&lt;/p&gt;

&lt;p&gt;The model, generation settings, validation, backend, and frontend all have to work together.&lt;/p&gt;

&lt;p&gt;I also learned that AI responses can take longer than normal API requests.&lt;/p&gt;

&lt;p&gt;Instead of pretending the response is instant, PlanB shows a clear loading state while the plan is being analyzed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;PlanB uses &lt;strong&gt;Gemma, an open-weight model&lt;/strong&gt;, as its reasoning engine.&lt;/p&gt;

&lt;p&gt;That matters to me because the intelligence behind the product doesn't have to be permanently tied to one closed model.&lt;/p&gt;

&lt;p&gt;The application has a simple boundary:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Plan
  ↓
AI Reasoning
  ↓
Structured Schema
  ↓
Application
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Today, I use Gemma through an API because it allowed me to build and ship the idea quickly during the weekend challenge.&lt;/p&gt;

&lt;p&gt;But because Gemma is open-weight, there is a path to running the model through different infrastructure or even locally with suitable hardware in the future.&lt;/p&gt;

&lt;p&gt;That is especially interesting for PlanB.&lt;/p&gt;

&lt;p&gt;People might use it for plans involving:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Job interviews&lt;/li&gt;
&lt;li&gt;Travel&lt;/li&gt;
&lt;li&gt;Work&lt;/li&gt;
&lt;li&gt;Personal events&lt;/li&gt;
&lt;li&gt;Projects&lt;/li&gt;
&lt;li&gt;Family plans&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of those plans can contain private information.&lt;/p&gt;

&lt;p&gt;Having an open-weight model creates more options for where that reasoning can happen.&lt;/p&gt;

&lt;p&gt;For me, that's one of the most exciting parts of open innovation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;It gives developers more control over how intelligence becomes part of their applications.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Best Use of Gemma
&lt;/h3&gt;

&lt;p&gt;Gemma is the core reasoning engine behind PlanB.&lt;/p&gt;

&lt;p&gt;It analyzes Plan A, identifies what the plan depends on, finds realistic failure scenarios, creates preparation steps, and generates Plan C when something actually goes wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Use of Render
&lt;/h3&gt;

&lt;p&gt;PlanB's FastAPI backend is deployed on Render.&lt;/p&gt;

&lt;p&gt;The Render service handles the API layer connecting the Next.js frontend with Gemma and serves both the Plan B analysis and Plan C recovery workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thought
&lt;/h2&gt;

&lt;p&gt;I started this project with a simple observation about a friend.&lt;/p&gt;

&lt;p&gt;He didn't need another tool to make plans.&lt;/p&gt;

&lt;p&gt;He needed something that could challenge the plan he already had.&lt;/p&gt;

&lt;p&gt;That became &lt;strong&gt;PlanB&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And after building it, I realized the idea applies to much more than one person.&lt;/p&gt;

&lt;p&gt;PlanB doesn't try to predict the future.&lt;/p&gt;

&lt;p&gt;It simply helps you stay ready when things don't go as planned.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Because when Plan A fails, you should always have a Plan B.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>hf26challenge</category>
    </item>
    <item>
      <title>Mastering Routing in FastAPI: From Flat Files to Clean Architecture</title>
      <dc:creator>Arun Yadav</dc:creator>
      <pubDate>Wed, 09 Sep 2026 17:37:32 +0000</pubDate>
      <link>https://dev.to/itsdevcode/mastering-routing-in-fastapi-from-flat-files-to-clean-architecture-427g</link>
      <guid>https://dev.to/itsdevcode/mastering-routing-in-fastapi-from-flat-files-to-clean-architecture-427g</guid>
      <description>&lt;p&gt;When building an API with FastAPI, it’s deceptively easy to dump every endpoint into &lt;code&gt;main.py&lt;/code&gt;. A few &lt;code&gt;@app.get()&lt;/code&gt; decorators here, a couple of &lt;code&gt;@app.post()&lt;/code&gt; decorators there, and everything works.&lt;/p&gt;

&lt;p&gt;Then your project grows. Suddenly, &lt;code&gt;main.py&lt;/code&gt; is an 800-line monolith, team members are constantly hitting Git merge conflicts, and nobody knows where the user authentication logic ends and the billing logic begins.&lt;/p&gt;

&lt;p&gt;FastAPI solves this with &lt;code&gt;APIRouter&lt;/code&gt;. Here is how to structure your routing cleanly from day one.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Core Tool: &lt;code&gt;APIRouter&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Think of &lt;code&gt;APIRouter&lt;/code&gt; as a mini FastAPI app that doesn’t run on its own. It groups related path operations together, which you then mount onto your main application.&lt;/p&gt;

&lt;p&gt;A typical modular directory structure looks 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;my_project/
├── app/
│   ├── routers/
│   │   ├── users.py
│   │   └── items.py
│   ├── dependencies.py
│   └── main.py
└── requirements.txt

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

&lt;/div&gt;



&lt;p&gt;In your module (&lt;code&gt;app/routers/users.py&lt;/code&gt;), define your router:&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;APIRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HTTPException&lt;/span&gt;

&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&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;/&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;list_users&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;id&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;username&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;alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&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;/{user_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;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;span class="nb"&gt;int&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;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_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;username&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;alice&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;Then, register it in &lt;code&gt;app/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;app.routers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;users&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;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&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;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tags&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;Users&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;Two key parameters to notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;prefix&lt;/code&gt;&lt;/strong&gt;: Prepend &lt;code&gt;/users&lt;/code&gt; to every endpoint in the router. Notice how &lt;code&gt;users.py&lt;/code&gt; uses &lt;code&gt;/&lt;/code&gt; and &lt;code&gt;/{user_id}&lt;/code&gt; instead of repeating &lt;code&gt;/users&lt;/code&gt; everywhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;tags&lt;/code&gt;&lt;/strong&gt;: Groups these endpoints together in FastAPI's auto-generated Swagger UI (&lt;code&gt;/docs&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Cleaner Endpoints with Shared Dependencies
&lt;/h2&gt;

&lt;p&gt;One of the biggest advantages of &lt;code&gt;APIRouter&lt;/code&gt; is attaching security checks or common dependencies to an entire group of routes at once.&lt;/p&gt;

&lt;p&gt;Instead of writing &lt;code&gt;Depends(verify_token)&lt;/code&gt; on 15 separate endpoints, apply it to the router level:&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;# app/routers/admin.py
&lt;/span&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;APIRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Depends&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.dependencies&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;require_admin_role&lt;/span&gt;

&lt;span class="c1"&gt;# Every route attached to this router will now require admin access
&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tags&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;Admin&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;dependencies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&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;require_admin_role&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nd"&gt;@router.delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/purge-cache&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;purge_cache&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;cache cleared&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;h2&gt;
  
  
  3. Nesting Routers for Sub-Resources
&lt;/h2&gt;

&lt;p&gt;Real-world APIs often have hierarchical relationships—such as comments belonging to a specific post (&lt;code&gt;/posts/{post_id}/comments&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Rather than hardcoding long prefix strings, routers can be nested inside other routers:&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;# app/routers/comments.py
&lt;/span&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;APIRouter&lt;/span&gt;

&lt;span class="n"&gt;comments_router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nd"&gt;@comments_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;/&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_comments&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;post_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="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;post_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;post_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;comments&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/routers/posts.py
&lt;/span&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;APIRouter&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.routers.comments&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;comments_router&lt;/span&gt;

&lt;span class="n"&gt;posts_router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/posts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tags&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;Posts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Mount comments directly under a specific post
&lt;/span&gt;&lt;span class="n"&gt;posts_router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;comments_router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/{post_id}/comments&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tags&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;Comments&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;Now, mounting &lt;code&gt;posts_router&lt;/code&gt; inside your &lt;code&gt;main.py&lt;/code&gt; automatically exposes both &lt;code&gt;/posts&lt;/code&gt; and &lt;code&gt;/posts/{post_id}/comments&lt;/code&gt; cleanly.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. API Versioning Without Headaches
&lt;/h2&gt;

&lt;p&gt;Versioning is simple when your routing is modular. You can bundle whole sets of routers under a version prefix:&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;# app/main.py
&lt;/span&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="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;APIRouter&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;app.routers&lt;/span&gt; &lt;span class="kn"&gt;import&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;items&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="c1"&gt;# Create a v1 router
&lt;/span&gt;&lt;span class="n"&gt;api_v1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/v1&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_v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&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;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/users&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tags&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;Users&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_v1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/items&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tags&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;Items&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c1"&gt;# Include the full v1 bundle into the main app
&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_v1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;When it's time for &lt;code&gt;v2&lt;/code&gt;, you can spin up an &lt;code&gt;api_v2&lt;/code&gt; router alongside it without touching older client integrations.&lt;/p&gt;




</description>
      <category>api</category>
      <category>architecture</category>
      <category>backend</category>
      <category>python</category>
    </item>
  </channel>
</rss>
