<?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: Javad Zarezadeh</title>
    <description>The latest articles on DEV Community by Javad Zarezadeh (@justjayzee).</description>
    <link>https://dev.to/justjayzee</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%2F2120062%2Fbb098715-8751-4964-ad2c-e3be91cbf64b.png</url>
      <title>DEV Community: Javad Zarezadeh</title>
      <link>https://dev.to/justjayzee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/justjayzee"/>
    <language>en</language>
    <item>
      <title>FastForge: A Modern FastAPI Boilerplate for Authentication-Driven Applications</title>
      <dc:creator>Javad Zarezadeh</dc:creator>
      <pubDate>Sat, 18 Oct 2025 13:41:24 +0000</pubDate>
      <link>https://dev.to/justjayzee/fastforge-a-modern-fastapi-boilerplate-for-authentication-driven-applications-2f57</link>
      <guid>https://dev.to/justjayzee/fastforge-a-modern-fastapi-boilerplate-for-authentication-driven-applications-2f57</guid>
      <description>&lt;p&gt;Are you tired of losing time setting up authentication for your FastAPI projects? &lt;strong&gt;FastForge&lt;/strong&gt; is a lightweight, secure, and scalable FastAPI boilerplate built for rapid development of authentication-driven apps. It features robust authentication with phone-based OTP verification and role-based access control, using modern Python tools and best practices.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/javadzarezadeh/fastforge" rel="noopener noreferrer"&gt;View FastForge on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why FastForge?
&lt;/h2&gt;

&lt;p&gt;Let’s be real: setting up authentication is a pain. I’ve lost days tweaking templates that didn’t quite fit my needs: too complex, too rigid, or just not my style. The official &lt;strong&gt;Full-stack FastAPI Template&lt;/strong&gt; is awesome, but I wanted something leaner, faster, and built for phone-based OTP flows without leaning on third-party OAuth2 servers. So, I rolled up my sleeves and created &lt;strong&gt;FastForge&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Principles
&lt;/h2&gt;

&lt;p&gt;FastForge is built on a few non-negotiables:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;KISS Principle&lt;/strong&gt; – Minimal dependencies and clear.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security First&lt;/strong&gt; – Protection built-in from the start.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Practices&lt;/strong&gt; – No hacky shortcuts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt; – Ready to grow when your app takes off.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Features at a Glance
&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;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Phone/Email OTP Auth&lt;/td&gt;
&lt;td&gt;Secure, flexible registration/login&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JWT + Refresh Tokens&lt;/td&gt;
&lt;td&gt;Bulletproof session management&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Role-Based Access Control (RBAC)&lt;/td&gt;
&lt;td&gt;Multiple, flexible user roles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email Verification &amp;amp; Mock Service&lt;/td&gt;
&lt;td&gt;Out of the box&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OTP Attempt Limiting&lt;/td&gt;
&lt;td&gt;Keeps brute-force attackers at bay&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UUIDs for All IDs&lt;/td&gt;
&lt;td&gt;Scalable and reliable in distributed systems&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Soft Delete &amp;amp; Identifier Hashing&lt;/td&gt;
&lt;td&gt;Privacy and data safety built-in&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Health Checks / Pre-commit Hooks&lt;/td&gt;
&lt;td&gt;Quality you can trust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Docker &amp;amp; Local Setup&lt;/td&gt;
&lt;td&gt;Start up YOUR way&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Authentication &amp;amp; Authorization
&lt;/h2&gt;

&lt;p&gt;Authentication is usually the thing developers dread, and end up procrastinating for days (been there so many times 😁). FastForge gives you a modern phone number/OTP setup. No more old-school username/password headaches or dependency on third-party OAuth. In FastForge, your phone (or email) is your username, and OTP is your password. All built on OAuth2 standards, so you get compatibility with Swagger UI for easy testing.&lt;/p&gt;

&lt;p&gt;Here’s what you get out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OTP attempt limiting (a real brute-force stopper)&lt;/li&gt;
&lt;li&gt;Email verification&lt;/li&gt;
&lt;li&gt;JWT management with refresh token rotation&lt;/li&gt;
&lt;li&gt;Login with phone or email, form data and JSON payloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Works great for web and mobile.&lt;/p&gt;

&lt;h2&gt;
  
  
  Role-Based Access Control (RBAC)
&lt;/h2&gt;

&lt;p&gt;Access control shouldn’t slow you down or lock you into spaghetti code. FastForge uses JWT to encode roles (so no extra DB checks!), supports many-to-many user-role relationships, and adapts to all kinds of systems: imagine a football club app with roles for Manager, Player, Staff, and Fan. Users can have multiple roles at once, just like a player-manager who’s also a fan (think Kenny Dalglish). Roles are assigned via the &lt;code&gt;UserRoleLink&lt;/code&gt; table, right in the core.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tech Stack &amp;amp; Quality
&lt;/h2&gt;

&lt;p&gt;These are the tools that power FastForge:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI (by &lt;a class="mentioned-user" href="https://dev.to/tiangolo"&gt;@tiangolo&lt;/a&gt;)&lt;/strong&gt; – High-performance web framework, with flawless API docs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLModel&lt;/strong&gt; – Combines SQLAlchemy and Pydantic for type-safe DB ops&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; &amp;amp; &lt;strong&gt;Redis&lt;/strong&gt; – Solid backends, quick OTP storage (TTL configured)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyJWT&lt;/strong&gt; – Secure token management&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SlowAPI&lt;/strong&gt; – Rate limiting, fast and simple&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;uv&lt;/strong&gt; – Lightning-fast Python dependency installer&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pydantic&lt;/strong&gt; – Input and data validation made easy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alembic&lt;/strong&gt; – DB migrations are no longer scary&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ruff&lt;/strong&gt; and &lt;strong&gt;isort&lt;/strong&gt; – Code quality and style&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pytest/pytest-asyncio/pytest-cov&lt;/strong&gt; – Testing and coverage&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Project Structure
&lt;/h2&gt;

&lt;p&gt;Here’s how everything fits together (so you won’t get lost):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fastforge/
├── src/
│   ├── main.py               # App entry point
│   ├── auth.py               # Auth logic
│   ├── routes/               # REST endpoints
│   ├── models/               # ORM models
│   └── config.py             # Centralized config
├── migrations/               # Alembic migrations
├── tests/                    # Test suite
├── .env.example              # Example config
├── Dockerfile/docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For an extended dive, check the README!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Ready to code? FastForge works both locally and with Docker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prerequisites
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Python&lt;/strong&gt;: 3.13 or higher&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;: Latest, with Compose&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL &amp;amp; Redis&lt;/strong&gt; (provided via Docker, or install locally)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick Start With Docker
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/javadzarezadeh/fastforge.git
&lt;span class="nb"&gt;cd &lt;/span&gt;fastforge
docker compose up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;API lives at &lt;code&gt;http://localhost:8000&lt;/code&gt;, docs at &lt;code&gt;/docs&lt;/code&gt; and &lt;code&gt;/redoc&lt;/code&gt;, and Adminer at &lt;code&gt;http://localhost:8081&lt;/code&gt; (handy for DB peeking).&lt;/p&gt;

&lt;h3&gt;
  
  
  Local Development
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/javadzarezadeh/fastforge.git
&lt;span class="nb"&gt;cd &lt;/span&gt;fastforge
uv &lt;span class="nb"&gt;sync
cp&lt;/span&gt; .env.example .env
uv run alembic upgrade &lt;span class="nb"&gt;head
&lt;/span&gt;uv run fastapi run src/main.py &lt;span class="nt"&gt;--port&lt;/span&gt; 8000 &lt;span class="nt"&gt;--host&lt;/span&gt; 0.0.0.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check your terminal for OTP logs (when using mock SMS), and for Docker, get them via &lt;code&gt;docker compose logs app&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  API Docs
&lt;/h2&gt;

&lt;p&gt;Hit the full interactive docs at&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;http://localhost:8000/docs&lt;/code&gt; (Swagger UI)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;http://localhost:8000/redoc&lt;/code&gt; (ReDoc)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Contributing &amp;amp; Community
&lt;/h2&gt;

&lt;p&gt;Open-source is better when we build it together! Bugs, features, docs, or feedback. Just fork, branch, code, and PR. Pre-commit hooks and tests keep things tight.&lt;/p&gt;

&lt;p&gt;I always appreciate hearing from you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication flow usability&lt;/li&gt;
&lt;li&gt;Documentation clarity&lt;/li&gt;
&lt;li&gt;Real-world performance&lt;/li&gt;
&lt;li&gt;Cool features on your wish list&lt;/li&gt;
&lt;li&gt;Feedback for making FastForge even easier for developers&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Call To Action
&lt;/h2&gt;

&lt;p&gt;Ready to save time and boost security? Try FastForge now:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Star the repo&lt;/strong&gt; on GitHub&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test it in your next project&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Share your results with fellow devs&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Help improve by contributing&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Support development with a donation&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Together, we can make FastAPI authentication painless and powerful!&lt;/p&gt;

&lt;p&gt;Find FastForge on GitHub: &lt;a href="https://github.com/javadzarezadeh/fastforge" rel="noopener noreferrer"&gt;https://github.com/javadzarezadeh/fastforge&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Support the Project
&lt;/h3&gt;

&lt;p&gt;If FastForge speeds up your workflow, please consider donating. Your support keeps the project growing and improving.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Crypto donations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bitcoin&lt;/strong&gt;: &lt;code&gt;bc1qnk9dvr2zpp42rdrf4td99d3r5g4ylg0wlngpy0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ethereum&lt;/strong&gt;: &lt;code&gt;0x9D0C185Ed0BbfeFc9dC392D2E3d72Be2635D3BA3&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TON&lt;/strong&gt;: &lt;code&gt;UQA6dCXas-TAbpiH7ATdgSxKze1iekkxFz1ch-Z79GwDnFGw&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;USDT/USDC/DAI (ERC20)&lt;/strong&gt;: &lt;code&gt;0x9D0C185Ed0BbfeFc9dC392D2E3d72Be2635D3BA3&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Let FastForge do the heavy lifting for authentication, and get you building faster! Enjoy coding.&lt;/p&gt;

&lt;p&gt;(&lt;a href="https://github.com/javadzarezadeh/fastforge" rel="noopener noreferrer"&gt;https://github.com/javadzarezadeh/fastforge&lt;/a&gt;)&lt;/p&gt;

</description>
      <category>fastapi</category>
      <category>authentication</category>
      <category>webdev</category>
      <category>python</category>
    </item>
    <item>
      <title>Mobile-First Approach for FastAPI Full-Stack Template Authentication: Migrating to phone_number/OTP</title>
      <dc:creator>Javad Zarezadeh</dc:creator>
      <pubDate>Sun, 16 Feb 2025 14:20:31 +0000</pubDate>
      <link>https://dev.to/justjayzee/mobile-first-approach-for-fastapi-full-stack-template-authentication-migrating-to-phonenumberotp-m02</link>
      <guid>https://dev.to/justjayzee/mobile-first-approach-for-fastapi-full-stack-template-authentication-migrating-to-phonenumberotp-m02</guid>
      <description>&lt;p&gt;As you may know, &lt;strong&gt;FastAPI&lt;/strong&gt; is one of the most admired frameworks for developing RESTful APIs. Another fantastic project by the same author, &lt;a class="mentioned-user" href="https://dev.to/tiangolo"&gt;@tiangolo&lt;/a&gt;, is the &lt;a href="https://github.com/fastapi/full-stack-fastapi-template" rel="noopener noreferrer"&gt;Full Stack FastAPI Template&lt;/a&gt;, which I previously wrote about &lt;a href="https://dev.to/justjayzee/why-fastapi-full-stack-template-is-my-go-to-for-modern-web-development-1f2e"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this post, I'll guide you through the process of replacing the email/password authentication flow in the template with a phone_number/OTP-based system. This approach is ideal for mobile-first applications and offers a user-friendly, secure way to authenticate users. My goal is to make minimal changes to the original project while maintaining its adherence to &lt;strong&gt;OAuth2&lt;/strong&gt; and &lt;strong&gt;JWT standards&lt;/strong&gt;. Let’s dive in! 😉&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Replace &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; with &lt;code&gt;phone_number&lt;/code&gt; and &lt;code&gt;otp&lt;/code&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Update Configuration&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./.env&lt;/code&gt;&lt;br&gt;
&lt;strong&gt;Change Needed:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Update the &lt;code&gt;FIRST_SUPERUSER&lt;/code&gt; value to a phone number, e.g., &lt;code&gt;+17375550100&lt;/code&gt; or &lt;code&gt;+989130000000&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remove &lt;code&gt;FIRST_SUPERUSER_PASSWORD&lt;/code&gt; as it is no longer necessary.&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;Update the Models&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/models.py&lt;/code&gt; &lt;br&gt;
&lt;strong&gt;Changes Needed:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Replace all instances of the &lt;code&gt;email&lt;/code&gt; field with &lt;code&gt;phone_number&lt;/code&gt;.&lt;br&gt;&lt;br&gt;
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="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;EmailStr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique&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;index&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;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change to:&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;phone_number&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="nc"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;unique&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;index&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;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&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;Important:&lt;/strong&gt; This change requires updating the database schema using Alembic migrations.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Update API Routes&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Private Routes
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/api/routes/private.py&lt;/code&gt;&lt;br&gt;
Replace all occurrences of &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; with &lt;code&gt;phone_number&lt;/code&gt; and &lt;code&gt;otp&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  Login Route
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/api/routes/login.py&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Update the &lt;code&gt;authenticate&lt;/code&gt; call:&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&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&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;form_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&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;form_data&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change to:&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;authenticate&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&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;form_data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;form_data&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;⚠️ &lt;strong&gt;Note:&lt;/strong&gt; Keep &lt;code&gt;form_data.username&lt;/code&gt; and &lt;code&gt;form_data.password&lt;/code&gt; unchanged due to OAuth2 standards.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Update User CRUD&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/api/routes/users.py&lt;/code&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;email&lt;/code&gt; with &lt;code&gt;phone_number&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remove the &lt;code&gt;if statement&lt;/code&gt; in the &lt;code&gt;create_user&lt;/code&gt; function related to email validation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Database Utilities&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/core/db.py&lt;/code&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;email&lt;/code&gt; references with &lt;code&gt;phone_number&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Remove &lt;code&gt;FIRST_SUPERUSER_PASSWORD&lt;/code&gt; as it is no longer necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;CRUD Operations&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; ./backend/app/crud.py  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Replace all &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;password&lt;/code&gt; references with &lt;code&gt;phone_number&lt;/code&gt; and &lt;code&gt;otp&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Rename &lt;code&gt;get_user_by_email&lt;/code&gt; to &lt;code&gt;get_user_by_phone_number&lt;/code&gt; and update all references to this function.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Add an API Endpoint to Request OTP
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/api/routes/login.py&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Add the following endpoint:&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;OTP_EXPIRE_MINUTES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&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;/login/request-otp&lt;/span&gt;&lt;span class="sh"&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;request_otp&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;SessionDep&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone_number&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="n"&gt;Message&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 and send OTP to the provided phone number.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_user_by_phone_number&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&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;phone_number&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;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="n"&gt;crud&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;session&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_create&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;UserCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;otp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_otp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;otp_expires_at&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timezone&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;utc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;OTP_EXPIRE_MINUTES&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_user&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&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;db_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;user_in&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;UserUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otp_expires_at&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;otp_expires_at&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;send_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone_number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;OTP sent successfully.&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. Nullify OTP After Login
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/api/routes/login.py&lt;/code&gt; &lt;br&gt;
In the &lt;code&gt;login_access_token&lt;/code&gt; function, nullify the OTP after successful login:&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;crud&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_user&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&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;db_user&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;user_in&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;UserUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;otp&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;otp_expires_at&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  4. Remove Unnecessary Functions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/api/routes/login.py&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Remove the following functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;recover_password&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;reset_password&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;recover_password_html_content&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  5. Remove Unnecessary Email Features
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/api/routes/users.py&lt;/code&gt;&lt;br&gt;&lt;br&gt;
Remove the email-related logic, such as:&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;settings&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;emails_enabled&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;user_in&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="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Remove Password Update and User Registration Functions
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/api/routes/users.py&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Remove the following functions:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;update_password_me&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;register_user&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since we are now using OTP-based authentication, these functions are redundant.  &lt;/p&gt;




&lt;h2&gt;
  
  
  7. Simplify Models
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/models.py&lt;/code&gt;  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Replace &lt;code&gt;password&lt;/code&gt; with &lt;code&gt;otp&lt;/code&gt;:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Update all &lt;code&gt;password&lt;/code&gt; fields to &lt;code&gt;otp&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;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="n"&gt;password&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="nc"&gt;Field&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;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change to:&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;otp&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="nc"&gt;Field&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;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_length&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Remove OTP from &lt;code&gt;UserCreate&lt;/code&gt;:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For the &lt;code&gt;UserCreate&lt;/code&gt; model, you don’t need to include the &lt;code&gt;otp&lt;/code&gt; field. Update it as follows:&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;UserCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UserBase&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simplifies the creation process since OTP will be generated later during login.  &lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;strong&gt;Add OTP Expiry Fields:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Add an &lt;code&gt;otp_expires_at&lt;/code&gt; field to both the &lt;code&gt;UserUpdate&lt;/code&gt; and &lt;code&gt;User&lt;/code&gt; models.  &lt;/p&gt;

&lt;p&gt;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="n"&gt;otp_expires_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;datetime&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="nc"&gt;Field&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;None&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;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  &lt;strong&gt;Remove Unnecessary Models:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Delete models that are no longer needed, including:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;UserRegister&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UpdatePassword&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NewPassword&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This cleanup ensures the models remain relevant to the new authentication system.  &lt;/p&gt;




&lt;h2&gt;
  
  
  8. Update Utilities
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;File:&lt;/strong&gt; &lt;code&gt;./backend/app/utils.py&lt;/code&gt;  &lt;/p&gt;

&lt;p&gt;Remove unused functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;generate_reset_password_email&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;generate_new_account_email&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;generate_password_reset_token&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;verify_password_reset_token&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Add OTP Generation:&lt;/strong&gt;
&lt;/h3&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;generate_otp&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;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randint&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;999999&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;  &lt;span class="c1"&gt;# 6-digit OTP
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Add SMS Sending:&lt;/strong&gt;
&lt;/h3&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;send_otp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;phone_number&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;otp&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;
    Sends an OTP to the provided phone number.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="c1"&gt;# Implement this function according to your SMS provider
&lt;/span&gt;
    &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Following these steps will transform the Full Stack FastAPI Template’s email/password flow into a phone_number/OTP-based system while keeping it aligned with best practices and standards. Happy coding! 🚀 &lt;/p&gt;




&lt;p&gt;These changes to the  original project are available in my &lt;a href="https://github.com/javadzarezadeh/phone-otp-auth-fastapi" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. It is important to use this project cautiously, since I have not yet had time to write the tests.&lt;/p&gt;

</description>
      <category>fastapi</category>
      <category>python</category>
      <category>webdev</category>
      <category>backend</category>
    </item>
    <item>
      <title>Why FastAPI Full-Stack Template Is My Go-To for Modern Web Development</title>
      <dc:creator>Javad Zarezadeh</dc:creator>
      <pubDate>Sun, 26 Jan 2025 15:09:33 +0000</pubDate>
      <link>https://dev.to/justjayzee/why-fastapi-full-stack-template-is-my-go-to-for-modern-web-development-1f2e</link>
      <guid>https://dev.to/justjayzee/why-fastapi-full-stack-template-is-my-go-to-for-modern-web-development-1f2e</guid>
      <description>&lt;p&gt;Python might not be the most modern programming language, but it’s undoubtedly one of the most widely used today. There’s an old Persian saying: &lt;strong&gt;"A thornless flower is divine." (گل بی‌خار خداست)&lt;/strong&gt;, which reminds us that nothing in the universe is without imperfections. Programming languages are no exception. Despite its performance issues (In comparison with compiled programming languages) and the infamous GIL, Python’s simplicity, vast community, and extensive library support far outweigh its shortcomings. Recent advancements in Python’s core are also paving the way for modern features like type hinting and concurrency—capabilities that were missing from the start.  &lt;/p&gt;

&lt;p&gt;With the introduction of &lt;strong&gt;type hinting&lt;/strong&gt; in Python 3.5 and its gradual adoption as a default in Python 3.10, FastAPI emerged. The now-famous de facto framework for RESTful API development hardly needs an introduction. But here’s where I want to take a creative detour: &lt;strong&gt;"&lt;a href="https://www.imdb.com/title/tt0057012/" rel="noopener noreferrer"&gt;How I Learned to Stop Worrying and Love the Bomb&lt;/a&gt;."&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;Yes, you read that right. FastAPI is the “bomb” that’s shaking up Django and even other web development frameworks from different languages. It builds on Python’s strengths without reinventing the wheel. FastAPI embraces Python’s core language features, making the learning process feel like rediscovering Python itself—but in a better way. Trust me on this: the learning curve feels more like a joyride. Hell yeah, learning curve! 😜  &lt;/p&gt;

&lt;p&gt;While the many merits of FastAPI could fill pages, this article focuses on why I love using the &lt;strong&gt;full-stack template&lt;/strong&gt; introduced by its author, &lt;strong&gt;&lt;a class="mentioned-user" href="https://dev.to/tiangolo"&gt;@tiangolo&lt;/a&gt; (Sebastián Ramírez)&lt;/strong&gt;. Sebastián isn’t just a great open-source contributor—he’s an idol. His dedication goes beyond building his own tools; he also highlights other projects worth exploring and using for a lifetime.  &lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why I Love the Full-Stack Template&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Gathering Modern Technologies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The template brings together a dream stack:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt; for the backend
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PostgreSQL&lt;/strong&gt; for the database
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt; for the frontend
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker Compose&lt;/strong&gt; for DevOps
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can find the full list of technologies &lt;a href="https://github.com/fastapi/full-stack-fastapi-template/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Rocket-Fast Performance!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Despite being based on Python, FastAPI’s performance is undoubtedly impressive. This is thanks to its foundation on two powerful tools: &lt;em&gt;&lt;a href="https://www.starlette.io/" rel="noopener noreferrer"&gt;Starlette&lt;/a&gt;&lt;/em&gt; and &lt;em&gt;&lt;a href="https://www.uvicorn.org/" rel="noopener noreferrer"&gt;Uvicorn&lt;/a&gt;&lt;/em&gt;. If you’ve worked with Django, you might know its performance isn’t its strongest suit. But take a look at the &lt;em&gt;&lt;a href="https://www.techempower.com/benchmarks/" rel="noopener noreferrer"&gt;TechEmpower Benchmark&lt;/a&gt;&lt;/em&gt;: FastAPI’s performance outshines &lt;strong&gt;Flask&lt;/strong&gt; and is miles ahead of &lt;strong&gt;Django&lt;/strong&gt;—not just far, but &lt;em&gt;far, far, far&lt;/em&gt; better!&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. The Dirty Work is Already Done!&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You might think, &lt;em&gt;"So what? I know these technologies and can integrate them myself."&lt;/em&gt; Fair point, but let’s be real—configuring and bridging these tools can be a nightmare. This template handles that for you, using best practices throughout. Why not trust it? By narrowing down the stack, you free your mind from debating JS/TS, Vite/Webpack, Chakra UI/Material UI, and so on. Straight to the code!  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Learning from Top Developers&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Before using this template, I hadn’t even heard of technologies like &lt;em&gt;&lt;a href="https://traefik.io/traefik/" rel="noopener noreferrer"&gt;Traefik&lt;/a&gt;&lt;/em&gt;, &lt;em&gt;&lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;Playwright&lt;/a&gt;&lt;/em&gt;, or &lt;em&gt;&lt;a href="https://chakra-ui.com/" rel="noopener noreferrer"&gt;Chakra UI&lt;/a&gt;&lt;/em&gt;. Discovering these tools through the template introduced me to industry best practices and inspired me to learn more.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Well-Organized Code and Best Practices&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I won’t dive too deep into the codebase, but one highlight is its exceptional implementation of user authentication. It uses OAuth2 and JWT standards—and nails it. Although the structure might feel complex at first glance, you’ll soon appreciate why it’s designed this way.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;6. Customization Right Out of the Box&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Do you prefer to stick with the backend and implement the frontend using your favorite framework, like Svelte? Not a problem! Removing the frontend folder is almost all you need to do. The template supports easy customization, whether on the backend or frontend, allowing you to tailor it to your specific needs.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;7. Documentation and Community Support&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Both FastAPI and the full-stack template have robust documentation. Additionally, there’s an active community around FastAPI, so finding solutions to issues or learning best practices is relatively easy.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The Downsides&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Pull Request Review Delays&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Sebastián maintains many amazing projects, so PR reviews can take longer than expected. On the bright side, he’s welcoming and offers warm responses when he has time to engage.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Complexity for Beginners&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;While the template is powerful, its structure and integrations can feel overwhelming to beginners. New developers might need extra time to understand how all the pieces fit together.  &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Maintenance of Customized Projects&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Once you’ve customized the template, keeping your project up-to-date with upstream changes can be tricky. Merging updates from the original repository requires careful attention to avoid conflicts with your customizations.&lt;/p&gt;




&lt;p&gt;In conclusion, the &lt;strong&gt;full-stack FastAPI template&lt;/strong&gt; isn’t just a collection of tools; it’s a thoughtfully crafted framework that balances modern technologies with ease of use. It’s not perfect—just like Python or anything else in life—but as the saying goes, &lt;em&gt;"A thornless flower is divine."&lt;/em&gt;  &lt;/p&gt;

</description>
      <category>fastapi</category>
      <category>python</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
