<?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: Mr Chike</title>
    <description>The latest articles on DEV Community by Mr Chike (@mrchike).</description>
    <link>https://dev.to/mrchike</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%2F2147140%2F6a3e756f-9c9e-4a62-89c7-c7c04634a9e7.jpg</url>
      <title>DEV Community: Mr Chike</title>
      <link>https://dev.to/mrchike</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mrchike"/>
    <language>en</language>
    <item>
      <title>🤝 Learn Front-End by Doing: Contribute to Cal.com's Open Source...🚀</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Thu, 14 Aug 2025 13:59:11 +0000</pubDate>
      <link>https://dev.to/mrchike/learn-front-end-by-doing-contribute-to-calcoms-open-source-4ne5</link>
      <guid>https://dev.to/mrchike/learn-front-end-by-doing-contribute-to-calcoms-open-source-4ne5</guid>
      <description>&lt;p&gt;In this tutorial, we'll be focusing on &lt;a href="https://cal.com/" rel="noopener noreferrer"&gt;Cal.com&lt;/a&gt;: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;A fully customizable scheduling software for individuals, businesses taking calls and developers building scheduling platforms where users meet users.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;⛔✋ Before you start scrolling and skimming...&lt;br&gt;
Here’s a quick overview of the project you’ll be setting up and contributing to.&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.amazonaws.com%2Fuploads%2Farticles%2Fxun15qnd3cro4p15zicn.gif" 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.amazonaws.com%2Fuploads%2Farticles%2Fxun15qnd3cro4p15zicn.gif" alt="Calcom Project" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  👇 Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⚙️ &lt;strong&gt;&lt;code&gt;Environment Setup (Optional)&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;&lt;code&gt;Project Scaffolding&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;&lt;code&gt;Launch&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  ⚙️ Environment Setup (Optional)
&lt;/h2&gt;

&lt;p&gt;Getting started with servers can feel overwhelming at first. I remember that stage well. That’s why I like to keep things beginner-friendly. If you’ve already got some experience under your belt, you can skip this part. &lt;/p&gt;

&lt;p&gt;For this guide, I’m working with Ubuntu Linux, but we’ll also walk through setting up a fresh environment on Windows using WSL (Windows Subsystem for Linux). Even if you don’t need it today, this is the kind of setup you’ll probably want to bookmark for later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 For Windows users&lt;/strong&gt;&lt;br&gt;
You can install &lt;a href="https://github.com/microsoft/WSL?tab=readme-ov-file#about" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;Windows Subsystem for Linux (WSL)&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; with the command &lt;code&gt;wsl --install&lt;/code&gt; in your terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wsl &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="nt"&gt;--online&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;The following is a list of valid distributions that can be installed.
Install using &lt;span class="s1"&gt;'wsl.exe --install &amp;lt;Distro&amp;gt;'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

NAME                            FRIENDLY NAME
AlmaLinux-8                     AlmaLinux OS 8
AlmaLinux-9                     AlmaLinux OS 9
AlmaLinux-Kitten-10             AlmaLinux OS Kitten 10
AlmaLinux-10                    AlmaLinux OS 10
Debian                          Debian GNU/Linux
FedoraLinux-42                  Fedora Linux 42
SUSE-Linux-Enterprise-15-SP6    SUSE Linux Enterprise 15 SP6
SUSE-Linux-Enterprise-15-SP7    SUSE Linux Enterprise 15 SP7
Ubuntu                          Ubuntu
Ubuntu-24.04                    Ubuntu 24.04 LTS
archlinux                       Arch Linux
kali-linux                      Kali Linux Rolling
openSUSE-Tumbleweed             openSUSE Tumbleweed
openSUSE-Leap-15.6              openSUSE Leap 15.6
Ubuntu-18.04                    Ubuntu 18.04 LTS
Ubuntu-20.04                    Ubuntu 20.04 LTS
Ubuntu-22.04                    Ubuntu 22.04 LTS
OracleLinux_7_9                 Oracle Linux 7.9
OracleLinux_8_10                Oracle Linux 8.10
OracleLinux_9_5                 Oracle Linux 9.5
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install Ubuntu 22.04 (recommended):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wsl &lt;span class="nt"&gt;--install&lt;/span&gt; Ubuntu-22.04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, launch your new Ubuntu distribution with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wsl &lt;span class="nt"&gt;-d&lt;/span&gt; Ubuntu-22.04
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can access your project folders in the new Linux environment using the &lt;strong&gt;WSL extension&lt;/strong&gt; in your favourite code editor (I use VSCode).&lt;br&gt;
From there, continue with the setup by running the commands below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 For Linux Users&lt;/strong&gt;&lt;br&gt;
Run the command below in your terminal. If you happen to be using a different Linux distribution, then replace &lt;code&gt;apt&lt;/code&gt; with your system's package manager like &lt;code&gt;yum&lt;/code&gt;, &lt;code&gt;dnf&lt;/code&gt;, &lt;code&gt;pkg&lt;/code&gt;, &lt;code&gt;apk&lt;/code&gt; and so on.&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;# Update package lists and upgrade existing packages&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Install useful dependencies&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker.io docker-compose tree vim openssh-server

&lt;span class="c"&gt;# Add current user to the docker group for non-root access&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;

&lt;span class="c"&gt;# Enable/start the SSH service&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;ssh
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start ssh

&lt;span class="c"&gt;# Allow SSH through the firewall and enable UFW (Uncomplicated Firewall)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow ssh
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;

&lt;span class="c"&gt;# Generate a new RSA SSH key pair with no passphrase and a comment for identification&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_rsa &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"ssh-key"&lt;/span&gt;

&lt;span class="c"&gt;# Reboot the system to apply changes&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;shutdown &lt;span class="nt"&gt;-r&lt;/span&gt; now

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

&lt;/div&gt;



&lt;p&gt;Now that we're done with running the above commands and restarting the server so changes take full effect, we will be moving to the next section which will be...&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Project Scaffolding
&lt;/h2&gt;

&lt;p&gt;In this section, we will be setting up the project structure.&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;# Clone the Cal.com repository from GitHub&lt;/span&gt;
git clone &lt;span class="nt"&gt;--depth&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 https://github.com/calcom/cal.com.git

&lt;span class="c"&gt;# Move into the newly cloned project directory&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;cal.com

&lt;span class="c"&gt;# Create and switch to a new Git branch called "dev"&lt;/span&gt;
git checkout &lt;span class="nt"&gt;-b&lt;/span&gt; dev

&lt;span class="c"&gt;# Create a new Docker network for containers to communicate easily with each other&lt;/span&gt;
docker network create calcom_net

docker run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--network&lt;/span&gt; calcom_net &lt;span class="se"&gt;\ &lt;/span&gt;                        &lt;span class="c"&gt;# Use custom network&lt;/span&gt;
  &lt;span class="nt"&gt;--dns&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8.8.8.8 &lt;span class="se"&gt;\ &lt;/span&gt;                               &lt;span class="c"&gt;# Set DNS to Google&lt;/span&gt;
  &lt;span class="nt"&gt;--privileged&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt;                                &lt;span class="c"&gt;# Grant extra permissions&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; calcom_dev &lt;span class="se"&gt;\ &lt;/span&gt;                           &lt;span class="c"&gt;# Name the container&lt;/span&gt;
  &lt;span class="nt"&gt;--add-host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"host.docker.internal:host-gateway"&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;# Access host from container&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; /var/run/docker.sock:/var/run/docker.sock &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;# Mount Docker socket&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;:/calcom &lt;span class="se"&gt;\ &lt;/span&gt;                           &lt;span class="c"&gt;# Mount current dir&lt;/span&gt;
  &lt;span class="nt"&gt;-w&lt;/span&gt; /calcom &lt;span class="se"&gt;\ &lt;/span&gt;                                  &lt;span class="c"&gt;# Set working dir&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;NVM_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/root/.nvm"&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt;                     &lt;span class="c"&gt;# NVM config&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;NODE_OPTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"--max-old-space-size=16384"&lt;/span&gt; &lt;span class="se"&gt;\ &lt;/span&gt;&lt;span class="c"&gt;# Increase Node memory&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;CALCOM_TELEMETRY_DISABLED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\ &lt;/span&gt;              &lt;span class="c"&gt;# Disable telemetry&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;NEXT_PUBLIC_LOGGER_LEVEL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3 &lt;span class="se"&gt;\ &lt;/span&gt;               &lt;span class="c"&gt;# Set log level&lt;/span&gt;
  &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="nv"&gt;NEXT_PUBLIC_IS_E2E&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="se"&gt;\ &lt;/span&gt;                     &lt;span class="c"&gt;# Enable E2E mode&lt;/span&gt;
  &lt;span class="nt"&gt;-it&lt;/span&gt; node:20-bullseye bash                      &lt;span class="c"&gt;# Run Node 20 with bash&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now you should be inside the container, and your bash shell should look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@60c156b42050:/calcom#
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In your container bash shell, run the command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade &lt;span class="nt"&gt;-y&lt;/span&gt;     &lt;span class="c"&gt;# Update &amp;amp; upgrade&lt;/span&gt;
apt &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; docker.io &lt;span class="se"&gt;\ &lt;/span&gt;      
               docker-compose &lt;span class="se"&gt;\ &lt;/span&gt; &lt;span class="c"&gt;# Install Docker tools&lt;/span&gt;
               vim &lt;span class="se"&gt;\ &lt;/span&gt;            &lt;span class="c"&gt;# Install text editor&lt;/span&gt;
               iputils-ping &lt;span class="se"&gt;\ &lt;/span&gt;   &lt;span class="c"&gt;# Install ping&lt;/span&gt;
               npm               &lt;span class="c"&gt;# Install Node package manager&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, let create &lt;em&gt;&lt;code&gt;setup.sh&lt;/code&gt;&lt;/em&gt; file and copy all the contents of this file 👉 &lt;a href="https://github.com/MrChike/scripts/blob/master/calcom_project_setup_script.sh" rel="noopener noreferrer"&gt;Calcom Setup Script&lt;/a&gt; into it.&lt;br&gt;
In this terminal shell, run the following 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="c"&gt;# Create setup script&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;setup.sh

&lt;span class="c"&gt;# Make it executable&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x setup.sh

&lt;span class="c"&gt;# Execute updated script&lt;/span&gt;
./setup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;NB: If you're not familiar with docker, try a crash course on YouTube...&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now there are some important updates to make in our Docker Compose files before spinning up the application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;docker-compose.dev.yml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker-compose.prod.yml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;apps/api/v2/docker-compose-apiv2.yaml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In each file, go to the volumes section and update the project's folder path to match the absolute path of your local cal.com project directory (e.g. &lt;code&gt;/home/mrchike/cal.com&lt;/code&gt;).&lt;br&gt;
You can run the pwd command inside the project folder in your host's terminal to get the correct path.&lt;/p&gt;

&lt;p&gt;This is what you’ll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;volumes:
   - /absolute/path/to/cal.com:/calcom &lt;span class="c"&gt;# UPDATE FOLDER PATH&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and this is what it should look like when done. (of course, updated with your own project folder path)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;volumes:
   - /home/mrchike/cal.com:/calcom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that you're done updating the path in each Docker Compose file. Run the following command.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Launch
&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;# Run the application in production mode (optimized build, no hot reloading)&lt;/span&gt;
docker-compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.prod.yml up &lt;span class="nt"&gt;--build&lt;/span&gt;

&lt;span class="c"&gt;# Run the application in development mode (supports real-time code changes / hot reloading)&lt;/span&gt;
docker-compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.dev.yml up &lt;span class="nt"&gt;--build&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; The project may take some time to spin up, approximately 30 minutes to 1 hour.&lt;br&gt;
If it starts consuming a lot of your system’s resources and doesn’t boot up properly, consider running it on an external server (e.g., AWS, GCP, or any equivalent).&lt;/p&gt;

&lt;p&gt;If you encounter an error... 🎉 Congratulations! You're officially a developer, figure it out. 😅&lt;/p&gt;

&lt;p&gt;But if, after a long (and valuable) struggle, you still need support, feel free to reach out &lt;a href="https://www.linkedin.com/in/chikeegonu/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;on LinkedIn&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The command will spin up all related services along with their respective GUIs for web access.&lt;/p&gt;

&lt;p&gt;Once they’re up, you can access them locally using the following URLs and credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cal.com APP (Frontend)&lt;/strong&gt;&lt;br&gt;
🌐 URL: &lt;a href="http://localhost:3000/" rel="noopener noreferrer"&gt;http://localhost:3000/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cal.com API (Backend)&lt;/strong&gt;&lt;br&gt;
🌐 URL: &lt;a href="http://localhost:3002/docs" rel="noopener noreferrer"&gt;http://localhost:3002/docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RedisInsight (Redis)&lt;/strong&gt;&lt;br&gt;
🌐 URL: &lt;a href="http://localhost:5540/" rel="noopener noreferrer"&gt;http://localhost:5540/&lt;/a&gt;&lt;br&gt;
🔌 Connection String: &lt;code&gt;redis://:root@redis:6379&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;pgAdmin (Postgres)&lt;/strong&gt;&lt;br&gt;
🌐 URL: &lt;a href="http://localhost:8083/" rel="noopener noreferrer"&gt;http://localhost:8083/&lt;/a&gt;&lt;br&gt;
🔐 Login:&lt;br&gt;
    Email: &lt;code&gt;root@mailinator.com&lt;/code&gt;&lt;br&gt;
    Password: &lt;code&gt;root&lt;/code&gt;  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The PostgreSQL database has already been updated with initial migrations! If you're new to pgAdmin, no w😉rries!. I’ll walk you through viewing the data:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Visit 👉 &lt;a href="http://localhost:8083/browser/" rel="noopener noreferrer"&gt;http://localhost:8083/browser/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click "Add New Server"&lt;/li&gt;
&lt;li&gt;Under the General tab, set a name (e.g., &lt;code&gt;Cal.com App&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Under the Connection tab, fill in the following:&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Host name/address&lt;/em&gt;: &lt;code&gt;postgres&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Port&lt;/em&gt;: &lt;code&gt;5432&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Maintenance database&lt;/em&gt;: &lt;code&gt;root&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Username&lt;/em&gt;: &lt;code&gt;root&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Password&lt;/em&gt;: &lt;code&gt;root&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Save password?&lt;/em&gt;: ✅&lt;/li&gt;
&lt;li&gt;Click Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To view your data: &lt;br&gt;
Go to &lt;code&gt;Databases(1)&lt;/code&gt; -&amp;gt; &lt;code&gt;Schemas(1)&lt;/code&gt; -&amp;gt; &lt;code&gt;public&lt;/code&gt; -&amp;gt; &lt;code&gt;Tables (100)&lt;/code&gt;.&lt;br&gt;
Right-click any table -&amp;gt; &lt;code&gt;View/Edit Data&lt;/code&gt; -&amp;gt; &lt;code&gt;All Rows&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When you are done setting up. You can either create a user and log in or use the already existing users below:&lt;/p&gt;

&lt;p&gt;username: enterprise-member-1&lt;br&gt;
email: &lt;a href="mailto:enterprise-member-1@example.com"&gt;enterprise-member-1@example.com&lt;/a&gt;&lt;br&gt;
password: enterprise-member-1&lt;/p&gt;

&lt;p&gt;username: enterprise-member-2&lt;br&gt;
email: &lt;a href="mailto:enterprise-member-2@example.com"&gt;enterprise-member-2@example.com&lt;/a&gt;&lt;br&gt;
password: enterprise-member-2&lt;/p&gt;

&lt;p&gt;username: enterprise-member-3&lt;br&gt;
email: &lt;a href="mailto:enterprise-member-3@example.com"&gt;enterprise-member-3@example.com&lt;/a&gt;&lt;br&gt;
password: enterprise-member-3&lt;/p&gt;

&lt;p&gt;and below are some URLs that you might find helpful once your project is up and running!&lt;/p&gt;

&lt;p&gt;&lt;a href="http://localhost:3000/event-types" rel="noopener noreferrer"&gt;http://localhost:3000/event-types&lt;/a&gt;&lt;br&gt;
&lt;a href="http://localhost:3000/auth/setup" rel="noopener noreferrer"&gt;http://localhost:3000/auth/setup&lt;/a&gt;&lt;br&gt;
&lt;a href="http://localhost:3000/getting-started" rel="noopener noreferrer"&gt;http://localhost:3000/getting-started&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That’s all, folks! 🎉&lt;/p&gt;

&lt;p&gt;Hope you have fun contributing and learning on the job. This project is packed with value, and you’ll definitely learn a lot because the technologies used are industry standard for building front-end applications.&lt;/p&gt;

&lt;p&gt;Feel free to supplement your learning with YouTube or other popular educational platforms to deepen your understanding.&lt;/p&gt;

&lt;p&gt;Good luck, and happy building! 🚀👨🏾‍💻&lt;/p&gt;

&lt;p&gt;💡 Enjoyed this article? Connect with me on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/chikeegonu/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;LinkedIn&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐙 &lt;a href="https://github.com/MrChike" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;GitHub&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your support means a lot. If you’d like to buy me a coffee ☕️ to keep me fueled, feel free to check out &lt;a href="https://buymeacoffee.com/mrchike" rel="noopener noreferrer"&gt;this link&lt;/a&gt;. Your generosity would go a long way in helping me continue to create content like this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Previously Written Articles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 &lt;em&gt;Create Professional Portfolios Using Material for MkDocs (Series-X)&lt;/em&gt; → &lt;a href="https://dev.to/mrchike/series-x-create-professional-portfolios-using-material-for-mkdocs-fio"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;Read here&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🛠️ &lt;em&gt;FastAPI in Production: Build, Scale &amp;amp; Deploy - Series B : Services, Queues &amp;amp; Containers&lt;/em&gt; → &lt;a href="https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-b-services-queues-containers-2i08"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;Read here&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🧠 &lt;em&gt;Master the Art of Learning Efficiently (A Memo for Lifelong Learners)&lt;/em&gt; ⏱️🎯 → &lt;a href="https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;Read here&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>frontend</category>
      <category>programming</category>
      <category>opensource</category>
    </item>
    <item>
      <title>🛠️ FastAPI in Production: Build, Scale &amp; Deploy - Series B : Services, Queues &amp; Containers</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Wed, 23 Jul 2025 02:44:00 +0000</pubDate>
      <link>https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-b-services-queues-containers-2i08</link>
      <guid>https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-b-services-queues-containers-2i08</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Welcome to Part 2 of our 3-part FastAPI Series&lt;/strong&gt; 📦 - &lt;a href="https://github.com/MrChike/media_app/tree/seriesB" rel="noopener noreferrer"&gt;Full source code is available on GitHub!&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In case you missed it, here’s &lt;a href="https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-a-codebase-design-ao3"&gt;&lt;code&gt;🔥PART 1&lt;/code&gt;&lt;/a&gt; to get you up to speed!&lt;/p&gt;

&lt;p&gt;To whet your appetite, here are just a few of the interesting features we’ll be focusing on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🐳 Dockerized Environment Setup&lt;/li&gt;
&lt;li&gt;🚀 Asynchronous Task Processing with Celery&lt;/li&gt;
&lt;li&gt;📦 Boss-Level Project Documentation with MKDocs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before we dive in, here's a quick look at what we'll cover:&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⚽ Picking Up Where We Left Off
&lt;/li&gt;
&lt;li&gt;🗂️ Project Structure
&lt;/li&gt;
&lt;li&gt;🛢️ Setup Database
&lt;/li&gt;
&lt;li&gt;💾 Perform CRUD Operations
&lt;/li&gt;
&lt;li&gt;🚀 Offloading CPU Intensive Workloads with Celery
&lt;/li&gt;
&lt;li&gt;📄 Project Documentation with MKDocs
&lt;/li&gt;
&lt;li&gt;🐳 Running Your Project in Docker
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚽ Picking Up Where We Left Off
&lt;/h2&gt;

&lt;p&gt;Let’s pick things up by cloning the repo from Part 1 and setting up our project environment. Follow these steps to get started:&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;# Clone project&lt;/span&gt;
git clone &lt;span class="nt"&gt;--branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;seriesA https://github.com/MrChike/media_app.git

&lt;span class="nb"&gt;cd &lt;/span&gt;media_app

&lt;span class="c"&gt;# Create and activate virtual environment&lt;/span&gt;
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="nb"&gt;env&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that our project is all set up, let's create a &lt;a href="https://github.com/MrChike/media_app/blob/seriesB/series_b_setup.sh" rel="noopener noreferrer"&gt;&lt;code&gt;setup script&lt;/code&gt;&lt;/a&gt; to bootstrap the series_b files we’ll be working with:&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 the setup script file&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;series_b_setup.sh

&lt;span class="c"&gt;# Make the setup script executable&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x series_b_setup.sh

&lt;span class="c"&gt;# Run the setup script (after updating it with the setup script repo link)&lt;/span&gt;
./series_b_setup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, your project structure would look like this 👇🏼&lt;/p&gt;

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



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

├── base/                                &lt;span class="c"&gt;# Core feature module&lt;/span&gt;
│   ├── __init__.py
│   ├── router.py                        &lt;span class="c"&gt;# Defines HTTP API endpoints and maps them to controller functions&lt;/span&gt;
│   ├── controller.py                    &lt;span class="c"&gt;# Handles request-response cycle; delegates business logic to services&lt;/span&gt;
│   ├── service.py                       &lt;span class="c"&gt;# Core business logic for async I/O operations&lt;/span&gt;
│   ├── model.py                         &lt;span class="c"&gt;# SQLAlchemy ORM models representing database tables&lt;/span&gt;
│   ├── schema.py                        &lt;span class="c"&gt;# Pydantic models for input validation and output serialization&lt;/span&gt;
│   ├── dependencies.py                  &lt;span class="c"&gt;# Module-specific DI components like authentication and DB sessions&lt;/span&gt;
│   └── tasks.py                         &lt;span class="c"&gt;# Core business logic for CPU-bound operations&lt;/span&gt;

├── movies/                              &lt;span class="c"&gt;# Movie feature module (same layout as base)&lt;/span&gt;
│   ├── __init__.py
│   ├── router.py
│   ├── controller.py
│   ├── service.py
│   ├── model.py
│   ├── schema.py
│   ├── dependencies.py
│   └── tasks.py

├── static/                              &lt;span class="c"&gt;# (Optional) Static files (e.g., images, CSS)&lt;/span&gt;
├── templates/                           &lt;span class="c"&gt;# (Optional) Jinja2 or HTML templates for frontend rendering&lt;/span&gt;
├── docs/                                &lt;span class="c"&gt;# (Optional) API documentation, design specs, or OpenAPI enhancements&lt;/span&gt;

├── shared/                              &lt;span class="c"&gt;# Project-wide shared codebase&lt;/span&gt;
│   ├── __init__.py
│   ├── config/
│   │   ├── __init__.py
│   │   ├── base_settings.py             &lt;span class="c"&gt;# Base config for environments&lt;/span&gt;
│   │   └── settings.py                  &lt;span class="c"&gt;# Pydantic-based config management&lt;/span&gt;
│   ├── db/
│   │   ├── __init__.py
│   │   └── connection.py                &lt;span class="c"&gt;# DB engine/session handling&lt;/span&gt;
│   ├── dependencies/                    &lt;span class="c"&gt;# Shared DI functions (e.g., auth, DB session)&lt;/span&gt;
│   │   └── __init__.py
│   ├── middleware/                      &lt;span class="c"&gt;# Global middlewares (e.g., logging, error handling)&lt;/span&gt;
│   │   └── __init__.py
│   ├── services/
│   │   ├── __init__.py
│   │   ├── external_apis/               &lt;span class="c"&gt;# Third-party integrations&lt;/span&gt;
│   │   │   ├── __init__.py
│   │   │   └── omdb_movies.py           &lt;span class="c"&gt;# Integration with OMDB API&lt;/span&gt;
│   │   └── internal_operations/         &lt;span class="c"&gt;# CPU-intensive logic, background tasks&lt;/span&gt;
│   │       └── __init__.py
│   └── utils/                           &lt;span class="c"&gt;# Generic helpers&lt;/span&gt;
│       ├── __init__.py
│       └── fetch_request_with_error_handling.py  &lt;span class="c"&gt;# Error-resilient HTTP requests&lt;/span&gt;

├── scripts/                             &lt;span class="c"&gt;# Developer or DevOps utilities&lt;/span&gt;
│   ├── __init__.py
│   └── sanity_check.py                  &lt;span class="c"&gt;# A friendly reminder not to lose your mind while debugging&lt;/span&gt;

tests/                                     &lt;span class="c"&gt;# Root of all tests&lt;/span&gt;
├── __init__.py
│
├── unit/                                  &lt;span class="c"&gt;# Fast, isolated logic-level tests&lt;/span&gt;
│   ├── __init__.py
│   ├── base/
│   │   ├── __init__.py
│   │   └── test_service.py
│   └── movies/
│       ├── __init__.py
│       ├── test_controller.py
│       ├── test_service.py
│       └── test_tasks.py
│
├── integration/                           &lt;span class="c"&gt;# DB/API/network dependent tests&lt;/span&gt;
│   ├── __init__.py
│
├── e2e/                                   &lt;span class="c"&gt;# High-level, full user flow tests&lt;/span&gt;
│   ├── __init__.py
│
├── system/                                &lt;span class="c"&gt;# System resilience, performance, fault-tolerance tests&lt;/span&gt;
│   ├── __init__.py

├── migrations/                          &lt;span class="c"&gt;# Alembic migration files&lt;/span&gt;
│   ├── env.py
│   ├── README
│   ├── script.py.mako
│   └── versions/                        &lt;span class="c"&gt;# Versioned migration scripts&lt;/span&gt;

├── alembic.ini                          &lt;span class="c"&gt;# Alembic configuration for database migrations&lt;/span&gt;
├── celeryconfig.py                      &lt;span class="c"&gt;# Celery settings for async task queue&lt;/span&gt;

├── docker-compose.api.yaml              &lt;span class="c"&gt;# Docker Compose API&lt;/span&gt;
├── docker-compose.db.yaml               &lt;span class="c"&gt;# Docker Compose DB&lt;/span&gt;
├── Dockerfile                           &lt;span class="c"&gt;# Base app Dockerfile&lt;/span&gt;
├── Dockerfile.nginx                     &lt;span class="c"&gt;# Nginx reverse proxy Dockerfile&lt;/span&gt;
├── nginx.conf                           &lt;span class="c"&gt;# Nginx configuration&lt;/span&gt;
├── entrypoint.sh                        &lt;span class="c"&gt;# Shell script to run app container&lt;/span&gt;
├── series_a_setup.sh                    &lt;span class="c"&gt;# SeriesA Environment setup script&lt;/span&gt;
├── series_b_setup.sh                    &lt;span class="c"&gt;# SeriesB Environment setup script&lt;/span&gt;

├── .example.env                         &lt;span class="c"&gt;# Template for environment variables&lt;/span&gt;
├── .coveragerc                          &lt;span class="c"&gt;# Code coverage settings&lt;/span&gt;
├── .gitignore                           &lt;span class="c"&gt;# Files and folders ignored by Git&lt;/span&gt;

├── main.py                              &lt;span class="c"&gt;# FastAPI application entrypoint&lt;/span&gt;
├── pytest.ini                           &lt;span class="c"&gt;# Pytest configuration&lt;/span&gt;
├── requirements.txt                     &lt;span class="c"&gt;# Python dependency list&lt;/span&gt;
├── JOURNAL.md                           &lt;span class="c"&gt;# Development log: issues faced, solutions, and resources&lt;/span&gt;
└── README.md                            &lt;span class="c"&gt;# Project overview, setup, and usage&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  🛢️ Setup Database
&lt;/h2&gt;

&lt;p&gt;Now that we know what to expect, we will set up our database(s). &lt;br&gt;
At first, we will start by updating these files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/movies/model.py" rel="noopener noreferrer"&gt;&lt;code&gt;model.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/movies/schema.py" rel="noopener noreferrer"&gt;&lt;code&gt;schema.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;shared/config/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/shared/config/settings.py" rel="noopener noreferrer"&gt;&lt;code&gt;settings.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;shared/db/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/shared/db/connection.py" rel="noopener noreferrer"&gt;&lt;code&gt;connection.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now you've updated the files we will be moving next to setting up alembic. &lt;br&gt;
What the awwwwn is an Alembic...? you ask? 😉&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Alembic is a database migration tool for Python that integrates with SQLAlchemy to generate, track, and apply versioned schema changes across different environments.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now that you’ve got all that off your chest, it’s time to initialize the &lt;code&gt;migrations folder&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quick Note💥&lt;/strong&gt;: You can technically name this folder anything, even &lt;em&gt;alembic&lt;/em&gt;. But I prefer &lt;em&gt;migrations&lt;/em&gt; because it’s clear and straightforward, and it helps anyone reading the code later (including future me) to quickly understand its purpose without confusion.&lt;/p&gt;

&lt;p&gt;Next, run the command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  Creating directory /path/to/media_app/migrations ...  &lt;span class="k"&gt;done
  &lt;/span&gt;Creating directory /path/to/media_app/migrations/versions ...  &lt;span class="k"&gt;done
  &lt;/span&gt;Generating /path/to/media_app/migrations/README ...  &lt;span class="k"&gt;done
  &lt;/span&gt;Generating /path/to/media_app/alembic.ini ...  &lt;span class="k"&gt;done
  &lt;/span&gt;Generating /path/to/media_app/migrations/env.py ...  &lt;span class="k"&gt;done
  &lt;/span&gt;Generating /path/to/media_app/migrations/script.py.mako ...  &lt;span class="k"&gt;done
  &lt;/span&gt;Please edit configuration/connection/logging
  settings &lt;span class="k"&gt;in&lt;/span&gt; /path/to/media_app/alembic.ini before proceeding.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After running the command, you’ll notice an &lt;code&gt;alembic.ini&lt;/code&gt; file and a &lt;code&gt;migrations&lt;/code&gt; folder have been created.&lt;/p&gt;

&lt;p&gt;Our focus will be on updating the migrations/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/migrations/env.py" rel="noopener noreferrer"&gt;&lt;code&gt;env.py&lt;/code&gt;&lt;/a&gt; file.&lt;/p&gt;

&lt;p&gt;This file is generated automatically when you run &lt;code&gt;alembic init&lt;/code&gt;, but there are several key parts we’ll be updating to make it work with our PostgreSQL database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/migrations/env.py#L5" rel="noopener noreferrer"&gt;&lt;code&gt;Line 5&lt;/code&gt;&lt;/a&gt; (Import application settings)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/migrations/env.py#L6" rel="noopener noreferrer"&gt;&lt;code&gt;Line 6&lt;/code&gt;&lt;/a&gt; (Import modules models)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/migrations/env.py#L11" rel="noopener noreferrer"&gt;&lt;code&gt;Line 11&lt;/code&gt;&lt;/a&gt; (Configure PostgreSQL connection URL)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/migrations/env.py#L31" rel="noopener noreferrer"&gt;&lt;code&gt;Line 31&lt;/code&gt;&lt;/a&gt; (Register modules migration)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/migrations/env.py#L53" rel="noopener noreferrer"&gt;&lt;code&gt;Line 53&lt;/code&gt;&lt;/a&gt; (Insert database connection string)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/migrations/env.py#L76" rel="noopener noreferrer"&gt;&lt;code&gt;Line 76&lt;/code&gt;&lt;/a&gt; (Add database URL and connection parameters)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that the settings are complete, it’s time to configure the database using a Docker Compose file.&lt;/p&gt;

&lt;p&gt;Update your &lt;code&gt;docker-compose.db.yaml&lt;/code&gt; file to reflect the necessary &lt;a href="https://github.com/MrChike/media_app/blob/seriesB_db_setup/docker-compose.db.yaml" rel="noopener noreferrer"&gt;&lt;code&gt;services&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note: I purposely included all database configurations in a single Docker Compose file for simplicity. I understand that some of you might already be using external databases. However, for the purpose of this tutorial, I’ve bundled &lt;code&gt;Redis&lt;/code&gt;, &lt;code&gt;Postgres&lt;/code&gt;, and &lt;code&gt;MongoDB&lt;/code&gt; along with their respective GUIs: &lt;code&gt;RedisInsight&lt;/code&gt;, &lt;code&gt;pgAdmin&lt;/code&gt;, and &lt;code&gt;Mongo Express&lt;/code&gt; into one file for convenience.&lt;/p&gt;

&lt;p&gt;If you’re already using external databases, you can skip the next step. Otherwise, start the services by running:&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 &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.db.yaml up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will spin up the databases along with their respective GUIs. Give it a minute or so for all the services to initialize properly. &lt;em&gt;(Between you and I, pgAdmin is an elder, so he takes more time to get prepared, so please be patient with him)&lt;/em&gt;😉&lt;/p&gt;

&lt;p&gt;Once they’re up, you can access them locally using the following URLs and credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;RedisInsight (Redis)&lt;/strong&gt;&lt;br&gt;
🌐 URL: &lt;a href="http://localhost:5540/" rel="noopener noreferrer"&gt;http://localhost:5540/&lt;/a&gt;&lt;br&gt;
🔌 Connection String: &lt;code&gt;redis://:root@redis:6379&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mongo Express (MongoDB)&lt;/strong&gt;&lt;br&gt;
🌐 URL: &lt;a href="http://localhost:8081/" rel="noopener noreferrer"&gt;http://localhost:8081/&lt;/a&gt;&lt;br&gt;
🔐 Login: Already logged in as &lt;code&gt;admin&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;pgAdmin (Postgres)&lt;/strong&gt;&lt;br&gt;
🌐 URL: &lt;a href="http://localhost:8083/" rel="noopener noreferrer"&gt;http://localhost:8083/&lt;/a&gt;&lt;br&gt;
🔐 Login:&lt;br&gt;
    Email: &lt;code&gt;root@mailinator.com&lt;/code&gt;&lt;br&gt;
    Password: &lt;code&gt;root&lt;/code&gt;  &lt;/p&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fbl86o3nyfjxkxj1w6et2.gif" 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.amazonaws.com%2Fuploads%2Farticles%2Fbl86o3nyfjxkxj1w6et2.gif" alt="DB GUIs" width="1920" height="1063"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have our databases up and running, let’s not lose sight of what we’ve accomplished so far with Alembic.&lt;/p&gt;

&lt;p&gt;So far, we’ve only completed the first step in the 3-step Alembic flow: &lt;strong&gt;initializing migrations&lt;/strong&gt;. The next two steps are just as important, &lt;strong&gt;generating&lt;/strong&gt; and &lt;strong&gt;applying&lt;/strong&gt; those migrations. That’s what we’ll focus on next.&lt;/p&gt;

&lt;p&gt;To generate a new migration based on your current models, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;alembic revision &lt;span class="nt"&gt;--autogenerate&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial Migration"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Replace "Initial Migration" with a message that describes the changes you're capturing, if needed.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;INFO  &lt;span class="o"&gt;[&lt;/span&gt;alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  &lt;span class="o"&gt;[&lt;/span&gt;alembic.runtime.migration] Will assume transactional DDL.
INFO  &lt;span class="o"&gt;[&lt;/span&gt;alembic.autogenerate.compare] Detected added table &lt;span class="s1"&gt;'movies'&lt;/span&gt;
INFO  &lt;span class="o"&gt;[&lt;/span&gt;alembic.autogenerate.compare] Detected added index &lt;span class="s1"&gt;'ix_movies_id'&lt;/span&gt; on &lt;span class="s1"&gt;'('&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="s1"&gt;',)'&lt;/span&gt;
INFO  &lt;span class="o"&gt;[&lt;/span&gt;alembic.autogenerate.compare] Detected added index &lt;span class="s1"&gt;'ix_movies_title'&lt;/span&gt; on &lt;span class="s1"&gt;'('&lt;/span&gt;title&lt;span class="s1"&gt;',)'&lt;/span&gt;
  Generating /path/to/media_app/migrations/versions/b7283418aefb_initial
  _migration.py ...  &lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To apply the generated migrations to your relational (PostgreSQL) database, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;alembic upgrade &lt;span class="nb"&gt;head&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;INFO  &lt;span class="o"&gt;[&lt;/span&gt;alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  &lt;span class="o"&gt;[&lt;/span&gt;alembic.runtime.migration] Will assume transactional DDL.
INFO  &lt;span class="o"&gt;[&lt;/span&gt;alembic.runtime.migration] Running upgrade  -&amp;gt; b7283418aefb, Initial Migration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will apply the latest migration(s) to your database schema, syncing it with your current models.&lt;/p&gt;

&lt;p&gt;Your PostgreSQL database has been updated with the movies table! If you're new to pgAdmin, no w😉rries!. I’ll guide you through how to view it. First, head to &lt;a href="http://localhost:8083/browser/" rel="noopener noreferrer"&gt;http://localhost:8083/browser/&lt;/a&gt; and register a new server. Under the General tab, name your server something like &lt;code&gt;Media App&lt;/code&gt;. Then, in the Connection tab, update the following details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Host name/address&lt;/em&gt;: &lt;code&gt;postgres&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Port&lt;/em&gt;: &lt;code&gt;5432&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Maintenance database&lt;/em&gt;: &lt;code&gt;root&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Username&lt;/em&gt;: &lt;code&gt;root&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Password&lt;/em&gt;: &lt;code&gt;root&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Save password?&lt;/em&gt;: ✅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And Don’t forget to smash the Save button... &amp;amp; &lt;a href="https://www.linkedin.com/in/chikeegonu/" rel="noopener noreferrer"&gt;&lt;code&gt;follow for more!&lt;/code&gt;&lt;/a&gt;👍&lt;/p&gt;

&lt;p&gt;Once you're connected, go to &lt;code&gt;Databases(2)&lt;/code&gt; -&amp;gt; &lt;code&gt;root&lt;/code&gt; -&amp;gt; &lt;code&gt;Schemas&lt;/code&gt; -&amp;gt; &lt;code&gt;public&lt;/code&gt; -&amp;gt; &lt;code&gt;Tables (2)&lt;/code&gt;. Right-click on the movies table, and choose &lt;code&gt;View/Edit Data&lt;/code&gt; -&amp;gt; &lt;code&gt;All Rows&lt;/code&gt; to see the contents.&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.amazonaws.com%2Fuploads%2Farticles%2Frwu4tnx3v6e2l455aahx.gif" 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.amazonaws.com%2Fuploads%2Farticles%2Frwu4tnx3v6e2l455aahx.gif" alt="pgadmin" width="1920" height="996"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we’ve completed the migration process and have our database up and running, it’s time to move on to the next phase. 👣&lt;/p&gt;

&lt;h2&gt;
  
  
  💾 Perform CRUD Operations
&lt;/h2&gt;

&lt;p&gt;What’s an app without CRUD? 😤&lt;br&gt;
At the heart of every killer app, no matter how sleek the UI, how fancy the animations, or how many laws of space-time complexities it defies, one simple truth is: users just want to create, read, update, and delete stuff.&lt;/p&gt;

&lt;p&gt;If your app can’t handle their basic requests? &lt;strong&gt;Game Over!&lt;/strong&gt;❌&lt;br&gt;
So let’s give our stakeholders what they truly want, reliable CRUD endpoints that just work.&lt;/p&gt;

&lt;p&gt;We will be updating the following files according to the order of the &lt;a href="https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-a-codebase-design-ao3#request-lifecycle"&gt;&lt;code&gt;request life cycle&lt;/code&gt;&lt;/a&gt; explained in part 1.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_crud_ops/movies/router.py" rel="noopener noreferrer"&gt;&lt;code&gt;router.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_crud_ops/movies/controller.py" rel="noopener noreferrer"&gt;&lt;code&gt;controller.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_crud_ops/movies/service.py" rel="noopener noreferrer"&gt;&lt;code&gt;service.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_crud_ops/movies/dependencies.py" rel="noopener noreferrer"&gt;&lt;code&gt;dependencies.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;shared/services/external_apis/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_crud_ops/shared/services/external_apis/omdb_movies.py" rel="noopener noreferrer"&gt;&lt;code&gt;omdb_movies.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;shared/utils/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_crud_ops/shared/utils/fetch_request_with_error_handling.py" rel="noopener noreferrer"&gt;&lt;code&gt;fetch_request_with_error_handling.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;tests/unit/movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_crud_ops/tests/unit/movies/test_controller.py" rel="noopener noreferrer"&gt;&lt;code&gt;test_controller.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;tests/unit/movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_crud_ops/tests/unit/movies/test_service.py" rel="noopener noreferrer"&gt;&lt;code&gt;test_service.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_crud_ops/main.py" rel="noopener noreferrer"&gt;&lt;code&gt;main.py&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we've updated these files, let's check if unit tests are all intact. Run the command:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;=======================================================================&lt;/span&gt; &lt;span class="nb"&gt;test &lt;/span&gt;session starts &lt;span class="o"&gt;========================================================================&lt;/span&gt;
platform linux &lt;span class="nt"&gt;--&lt;/span&gt; Python 3.10.12, pytest-8.3.5, pluggy-1.6.0
rootdir: /path/to/media_app
configfile: pytest.ini
testpaths: tests/
plugins: cov-6.1.1, anyio-4.9.0
collected 13 items                                                                                                                                                 

tests/unit/movies/test_controller.py ......                                                                                                                  &lt;span class="o"&gt;[&lt;/span&gt; 46%]
tests/unit/movies/test_service.py .......                                                                                                                    &lt;span class="o"&gt;[&lt;/span&gt;100%]

&lt;span class="o"&gt;==========================================================================&lt;/span&gt; tests coverage &lt;span class="o"&gt;==========================================================================&lt;/span&gt;
_________________________________________________________ coverage: platform linux, python 3.10.12-final-0 _________________________________________________________

Name                   Stmts   Miss  Cover   Missing
&lt;span class="nt"&gt;----------------------------------------------------&lt;/span&gt;
movies/controller.py      22      0   100%
movies/service.py         86      0   100%
movies/tasks.py            0      0   100%
&lt;span class="nt"&gt;----------------------------------------------------&lt;/span&gt;
TOTAL                    108      0   100%
&lt;span class="o"&gt;========================================================================&lt;/span&gt; 13 passed &lt;span class="k"&gt;in &lt;/span&gt;8.68s &lt;span class="o"&gt;========================================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NB: The test configuration had already been set &lt;a href="https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-a-codebase-design-ao3#testing-the-gears"&gt;&lt;code&gt;here&lt;/code&gt;&lt;/a&gt; in part 1. So if interested feel free to check it up...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Everythings seems good. Let have a view of our changes, run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvicorn main:app &lt;span class="nt"&gt;--reload&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;INFO:     Will watch &lt;span class="k"&gt;for &lt;/span&gt;changes &lt;span class="k"&gt;in &lt;/span&gt;these directories: &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'/path/to/media_app'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
INFO:     Uvicorn running on http://127.0.0.1:8006 &lt;span class="o"&gt;(&lt;/span&gt;Press CTRL+C to quit&lt;span class="o"&gt;)&lt;/span&gt;
INFO:     Started reloader process &lt;span class="o"&gt;[&lt;/span&gt;59568] using WatchFiles
INFO:     Started server process &lt;span class="o"&gt;[&lt;/span&gt;59588]
INFO:     Waiting &lt;span class="k"&gt;for &lt;/span&gt;application startup.
INFO:     Application startup complete.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2Fyfm3jh8dbmpbzeom6vf8.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.amazonaws.com%2Fuploads%2Farticles%2Fyfm3jh8dbmpbzeom6vf8.png" alt="App Loaded" width="800" height="331"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this endpoint, feel free to play with the endpoints. &lt;em&gt;(See what i did there)&lt;/em&gt;😏&lt;/p&gt;

&lt;p&gt;So, to add the final icing on this piece of cake, in the next section, we’ll be introducing the one and only Celery... 💃&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Offloading CPU Intensive Workloads with Celery
&lt;/h2&gt;

&lt;p&gt;If async gives FastAPI the speed of Superman, then adding Celery makes it the Flash on three cups of coffee and a shot of tequila.&lt;/p&gt;

&lt;p&gt;So first, we will conclude by updating the pending files related to crud operations for celery task processing. Go ahead and update the following files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_celery_setup/movies/router.py" rel="noopener noreferrer"&gt;&lt;code&gt;router.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_celery_setup/movies/controller.py" rel="noopener noreferrer"&gt;&lt;code&gt;controller.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_celery_setup/movies/service.py" rel="noopener noreferrer"&gt;&lt;code&gt;service.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_celery_setup/movies/tasks.py" rel="noopener noreferrer"&gt;&lt;code&gt;tasks.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;tests/unit/movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_celery_setup/tests/unit/movies/test_controller.py" rel="noopener noreferrer"&gt;&lt;code&gt;test_controller.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;tests/unit/movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_celery_setup/tests/unit/movies/test_service.py" rel="noopener noreferrer"&gt;&lt;code&gt;test_service.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;tests/unit/movies/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_celery_setup/tests/unit/movies/test_tasks.py" rel="noopener noreferrer"&gt;&lt;code&gt;test_tasks.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for the celery configuration itself update the following files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;shared/config/&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_celery_setup/shared/config/settings.py" rel="noopener noreferrer"&gt;&lt;code&gt;settings.py&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_celery_setup/celeryconfig.py" rel="noopener noreferrer"&gt;&lt;code&gt;celeryconfig.py&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we're done with the setup. Let's run the following command to get our celery workers up and running...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;celery &lt;span class="nt"&gt;-A&lt;/span&gt; shared.config.settings.redis_broker worker &lt;span class="nt"&gt;--loglevel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;INFO &lt;span class="nt"&gt;--concurrency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt; &lt;span class="nt"&gt;--------------&lt;/span&gt; celery@mrchike-vm v5.5.2 &lt;span class="o"&gt;(&lt;/span&gt;immunity&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="k"&gt;*****&lt;/span&gt; &lt;span class="nt"&gt;-----&lt;/span&gt; 
&lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="k"&gt;*******&lt;/span&gt; &lt;span class="nt"&gt;----&lt;/span&gt; Linux-6.8.0-60-generic-x86_64-with-glibc2.35 2025-07-10 00:32:39
- &lt;span class="k"&gt;***&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; 
- &lt;span class="k"&gt;**&lt;/span&gt; &lt;span class="nt"&gt;----------&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;config]
- &lt;span class="k"&gt;**&lt;/span&gt; &lt;span class="nt"&gt;----------&lt;/span&gt; .&amp;gt; app:         tasks:0x722396ee9cf0
- &lt;span class="k"&gt;**&lt;/span&gt; &lt;span class="nt"&gt;----------&lt;/span&gt; .&amp;gt; transport:   redis://:&lt;span class="k"&gt;**&lt;/span&gt;@localhost:6379/0
- &lt;span class="k"&gt;**&lt;/span&gt; &lt;span class="nt"&gt;----------&lt;/span&gt; .&amp;gt; results:     redis://:&lt;span class="k"&gt;**&lt;/span&gt;@localhost:6379/0
- &lt;span class="k"&gt;***&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nt"&gt;---&lt;/span&gt; .&amp;gt; concurrency: 4 &lt;span class="o"&gt;(&lt;/span&gt;prefork&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="k"&gt;*******&lt;/span&gt; &lt;span class="nt"&gt;----&lt;/span&gt; .&amp;gt; task events: OFF &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; to monitor tasks &lt;span class="k"&gt;in &lt;/span&gt;this worker&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nt"&gt;---&lt;/span&gt; &lt;span class="k"&gt;*****&lt;/span&gt; &lt;span class="nt"&gt;-----&lt;/span&gt; 
 &lt;span class="nt"&gt;--------------&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;queues]
                .&amp;gt; celery           &lt;span class="nv"&gt;exchange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;celery&lt;span class="o"&gt;(&lt;/span&gt;direct&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;celery


&lt;span class="o"&gt;[&lt;/span&gt;tasks]
  &lt;span class="nb"&gt;.&lt;/span&gt; movies.tasks.process_heavy_task

&lt;span class="o"&gt;[&lt;/span&gt;2025-07-10 00:32:40,268: INFO/MainProcess] Connected to redis://:&lt;span class="k"&gt;**&lt;/span&gt;@localhost:6379/0
&lt;span class="o"&gt;[&lt;/span&gt;2025-07-10 00:32:40,286: INFO/MainProcess] mingle: searching &lt;span class="k"&gt;for &lt;/span&gt;neighbors
&lt;span class="o"&gt;[&lt;/span&gt;2025-07-10 00:32:41,385: INFO/MainProcess] mingle: all alone
&lt;span class="o"&gt;[&lt;/span&gt;2025-07-10 00:32:41,494: INFO/MainProcess] celery@mrchike-vm ready.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tasks have been registered and now we need to execute this through the api.&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.amazonaws.com%2Fuploads%2Farticles%2F8v7pc48vsypppj38udx0.gif" 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.amazonaws.com%2Fuploads%2Farticles%2F8v7pc48vsypppj38udx0.gif" alt="Celery Api calls" width="1920" height="827"&gt;&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="o"&gt;[&lt;/span&gt;2025-07-10 00:37:33,717: INFO/MainProcess] Task movies.tasks.process_heavy_task[c0553b69-9529-42df-8ce4-506b3fa8d2ed] received
&lt;span class="o"&gt;[&lt;/span&gt;2025-07-10 00:41:37,690: INFO/ForkPoolWorker-4] &lt;span class="o"&gt;==============================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;2025-07-10 00:41:37,692: INFO/ForkPoolWorker-4] Successfully Processed 1 Billion Transactions...
&lt;span class="o"&gt;[&lt;/span&gt;2025-07-10 00:41:37,692: INFO/ForkPoolWorker-4] &lt;span class="o"&gt;==============================================&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;2025-07-10 00:41:37,723: INFO/ForkPoolWorker-4] Task movies.tasks.process_heavy_task[c0553b69-9529-42df-8ce4-506b3fa8d2ed] succeeded &lt;span class="k"&gt;in &lt;/span&gt;243.99923642900103s: 1000000000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This task takes 243.999 seconds, which is approximately 4.07 minutes. Now imagine if this task weren’t offloaded to the background using Celery, and your user had to wait the full 4 minutes before being able to continue. That’s enough time to completely lose their attention, and likely their patience.&lt;/p&gt;

&lt;p&gt;Now scale that up to thousands or even millions of users. Blocking execution like that doesn’t just degrade user experience, it can cripple your application. Background task queues like Celery aren’t just convenient but essential for performance and scalability.&lt;/p&gt;

&lt;p&gt;At this point your changes would have reflected in the Redis DB. Check it up. And that's a wrap for this section. We'll be moving to project documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  📄 Project Documentation with MKDocs
&lt;/h2&gt;

&lt;p&gt;The project documentation we will be building can be found below but it's important to note that the documentation structure has already been set when you ran the setup script.&lt;/p&gt;

&lt;p&gt;To enable display of our documentation static files, we would be udpating the &lt;code&gt;main.py&lt;/code&gt; to include static &lt;a href="https://github.com/MrChike/media_app/blob/seriesB_project_docs/main.py#L3" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;import&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://github.com/MrChike/media_app/blob/seriesB_project_docs/main.py#L22" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;mounting&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After you're done with the update. You can now access the documentation page on &lt;a href="http://127.0.0.1:8000/docs/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;http://127.0.0.1:8000/docs/&lt;/code&gt;&lt;/strong&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2F7xdt3pws4pecnbxcyi75.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.amazonaws.com%2Fuploads%2Farticles%2F7xdt3pws4pecnbxcyi75.png" alt="project docs site" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now for the grand finale, let's put it all in a box.&lt;/p&gt;

&lt;h2&gt;
  
  
  🐳 Running Your Project in Docker
&lt;/h2&gt;

&lt;p&gt;To wrap things up, you will be updating the following files&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_docker_setup/docker-compose.api.yaml" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;docker-compose.api.yaml&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_docker_setup/Dockerfile" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_docker_setup/Dockerfile.nginx" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;Dockerfile.nginx&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_docker_setup/nginx.conf" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;nginx.conf&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/MrChike/media_app/blob/seriesB_docker_setup/entrypoint.sh" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;entrypoint.sh&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Take your time and go through the &lt;code&gt;DockerFile&lt;/code&gt;s. &lt;strong&gt;That's your assignment&lt;/strong&gt;.&lt;br&gt;
What i would be focusing on is explaining &lt;strong&gt;Nginx&lt;/strong&gt; and &lt;strong&gt;Entrypoint&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nginx&lt;/strong&gt; serves as a reverse proxy. &lt;br&gt;
What's a reverse proxy, you asked?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A &lt;strong&gt;reverse proxy&lt;/strong&gt; is a server that sits between clients and backend servers, forwarding client requests to the appropriate backend server and then returning the server's response back to the client and &lt;code&gt;nginx.conf&lt;/code&gt; is what handles this.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;strong&gt;entrypoint&lt;/strong&gt; is designed to build your project documentation, run your database migrations, execute tests, and start the application. All of this is very helpful when done during each build. However, what’s most important for me to explain to you is the &lt;code&gt;set -e&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;set -e&lt;/code&gt; is used to make your script safer and more predictable by stopping execution as soon as something goes wrong. For example, if your tests fail, the app won't start, which is actually very helpful. It gives you a sense of what proper CI/CD should look like: your code shouldn’t be deployed to production if the tests are failing.&lt;/p&gt;

&lt;p&gt;During development, you can comment it out to avoid interruptions, but once you're done, be sure to turn it back on.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;🔧 Update the service hostnames in your &lt;code&gt;.env&lt;/code&gt; file to match these: 👉 &lt;a href="https://github.com/MrChike/media_app/blob/seriesB_docker_env_vars/.example.env" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;env.example&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The hostnames are the same as the service names defined in your Docker Compose file. This allows containers to communicate with each other via Docker’s internal networking, so you won’t need to manually update IP addresses every time.&lt;/p&gt;

&lt;p&gt;Now run the following 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="c"&gt;# Stop and remove containers, including orphans&lt;/span&gt;
docker-compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.db.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.api.yaml down &lt;span class="nt"&gt;--remove-orphans&lt;/span&gt;

&lt;span class="c"&gt;# Build and start services&lt;/span&gt;
docker-compose &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.db.yaml &lt;span class="nt"&gt;-f&lt;/span&gt; docker-compose.api.yaml up &lt;span class="nt"&gt;--build&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;And with that, we've come to the end of this tutorial.&lt;br&gt;
In the next part of this series, we'll focus on deploying our app for a live demo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Enjoyed this article?&lt;/strong&gt; Connect with me on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/chikeegonu/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;LinkedIn&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐙 &lt;a href="https://github.com/MrChike" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;GitHub&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your support means a lot, if you’d like to buy me a coffee ☕️ to keep me fueled, feel free to check out &lt;a href="https://buymeacoffee.com/mrchike" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;this link&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;. Your generosity would go a long way in helping me continue to create content like this.&lt;/p&gt;

&lt;p&gt;Until next time, happy coding! 👨🏾‍💻🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Previously Written Articles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔥 &lt;em&gt;FastAPI in Production: Build, Scale &amp;amp; Deploy – Series A: Codebase Design&lt;/em&gt; → &lt;a href="https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-a-codebase-design-ao3"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;Read here&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;em&gt;Series-X: Create Professional Portfolios Using Material for MkDocs&lt;/em&gt; → &lt;a href="https://dev.to/mrchike/series-x-create-professional-portfolios-using-material-for-mkdocs-fio"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;Read here&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;How to Learn Effectively &amp;amp; Efficiently as a Professional in any Field&lt;/em&gt; 🧠⏱️🎯 → &lt;a href="https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;Read here&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>fastapi</category>
      <category>python</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>🚀 Create Professional Portfolios Using Material for MkDocs (Series-X)</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Mon, 21 Jul 2025 06:00:10 +0000</pubDate>
      <link>https://dev.to/mrchike/series-x-create-professional-portfolios-using-material-for-mkdocs-fio</link>
      <guid>https://dev.to/mrchike/series-x-create-professional-portfolios-using-material-for-mkdocs-fio</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;&lt;em&gt;See the source code on GitHub&lt;/em&gt;&lt;/strong&gt;: &lt;a href="https://github.com/MrChike/mkdocs-portfolio" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;Material for MkDocs Portfolio Template&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
🔥 &lt;strong&gt;&lt;em&gt;Live Demo&lt;/em&gt;&lt;/strong&gt;: &lt;a href="https://mrchike.github.io/portfolio/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;Portfolio Site&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;This article teaches you how to create stunning, professional portfolios using Material for MkDocs,  a fast, customizable, and open-source static site generator trusted by over 20,000 users to build responsive, searchable, and beautifully designed websites.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is one of the most frustrating article I've ever written &lt;em&gt;(Weird way to start an article, right?)&lt;/em&gt; 😜. It was truly a bittersweet experience. &lt;/p&gt;

&lt;p&gt;&lt;em&gt;Did I hear you say why? Glad you asked... Now let me lay it down for you.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ✌️ Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⚙️ &lt;strong&gt;&lt;code&gt;Environment Setup (Optional)&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;📦 &lt;strong&gt;&lt;code&gt;Project Scaffolding&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🤬 &lt;strong&gt;&lt;code&gt;Frustrations (Optional)&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🚶‍♂️ &lt;strong&gt;&lt;code&gt;Walk Through&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;🚀 &lt;strong&gt;&lt;code&gt;Deployment (Github Actions Included)&lt;/code&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  ⚙️ Environment Setup (Optional)
&lt;/h2&gt;

&lt;p&gt;I always write my articles with beginners in mind because I was once one, too. If you're already experienced, feel free to skip this section. This guide assumes you're using Ubuntu Linux. The following commands will help you to set up a fresh server environment and serve as a reference point some time in the future because eventually, you’ll probably be needing it again. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 For other Linux distributions&lt;/strong&gt;: Replace &lt;code&gt;apt&lt;/code&gt; with your system's package manager like &lt;code&gt;yum&lt;/code&gt;, &lt;code&gt;pkg&lt;/code&gt;, &lt;code&gt;apk&lt;/code&gt; and so on. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 For Windows users&lt;/strong&gt;: You can install &lt;a href="https://github.com/microsoft/WSL?tab=readme-ov-file#about" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;Windows Subsystem for Linux (WSL)&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; with the command &lt;code&gt;wsl --install&lt;/code&gt; in your terminal, access it with your favourite code editor and then run the commands below.&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;# Update package lists and upgrade existing packages&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt; update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt; upgrade

&lt;span class="c"&gt;# Install Docker, Docker Compose, and add current user to the docker group for non-root access&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;docker.io
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;docker-compose
&lt;span class="nb"&gt;sudo &lt;/span&gt;usermod &lt;span class="nt"&gt;-aG&lt;/span&gt; docker &lt;span class="nv"&gt;$USER&lt;/span&gt;

&lt;span class="c"&gt;# Install useful dependencies&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;tree
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;vim

&lt;span class="c"&gt;# Install Python 3.10 virtual environment package&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;python3.10-venv

&lt;span class="c"&gt;# Install pip for Python 3&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;python3-pip

&lt;span class="c"&gt;# Install OpenSSH server and enable/start the SSH service&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="nb"&gt;install &lt;/span&gt;openssh-server
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;ssh
&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl start ssh

&lt;span class="c"&gt;# Allow SSH through the firewall and enable UFW (Uncomplicated Firewall)&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw allow ssh
&lt;span class="nb"&gt;sudo &lt;/span&gt;ufw &lt;span class="nb"&gt;enable&lt;/span&gt;

&lt;span class="c"&gt;# Generate a new RSA SSH key pair with no passphrase and a comment for identification&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; rsa &lt;span class="nt"&gt;-f&lt;/span&gt; ~/.ssh/id_rsa &lt;span class="nt"&gt;-N&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"ssh-key"&lt;/span&gt;

&lt;span class="c"&gt;# Reboot the system to apply changes&lt;/span&gt;
&lt;span class="nb"&gt;sudo &lt;/span&gt;shutdown &lt;span class="nt"&gt;-r&lt;/span&gt; now

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

&lt;/div&gt;



&lt;p&gt;Now that we're done with running the above commands and restarting the server so changes take full effect, we will be moving to the next section which will be...&lt;/p&gt;

&lt;h2&gt;
  
  
  📦 Project Scaffolding
&lt;/h2&gt;

&lt;p&gt;In this section, we will setting up the project structure by creating and executing the &lt;a href="https://github.com/MrChike/mkdocs-portfolio/blob/master/setup.sh" rel="noopener noreferrer"&gt;&lt;code&gt;setup.sh&lt;/code&gt;&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;# Create &amp;amp; make setup script executable&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;setup.sh &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chmod&lt;/span&gt; +x setup.sh

&lt;span class="c"&gt;# Excute setup script (populate script from github link provided)&lt;/span&gt;
./setup.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After successful execution, your project directory should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;portfolio/
├── .github
├── .gitignore
├── Journal.md
├── docs
├── mkdocs.yml
├── requirements.txt
└── site
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To activate your virtual environment and start the project, run the following 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="c"&gt;# Activate virtual environment&lt;/span&gt;
&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate

&lt;span class="c"&gt;# Navigate into the project folder&lt;/span&gt;
&lt;span class="nb"&gt;cd &lt;/span&gt;portfolio

&lt;span class="c"&gt;# Start the development serve&lt;/span&gt;
mkdocs serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;INFO    -  Building documentation...
INFO    -  Cleaning site directory
INFO    -  Documentation built &lt;span class="k"&gt;in &lt;/span&gt;0.31 seconds
INFO    -  &lt;span class="o"&gt;[&lt;/span&gt;17:59:56] Watching paths &lt;span class="k"&gt;for &lt;/span&gt;changes: &lt;span class="s1"&gt;'docs'&lt;/span&gt;, &lt;span class="s1"&gt;'mkdocs.yml'&lt;/span&gt;
INFO    -  &lt;span class="o"&gt;[&lt;/span&gt;17:59:56] Serving on http://127.0.0.1:8000/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you happen to be running on a VM or an external server. You can use this instead, as it binds the IP to the host to make it accessible on your web browser.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mkdocs serve &lt;span class="nt"&gt;-a&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;hostname&lt;/span&gt; &lt;span class="nt"&gt;-I&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $1}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:8000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Head to the project URL, and you should see the screen below in your browser, which means the portfolio template is now up and running! 🚀&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.amazonaws.com%2Fuploads%2Farticles%2Fp8o8fcse87ydu24g41uu.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.amazonaws.com%2Fuploads%2Farticles%2Fp8o8fcse87ydu24g41uu.png" alt="Project Display" width="800" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt; &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;📌 When the foundation is not solid, everything built upon it will crumble in due time.&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
 &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The setup script that was run established a solid foundation. However, if you want to build on top of that, this reference page is crucial: &lt;a href="https://squidfunk.github.io/mkdocs-material/customization/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;https://squidfunk.github.io/mkdocs-material/customization/&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt; because it’s what will take your portfolio from what you see above to what you'll see below 👇.&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.amazonaws.com%2Fuploads%2Farticles%2F8phcyy1zyp6cz9xz4vzk.gif" 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.amazonaws.com%2Fuploads%2Farticles%2F8phcyy1zyp6cz9xz4vzk.gif" alt="Slide" width="1920" height="1007"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  🤬 Frustrations (Optional)
&lt;/h2&gt;

&lt;p&gt;This tutorial might look cute, but let me tell you, there was a &lt;strong&gt;whooooole lotta frustration&lt;/strong&gt; trying to figure out where to put what, getting things to work, and why something that worked perfectly on local breaks in production. &lt;em&gt;(That kind of mess)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It got so annoying that I ended up writing a script to scaffold the whole project from scratch because, just like a Microsoft Word CV, one tiny tweak can break the whole format, and suddenly you're spending hours trying to reformat stuff that shouldn't even be broken in the first place. And ohhhh! Don't even get me started on setting up &lt;strong&gt;&lt;em&gt;Github Actions&lt;/em&gt;&lt;/strong&gt;, that was the real rabbit hole 2.0. What I thought would take me just a few hours to figure out ended up taking a week.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚶‍♂️ Walk Through
&lt;/h2&gt;

&lt;p&gt;Wheeeew! Now that I’ve got that off my chest. Allow me, your one and only tour guide, &lt;a href="https://www.linkedin.com/in/chikeegonu/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;MrChike&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;, to take you on a cruise through the inner workings of this project.&lt;br&gt;
Ready, Player One? 🎮&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;docs/&lt;/strong&gt;: Your development environment (HTML, CSS &amp;amp; JavaScript)

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;overrides/&lt;/strong&gt;: Customise any part of the site to your taste&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;💡 Treat the markdowns(*.md) files like HTML:&lt;/strong&gt; you can add HTML tags like &lt;code&gt;div&lt;/code&gt; to it, and it would still work because it would be converted to index.html, as you will see under &lt;code&gt;site/&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docs/
├── articles.md
├── assets
│   ├── images
│   │   └── logo.svg
│   ├── javascripts
│   │   └── extra.js
│   └── stylesheets
│       └── extra.css
├── certifications.md
├── contributions.md
├── index.md
├── overrides
│   └── partials
│       └── logo.html
└── projects.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;sites/&lt;/strong&gt;: Production environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;💡 This folder is intended for public access&lt;/strong&gt;. You don't need to modify it manually as it's regenerated before each deployment. That's why it's included in &lt;code&gt;.gitignore&lt;/code&gt;. This folder is what gets deployed to the &lt;code&gt;gh-pages&lt;/code&gt; branch and displayed on your portfolio website.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;site/
├── 404.html
├── articles
│   └── index.html
├── assets
│   ├── images
│   ├── javascripts
│   └── stylesheets
├── certifications
│   └── index.html
├── contributions
│   └── index.html
├── css
│   ├── base.css
│   ├── bootstrap.min.css
│   ├── bootstrap.min.css.map
│   ├── brands.min.css
│   ├── fontawesome.min.css
│   ├── solid.min.css
│   └── v4-font-face.min.css
├── img
│   ├── favicon.ico
│   └── grid.png
├── index.html
├── js
│   ├── base.js
│   ├── bootstrap.bundle.min.js
│   ├── bootstrap.bundle.min.js.map
│   └── darkmode.js
├── overrides
│   └── partials
├── projects
│   └── index.html
├── search
│   ├── lunr.js
│   ├── main.js
│   ├── search_index.json
│   └── worker.js
├── sitemap.xml
├── sitemap.xml.gz
└── webfonts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;deploy.yml:&lt;/strong&gt; Github Actions Configuration file for automated deployment
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;.github/
└── workflows
    └── deploy.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Journal.md:&lt;/strong&gt; A log of your experiences and insights while working on your projects. &lt;em&gt;(Keeping a journal is a great habit to develop when working on projects.)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mkdocs.yml:&lt;/strong&gt; Configuration file for MKDocs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;requirements.txt:&lt;/strong&gt; Lists your project dependencies. &lt;em&gt;(It's good practice to include specific versions, as dependencies are frequently updated and changes may break your project in the future.)&lt;/em&gt;
&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="nb"&gt;.&lt;/span&gt;
├── Journal.md
├── mkdocs.yml
└── requirements.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you have a good grasp of the project structure, let's advance to deployment.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 Deployment (Github Actions Included)
&lt;/h2&gt;

&lt;p&gt;In this section, we will focus on both manual and automated deployment but first i will lay down the steps in order to follow.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📁 Create a &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;GitHub&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; Repository &lt;em&gt;(if not existing already)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;🔑 Generate SSH keys&lt;/li&gt;
&lt;li&gt;🗝️ Add your SSH public key to GitHub&lt;/li&gt;
&lt;li&gt;🧑‍💻 Manual Deployment using &lt;code&gt;mkdocs gh-deploy&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;🔐 Create a Personal Access Token (PAT)&lt;/li&gt;
&lt;li&gt;🤫 Add the PAT as a GitHub Secret&lt;/li&gt;
&lt;li&gt;🤖 Automated Deployment using GitHub Actions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  📁 Create a GitHub Repository
&lt;/h3&gt;

&lt;p&gt;Take Home Assignment: &lt;strong&gt;Figure it out! 😉&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  🔑 Generate SSH keys
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;First, confirm if you have SSH keys available
&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="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lh&lt;/span&gt; ~/.ssh/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;-rw-------&lt;/span&gt; 1 mrchike mrchike 2.6K Jun 20 05:26 id_rsa
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 mrchike mrchike  572 Jun 20 05:26 id_rsa.pub
&lt;span class="nt"&gt;-rw-------&lt;/span&gt; 1 mrchike mrchike  978 Jun 20 05:28 known_hosts
&lt;span class="nt"&gt;-rw-r--r--&lt;/span&gt; 1 mrchike mrchike  142 Jun 20 05:16 known_hosts.old
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 The &lt;code&gt;id_rsa.pub&lt;/code&gt; is your authentication public key to access external servers (in this case, GitHub). &lt;/p&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Note on SSH Keys:&lt;/strong&gt;&lt;br&gt;
If you try using a custom name for your SSH key (i.e something other than &lt;code&gt;id_rsa.pub&lt;/code&gt;), GitHub may reject the connection during deployment. If you encounter this issue, a simple workaround is to generate a new key and overwrite the existing one using the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-keygen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will recreate &lt;code&gt;id_rsa&lt;/code&gt; and &lt;code&gt;id_rsa.pub&lt;/code&gt;, which are the default names GitHub expects unless otherwise configured.&lt;/p&gt;

&lt;p&gt;You will need to register it on your GitHub account to have access to push/pull changes. So run the following command to print it out.&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;cat&lt;/span&gt; ~/.ssh/id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDKiPnhAeI70ooWzt7yDgopgmgllifUBwvev1RKBq/UM1rQ/std0PHokt+qcGZlIAtFWUsGdOZi+FDLpOywsL1+XO4UlBVW4M/qQasoVnE/CdT77GxaZQ0btYlHm5FS4mKYRWtxSIxjq3b+qRWB6U4KFkfOG3iQAinLI+iD0olcAikCaA8mRKTg541+qDxY33oSE3a9svjP8keVmB9ALN6zdGoDuLa3gX9OCK8wIOzewYDFfr3wMHpT/oJ0sG5oPtBFMBDHJcdt46T+u3uZCbaRs/Hre7UbYXgXkcQWNZ8fpSj4JieebjP8MrHxkRVG5mmM5/wumaC342fmTBbiA4wJUhOErR7zX/SDlUN5NDAyBiq7vDhdkVrj3sTisXgGnboRhLbrOt0TzAo3QRxyXQTZe7rQPh+9D/DDLgGuVz0PB0YOvSDcbVpWwsZvWzE+oBJi9Xxp3bkJH79+6M/AUZ36D9qd1jzI8sTf1+LNj8nxdNtIWmDtpWeRIIbgBcfusvs&lt;span class="o"&gt;=&lt;/span&gt; YOUR-SSH-KEY

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

&lt;/div&gt;



&lt;p&gt;Now, copy your SSH Key as you'll be needing it for the next step.&lt;/p&gt;

&lt;h3&gt;
  
  
  🗝️ Add your SSH public key to GitHub
&lt;/h3&gt;

&lt;p&gt;You can register your SSH key in one of two ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User-wide access:
&lt;a href="https://github.com/settings/keys" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;https://github.com/settings/keys&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repo-specific access &lt;strong&gt;&lt;code&gt;(Deploy Key)&lt;/code&gt;&lt;/strong&gt;:
&lt;code&gt;https://github.com/YOUR-USERNAME/REPO-NAME/settings/keys&lt;/code&gt; 

&lt;ul&gt;
&lt;li&gt;e.g &lt;code&gt;https://github.com/MrChike/temp/settings/keys&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;💡 Your use case should determine your preference.&lt;/p&gt;

&lt;p&gt;If you want to use the key across multiple repositories from the same machine, go with user-wide access.&lt;/p&gt;

&lt;p&gt;If you only want to allow access to a single repository (i.e for CI/CD purposes), then use a repo-specific deploy key.&lt;/p&gt;

&lt;p&gt;Once you've decided on your preference, &lt;strong&gt;add your SSH Key&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;📌 For Repo-specific access &lt;strong&gt;&lt;code&gt;(Deploy Key)&lt;/code&gt;&lt;/strong&gt; make sure you tick &lt;code&gt;Allow write access&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Congrats! 🎉 It's time to see our first deployment in action.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧑‍💻 Manual Deployment using &lt;code&gt;mkdocs gh-deploy&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;First we will start by initializing git in our project forlder&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;hint: Using &lt;span class="s1"&gt;'master'&lt;/span&gt; as the name &lt;span class="k"&gt;for &lt;/span&gt;the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use &lt;span class="k"&gt;in &lt;/span&gt;all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint:   git config &lt;span class="nt"&gt;--global&lt;/span&gt; init.defaultBranch &amp;lt;name&amp;gt;
hint: 
hint: Names commonly chosen instead of &lt;span class="s1"&gt;'master'&lt;/span&gt; are &lt;span class="s1"&gt;'main'&lt;/span&gt;, &lt;span class="s1"&gt;'trunk'&lt;/span&gt; and
hint: &lt;span class="s1"&gt;'development'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; The just-created branch can be renamed via this &lt;span class="nb"&gt;command&lt;/span&gt;:
hint: 
hint:   git branch &lt;span class="nt"&gt;-m&lt;/span&gt; &amp;lt;name&amp;gt;
Initialized empty Git repository &lt;span class="k"&gt;in&lt;/span&gt; /path/to/project/portfolio/.git/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then set your preferred default branch name. Feel free to name it whatever you want but in this tutorial i will be going with &lt;code&gt;master&lt;/code&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 config &lt;span class="nt"&gt;--global&lt;/span&gt; init.defaultBranch master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've done that, let's connect to our remote repo, commit changes and push to the master branch. Also, note that all GitHub-related URLs should be yours, I only use this tutorial repo to serve as a guide.&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;# Connects your local repo to the remote GitHub repository via SSH&lt;/span&gt;
git remote add origin git@github.com:MrChike/mkdocs-portfolio.git

&lt;span class="c"&gt;# Stages all changes and commits them with a message&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial Commit"&lt;/span&gt;

&lt;span class="c"&gt;# Pushes the 'master' branch to GitHub and sets it as the upstream branch&lt;/span&gt;
git push &lt;span class="nt"&gt;--set-upstream&lt;/span&gt; origin master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;master &lt;span class="o"&gt;(&lt;/span&gt;root-commit&lt;span class="o"&gt;)&lt;/span&gt; 516f9ae] Initial Commit
 14 files changed, 159 insertions&lt;span class="o"&gt;(&lt;/span&gt;+&lt;span class="o"&gt;)&lt;/span&gt;
 create mode 100644 .github/workflows/deploy.yml
 create mode 100644 .gitignore
 create mode 100644 Journal.md
 create mode 100644 docs/articles.md
 create mode 100644 docs/assets/images/logo.svg
 create mode 100644 docs/assets/javascripts/extra.js
 create mode 100644 docs/assets/stylesheets/extra.css
 create mode 100644 docs/certifications.md
 create mode 100644 docs/contributions.md
 create mode 100644 docs/index.md
 create mode 100644 docs/overrides/partials/logo.html
 create mode 100644 docs/projects.md
 create mode 100644 mkdocs.yml
 create mode 100644 requirements.txt

Enumerating objects: 24, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;24/24&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Delta compression using up to 12 threads
Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;11/11&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Writing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;24/24&lt;span class="o"&gt;)&lt;/span&gt;, 3.23 KiB | 826.00 KiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Total 24 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, reused 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 0
To github.com:MrChike/temp.git
 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;new branch]      master -&amp;gt; master
Branch &lt;span class="s1"&gt;'master'&lt;/span&gt; &lt;span class="nb"&gt;set &lt;/span&gt;up to track remote branch &lt;span class="s1"&gt;'master'&lt;/span&gt; from &lt;span class="s1"&gt;'origin'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we've pushed, let's deploy our site by running the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mkdocs gh-deploy &lt;span class="nt"&gt;--force&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: /path/to/portfolio/site
INFO    -  Documentation built &lt;span class="k"&gt;in &lt;/span&gt;0.39 seconds
WARNING -  Version check skipped: No version specified &lt;span class="k"&gt;in &lt;/span&gt;previous deployment.
INFO    -  Copying &lt;span class="s1"&gt;'/path/to/portfolio/site'&lt;/span&gt; to &lt;span class="s1"&gt;'gh-pages'&lt;/span&gt; branch and pushing to GitHub.
Enumerating objects: 72, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;72/72&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Delta compression using up to 12 threads
Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;63/63&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Writing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;72/72&lt;span class="o"&gt;)&lt;/span&gt;, 579.32 KiB | 1.66 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Total 72 &lt;span class="o"&gt;(&lt;/span&gt;delta 8&lt;span class="o"&gt;)&lt;/span&gt;, reused 0 &lt;span class="o"&gt;(&lt;/span&gt;delta 0&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 0
remote: Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;8/8&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: 
remote: Create a pull request &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="s1"&gt;'gh-pages'&lt;/span&gt; on GitHub by visiting:
remote:      https://github.com/MrChike/mkdocs-portfolio/pull/new/gh-pages
remote: 
To github.com:MrChike/mkdocs-portfolio.git
 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;new branch]      gh-pages -&amp;gt; gh-pages
INFO    -  Your documentation should shortly be available at: https://MrChike.github.io/mkdocs-portfolio/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, the portfolio site should be hosted on the link provided. In this case &lt;a href="https://MrChike.github.io/mkdocs-portfolio/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;https://MrChike.github.io/mkdocs-portfolio/&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have yours set up and working, a huge congratulations! &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;At this point, you might be wondering: if I can manually deploy my site from my local machine, why bother automating it?&lt;br&gt;
Honestly, I don’t even know why I decided to take it a step further. But this is when I finally understood what Nagato meant when he said to Naruto:&lt;/em&gt; &lt;strong&gt;&lt;em&gt;"And now... You shall know pain."&lt;/em&gt;&lt;/strong&gt; 😵‍💫&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  🔐 Create a Personal Access Token (PAT)
&lt;/h3&gt;

&lt;p&gt;Head to your Github account and create your personal access token at &lt;a href="https://github.com/settings/personal-access-tokens" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;https://github.com/settings/personal-access-tokens&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fill in the details as needed. Under &lt;strong&gt;Repository access&lt;/strong&gt;, select your preference (either all repos or just specific ones).&lt;br&gt;
Most importantly, under &lt;strong&gt;Permissions&lt;/strong&gt;, you’ll see two sections: &lt;strong&gt;Repository permissions&lt;/strong&gt; and &lt;strong&gt;Account permissions&lt;/strong&gt;. Go ahead and give everything under both sections &lt;strong&gt;read/write access&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once that’s done, scroll down and hit &lt;strong&gt;Generate token&lt;/strong&gt;.&lt;br&gt;
it's important that you copy this token and save somewhere because once you leave that page the only way to use it if forgotten is to regenerate it.&lt;br&gt;
 &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📌 &lt;strong&gt;&lt;em&gt;NB:&lt;/em&gt;&lt;/strong&gt; &lt;em&gt;It took me a while to figure this one out because without it, you’ll keep running into errors when deploying with GitHub Actions. At some point, I was really losing patience, so I just gave everything under both permission sections read/write access. When you have time, feel free to go back and untick anything you don’t actually need.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  🤫 Add the PAT as a GitHub Secret
&lt;/h3&gt;

&lt;p&gt;Head to your repo → &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Secrets and variables&lt;/strong&gt; → &lt;strong&gt;Actions&lt;/strong&gt;, and create a new repository secret for your token.&lt;/p&gt;

&lt;p&gt;Populate the following fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;ACCESS_TOKEN&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Secret: &lt;em&gt;Paste the personal access token you just generated and copied
Then click Save&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives GitHub Actions access for automated deployments&lt;/p&gt;

&lt;h3&gt;
  
  
  🤖 Automated Deployment using GitHub Actions
&lt;/h3&gt;

&lt;p&gt;To wrap things up, we'll automate deployment to run daily at 12:00 AM, ensuring any updates to your portfolio are always live.&lt;/p&gt;

&lt;p&gt;But first, let’s give credit where it’s due.&lt;br&gt;
A huge shoutout to &lt;a href="https://github.com/peaceiris/actions-gh-pages" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;peaceiris&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt; for simplifying what could have been a tedious process. Check out the repo when you have time, it's worth it!&lt;/p&gt;

&lt;p&gt;Now, update your &lt;strong&gt;deploy.yml&lt;/strong&gt; file with &lt;a href="https://github.com/MrChike/mkdocs-portfolio/blob/master/.github/workflows/deploy.yml" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;the following configuration&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;📝 The inline comments explain each section, but here are a few key points to emphasize:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;branches:&lt;/code&gt;&lt;br&gt;
Update this to match the branch you're deploying from (&lt;code&gt;master&lt;/code&gt;, &lt;code&gt;main&lt;/code&gt;, or multiple branches if needed). The workflow will only trigger on changes to the specified branch(es).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;personal_token:&lt;/code&gt;&lt;br&gt;
Do not change this key name. It must be exactly &lt;code&gt;personal_token&lt;/code&gt;, that’s what the GitHub Action expects.&lt;br&gt;
However, the repository secret name (i.e &lt;code&gt;ACCESS_TOKEN&lt;/code&gt;) can be whatever you like, just make sure the name you use in &lt;code&gt;Secrets and variables → Actions&lt;/code&gt; matches what you reference in the workflow.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;commit and &lt;strong&gt;push your changes to the repo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can monitor your deployment runs under the Actions tab in your GitHub repo. Each run will show success/failure logs and scheduling history as displayed in the screenshot below..&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.amazonaws.com%2Fuploads%2Farticles%2Fy37z0xq8c5dol8eivkiu.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.amazonaws.com%2Fuploads%2Farticles%2Fy37z0xq8c5dol8eivkiu.png" alt="Github Action" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's all folks. It's been an interest ride so far and if you have any blockers I'm open to mentor and assist.&lt;/p&gt;

&lt;p&gt;Would you like a deeper dive on this topic? 👉 &lt;a href="https://pollunit.com/polls/cwd-jffounjbgnrz8nzksw" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;code&gt;Cast your vote&lt;/code&gt;&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Enjoyed this article?&lt;/strong&gt; Connect with me on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/chikeegonu/" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;LinkedIn&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐙 &lt;a href="https://github.com/MrChike" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;GitHub&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your support means a lot, if you’d like to buy me a coffee ☕️ to keep me fueled, feel free to check out &lt;a href="https://buymeacoffee.com/mrchike" rel="noopener noreferrer"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;this link&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;. Your generosity would go a long way in helping me continue to create content like this.&lt;/p&gt;

&lt;p&gt;Until next time, happy coding! 👨🏾‍💻🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Previously Written Articles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🔥 &lt;em&gt;FastAPI in Production: Build, Scale &amp;amp; Deploy – Series A: Codebase Design&lt;/em&gt; → &lt;a href="https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-a-codebase-design-ao3"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;Read here&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;How to Learn Effectively &amp;amp; Efficiently as a Professional in any Field&lt;/em&gt; 🧠⏱️🎯 → &lt;a href="https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d"&gt;&lt;strong&gt;&lt;em&gt;&lt;code&gt;Read here&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>softwaredevelopment</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🔥 FastAPI in Production: Build, Scale &amp; Deploy – Series A: Codebase Design</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Mon, 02 Jun 2025 00:05:33 +0000</pubDate>
      <link>https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-a-codebase-design-ao3</link>
      <guid>https://dev.to/mrchike/fastapi-in-production-build-scale-deploy-series-a-codebase-design-ao3</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Welcome to Part 1 of the 3-part FastAPI Series&lt;/strong&gt; 📦 - &lt;a href="https://github.com/MrChike/media_app/tree/seriesA" rel="noopener noreferrer"&gt;View Full Code on GitHub&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We are building a &lt;strong&gt;scalable, production-ready FastAPI codebase&lt;/strong&gt; from the ground up. Along the way, we'll cover project structure, environment setup, dependency injection, and async I/O-bound API calls.&lt;/p&gt;

&lt;p&gt;Whether you're working on monoliths, microservices, or event-driven systems, this guide is about laying a clean, modular, and solid foundation, one that’s been tested in real-world environments, not just spun up for a quick demo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;🧠 A Bit of Background
&lt;/li&gt;
&lt;li&gt;🎯 What to Expect
&lt;/li&gt;
&lt;li&gt;🗂️ Project Structure Overview
&lt;/li&gt;
&lt;li&gt;🏗️ Project Initialization
&lt;/li&gt;
&lt;li&gt;🔄 Request Lifecycle
&lt;/li&gt;
&lt;li&gt;🧪 Testing the Gears
&lt;/li&gt;
&lt;li&gt;🏁 Conclusion
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  🧠 A Bit of Background
&lt;/h2&gt;

&lt;p&gt;Like many developers, I started with Python. I was eager to learn (still am), and dove into every tutorial I could find. It didn’t take long before I hit &lt;strong&gt;&lt;em&gt;Tut🔥rial Hell&lt;/em&gt;&lt;/strong&gt;, you know that endless loop where every new video feels like I've finally found the ch🙌sen one. Spoiler alert: it never was...&lt;/p&gt;

&lt;p&gt;But that hell did prepare me well enough to land an internship. And to my surprise, I realized I was actually light years ahead of my peers.&lt;/p&gt;

&lt;p&gt;That internship was a deep dive into the real world: a full-scale, SaaS, enterprise-grade KPI management system built with Django, serving over 100K users (with more being onboarded regularly). It was the first time I saw Python used at scale in a production environment and it completely changed how I thought about architecture and design.&lt;/p&gt;

&lt;p&gt;Since then, I’ve worked on Python applications across different industries, helping teams scale their systems (and occasionally refactoring parts of legacy code).&lt;/p&gt;

&lt;p&gt;Eventually, I started hearing about the latest kid on the block: &lt;strong&gt;FastAPI&lt;/strong&gt;, the &lt;em&gt;"speedster"&lt;/em&gt; of the Python ecosystem. I checked it out, watched a bunch of tutorials... and quickly noticed a pattern: a lot of them were just theory. Surface-level. Book-knowledge.&lt;/p&gt;

&lt;p&gt;This series is my attempt to share what I’ve learned over the years about Python’s real capabilities in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 What to Expect
&lt;/h2&gt;

&lt;p&gt;This series is practical. It’s grounded in real-world experience and designed with ❤️ by yours truly, the host of this series, &lt;a href="https://www.linkedin.com/in/chikeegonu/" rel="noopener noreferrer"&gt;Mr. Chike&lt;/a&gt;👨🏾‍💻 to show you how to build systems that are modular, maintainable, and scalable from day one.&lt;/p&gt;

&lt;p&gt;So enough talk.&lt;/p&gt;

&lt;p&gt;Let’s get to work. 💥 &lt;/p&gt;

&lt;h2&gt;
  
  
  🗂️ Project Structure Overview
&lt;/h2&gt;



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

base/                                  &lt;span class="c"&gt;# Feature module&lt;/span&gt;
├── __init__.py                        &lt;span class="c"&gt;# Python package initialization&lt;/span&gt;
├── router.py                          &lt;span class="c"&gt;# Defines HTTP API endpoints and maps them to controller functions&lt;/span&gt;
├── controller.py                      &lt;span class="c"&gt;# Handles request-response cycle; delegates business logic to services&lt;/span&gt;
├── service.py                         &lt;span class="c"&gt;# Core business logic for async I/O operations&lt;/span&gt;
├── model.py                           &lt;span class="c"&gt;# SQLAlchemy ORM models representing database tables&lt;/span&gt;
├── schema.py                          &lt;span class="c"&gt;# Pydantic models for input validation and output serialization&lt;/span&gt;
├── dependencies.py                    &lt;span class="c"&gt;# Module-specific DI components like authentication and DB sessions&lt;/span&gt;
├── tasks.py                           &lt;span class="c"&gt;# Core business logic for CPU-bound operations&lt;/span&gt;

├── movies/                            &lt;span class="c"&gt;# Movie feature module&lt;/span&gt;

├── tv_series/                         &lt;span class="c"&gt;# TV series feature module&lt;/span&gt;

├── static/                            &lt;span class="c"&gt;# (Optional) Static files (e.g., images, CSS)&lt;/span&gt;

├── templates/                         &lt;span class="c"&gt;# (Optional) Jinja2 or HTML templates for frontend rendering&lt;/span&gt;

├── docs/                              &lt;span class="c"&gt;# (Optional) API documentation, design specs, or OpenAPI enhancements&lt;/span&gt;

├── shared/                            &lt;span class="c"&gt;# Project-wide shared codebase&lt;/span&gt;
│   ├── __init__.py
│   ├── config/                        &lt;span class="c"&gt;# Environment configuration setup&lt;/span&gt;
│   │   ├── __init__.py
│   │   └── settings.py                &lt;span class="c"&gt;# Pydantic-based config management&lt;/span&gt;
│   ├── dependencies/                  &lt;span class="c"&gt;# Shared DI functions (e.g., auth, DB session)&lt;/span&gt;
│   ├── middleware/                    &lt;span class="c"&gt;# Global middlewares (e.g., logging, error handling)&lt;/span&gt;
│   ├── services/                      &lt;span class="c"&gt;# Reusable services&lt;/span&gt;
│   │   ├── __init__.py
│   │   ├── external_apis/             &lt;span class="c"&gt;# Third-party integrations (e.g., TMDB, IMDB)&lt;/span&gt;
│   │   └── internal_operations/       &lt;span class="c"&gt;# CPU-intensive logic, background tasks&lt;/span&gt;
│   └── utils/                         &lt;span class="c"&gt;# Generic helpers (e.g., slugify, formatters)&lt;/span&gt;

├── scripts/                           &lt;span class="c"&gt;# Developer or DevOps utilities&lt;/span&gt;
│   ├── __init__.py
│   └── sanity_check.py                &lt;span class="c"&gt;# A friendly reminder not to lose your mind while debugging&lt;/span&gt;

├── tests/                             &lt;span class="c"&gt;# # Unit, Integration, System, and End-to-End (E2E) tests for app modules&lt;/span&gt;
│   ├── __init__.py

├── .example.env                       &lt;span class="c"&gt;# Template for environment variables (e.g., DB_URL, API_KEY)&lt;/span&gt;
├── .coveragerc                        &lt;span class="c"&gt;# Code coverage settings&lt;/span&gt;
├── .gitignore                         &lt;span class="c"&gt;# Files and folders ignored by Git&lt;/span&gt;
├── main.py                            &lt;span class="c"&gt;# FastAPI application entrypoint&lt;/span&gt;
├── pytest.ini                         &lt;span class="c"&gt;# Pytest configuration&lt;/span&gt;
├── requirements.txt                   &lt;span class="c"&gt;# Python dependency list&lt;/span&gt;
├── JOURNAL.md                         &lt;span class="c"&gt;# Development log: issues faced, solutions, and resources&lt;/span&gt;
└── README.md                          &lt;span class="c"&gt;# Project overview, setup, and usage&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🏗️ Project Initialization
&lt;/h2&gt;

&lt;p&gt;We’ll start by setting up the project folder and running an initialization script to scaffold the directories and files we’ll use throughout the article.&lt;/p&gt;

&lt;p&gt;You can find the full &lt;a href="https://github.com/MrChike/media_app/blob/seriesA/setup.sh" rel="noopener noreferrer"&gt;setup.sh&lt;/a&gt; script in the GitHub repository.&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 the main project folder and initialize Git&lt;/span&gt;
&lt;span class="nb"&gt;mkdir &lt;/span&gt;media_app &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;media_app &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git init

&lt;span class="c"&gt;# Add and make the setup script executable&lt;/span&gt;
&lt;span class="nb"&gt;touch &lt;/span&gt;setup.sh &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;chmod&lt;/span&gt; +x setup.sh

&lt;span class="c"&gt;# Update 'setup.sh' with your GitHub repository link, then run the setup script to scaffold the project&lt;/span&gt;
./setup.sh

&lt;span class="c"&gt;# Activate your Python virtual environment (if applicable)&lt;/span&gt;
&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now update &lt;code&gt;main.py&lt;/code&gt; with the content from &lt;a href="https://github.com/MrChike/media_app/blob/project_setup_script/main.py" rel="noopener noreferrer"&gt;this file&lt;/a&gt;, then start the project by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uvicorn main:app &lt;span class="nt"&gt;--reload&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will launch the app with live reload enabled on port 8000. &lt;em&gt;(Feel free to change the port to whatever your majesty desires.)&lt;/em&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.amazonaws.com%2Fuploads%2Farticles%2Fkzz7ufyxgbdvb3rdmnwv.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.amazonaws.com%2Fuploads%2Farticles%2Fkzz7ufyxgbdvb3rdmnwv.png" alt="Up &amp;amp; Running" width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we create the module we want to work on from base&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;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; base movies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I know firsthand how frustrating it can be to read a technical article. it's almost like the developer assumes you're inside their head and completely understand all the complexities.&lt;/p&gt;

&lt;p&gt;That's exactly why I'm taking my time to explain things clearly and step by step.&lt;/p&gt;

&lt;p&gt;Now, let’s move on to the next phase...&lt;/p&gt;




&lt;h2&gt;
  
  
  🔄 Request Lifecycle
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;router&lt;/strong&gt; receives an HTTP request from the user and forwards it to a &lt;strong&gt;controller&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;controller&lt;/strong&gt; validates the request data often using &lt;strong&gt;schemas&lt;/strong&gt; for input validation and output serialization, then calls the appropriate &lt;strong&gt;service&lt;/strong&gt; or &lt;strong&gt;tasks&lt;/strong&gt; function. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;service&lt;/strong&gt; handles the core business logic for &lt;strong&gt;async I/O operations&lt;/strong&gt;, such as CRUD operations on the database (using &lt;code&gt;model.py&lt;/code&gt;) or interactions with external APIs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;When needed, the service also uses components from &lt;code&gt;dependencies.py&lt;/code&gt;, such as &lt;strong&gt;authentication&lt;/strong&gt; or &lt;strong&gt;database session injection&lt;/strong&gt;, to get the job done.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For &lt;strong&gt;CPU-bound or long-running operations&lt;/strong&gt;, the service delegates the work to &lt;code&gt;tasks.py&lt;/code&gt;. These tasks are executed asynchronously using &lt;strong&gt;Celery&lt;/strong&gt;, with a broker like &lt;strong&gt;Redis&lt;/strong&gt; or &lt;strong&gt;RabbitMQ&lt;/strong&gt;, to keep the user experience smooth. &lt;em&gt;(Covered in Part 2 of this series)&lt;/em&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;😒 No one loves waiting, so the heavy lifting is done in the background while the user gets a quick response and moves on with their day. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Once processing is complete, the &lt;strong&gt;service&lt;/strong&gt; returns the result to the &lt;strong&gt;controller&lt;/strong&gt;, which formats the response using &lt;strong&gt;schemas&lt;/strong&gt;, and sends it back through the &lt;strong&gt;router&lt;/strong&gt; to the client.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that we understand the overall process, let’s break down what it actually looks like in motion.&lt;/p&gt;

&lt;p&gt;When a user hits the movie endpoint, here’s what's going on in the background:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;App Entry&lt;/strong&gt; (main.py):&lt;br&gt;
The FastAPI app initializes and mounts the movie_router under /movies on &lt;a href="https://github.com/MrChike/media_app/blob/movies/main.py#L13" rel="noopener noreferrer"&gt;Line 13&lt;/a&gt;. This means all movie-related routes start with /movies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configuration Layer&lt;/strong&gt; (shared/config/settings.py):&lt;br&gt;
This layer manages the application's settings and environment variables using Pydantic for validation and dotenv for loading configuration from a .env file. The &lt;a href="https://github.com/MrChike/media_app/blob/movies/shared/config/settings.py#L7" rel="noopener noreferrer"&gt;AppSettings&lt;/a&gt; class defines various configuration fields such as database credentials and others.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Router Layer&lt;/strong&gt; (movies/router.py):&lt;br&gt;
The router defines specific HTTP routes and forwards incoming requests to the controller. For example, a POST request to /movies/omdb/ hits the router’s get_movie method on &lt;a href="https://github.com/MrChike/media_app/blob/movies/movies/router.py#L11" rel="noopener noreferrer"&gt;Line 11&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Controller Layer&lt;/strong&gt; (movies/controller.py):&lt;br&gt;
The controller acts as a middleman by receiving the validated request data, calls the service layer to handle business logic, and formats the response to send back to the client as seen from &lt;a href="https://github.com/MrChike/media_app/blob/movies/movies/controller.py#L10" rel="noopener noreferrer"&gt;Line 10&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Schema Layer&lt;/strong&gt; (movies/schemas.py):&lt;br&gt;
This layer defines the data structure and validation rules using Pydantic models. For incoming requests, MovieSchema ensures required and optional fields (like title, actors, and year) are properly validated. For responses, MovieResponseSchema extends &lt;a href="https://github.com/MrChike/media_app/blob/movies/movies/schema.py" rel="noopener noreferrer"&gt;MovieSchema&lt;/a&gt; to allow automatic population from ORM models, as seen from &lt;a href="https://github.com/MrChike/media_app/blob/movies/movies/controller.py#L10" rel="noopener noreferrer"&gt;Line 10&lt;/a&gt; of the controller.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Service Layer&lt;/strong&gt; (movies/service.py):&lt;br&gt;
This layer constructs the external API URL and delegates the task of fetching data to the external API service. It handles errors gracefully, logging issues for developers and returning user-friendly messages if something goes wrong as seen from &lt;a href="https://github.com/MrChike/media_app/blob/movies/movies/service.py#L19" rel="noopener noreferrer"&gt;Line 19&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;External API Call&lt;/strong&gt; (shared/services/external_apis/omdb_movies.py):&lt;br&gt;
The actual HTTP request to the OMDB API is made here using httpx. This function focuses on making reliable API calls and raising exceptions on errors, which the service layer catches as seen from &lt;a href="https://github.com/MrChike/media_app/blob/movies/shared/services/external_apis/omdb_movies.py#L6" rel="noopener noreferrer"&gt;Line 6&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once the response is received from the external service, it’s returned back through the chain:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;→ from fetch_movie_omdb to&lt;br&gt;
→ get_movie_details (service) to&lt;br&gt;
→ the controller, and finally&lt;br&gt;
→ back to the client via the router.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NB: &lt;strong&gt;Don't forget to register for your movie api key&lt;/strong&gt; @ &lt;a href="https://www.omdbapi.com/apikey.aspx" rel="noopener noreferrer"&gt;https://www.omdbapi.com/apikey.aspx&lt;/a&gt; and update you &lt;code&gt;.env&lt;/code&gt; file...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then run the following 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="c"&gt;# Refresh environment variables to reflect update&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .env

&lt;span class="c"&gt;# Start app with live reloading on specified port&lt;/span&gt;
uvicorn main:app &lt;span class="nt"&gt;--reload&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2F7b6m00nevkfvrmsia0d1.gif" 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.amazonaws.com%2Fuploads%2Farticles%2F7b6m00nevkfvrmsia0d1.gif" alt="schema" width="1920" height="1058"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This layered, modular design ensures each part has a clear responsibility, making the codebase easier to maintain, test, and scale.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Now speaking of testing…&lt;/strong&gt; &lt;em&gt;I just hope the length of this article isn’t unit-testing your patience.&lt;/em&gt;  🧪🤯&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Testing the Gears
&lt;/h2&gt;

&lt;p&gt;In this section, we’ll be blending three powerful tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;pytest&lt;/code&gt; to configure and run tests across the entire module,&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;unittest&lt;/code&gt; to drill down into individual units, and&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;coverage&lt;/code&gt; to generate reports on what’s been tested and what hasn’t.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This hybrid approach ensures both broad and deep testing of the system while keeping things modular, clear, and production-ready.&lt;/p&gt;

&lt;p&gt;We'll start by configuring &lt;a href="https://github.com/MrChike/media_app/blob/testing_setup/pytest.ini" rel="noopener noreferrer"&gt;pytest.ini&lt;/a&gt;  alongside coverage so it can automatically detect test files and report on which parts of the codebase are covered.&lt;/p&gt;

&lt;p&gt;Next, we’ll configure &lt;a href="https://github.com/MrChike/media_app/blob/testing_setup/.coveragerc" rel="noopener noreferrer"&gt;.coveragerc&lt;/a&gt; to omit files that don’t need to be tested like &lt;em&gt;(e.g, __init&lt;/em&gt;&lt;em&gt;.py, model.py)&lt;/em&gt; and other boilerplate or non-critical modules, so the reports remain clean, focused and provide meaningful insights.&lt;/p&gt;

&lt;p&gt;Now that we’ve done that, we can test if the configuration is properly set up by running the 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="nv"&gt;$ &lt;/span&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;env&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; mrchike@practice:~/code/contributions/education/media_app&lt;span class="nv"&gt;$ &lt;/span&gt;pytest
&lt;span class="o"&gt;====================================================&lt;/span&gt; &lt;span class="nb"&gt;test &lt;/span&gt;session starts &lt;span class="o"&gt;====================================================&lt;/span&gt;
platform linux &lt;span class="nt"&gt;--&lt;/span&gt; Python 3.10.12, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/mrchike/code/contributions/education/media_app
configfile: pytest.ini
testpaths: tests/
plugins: anyio-4.9.0, cov-6.1.1
collected 0 items                                                                                                           
/home/mrchike/code/contributions/education/media_app/env/lib/python3.10/site-packages/coverage/control.py:915: CoverageWarning: No data was collected. &lt;span class="o"&gt;(&lt;/span&gt;no-data-collected&lt;span class="o"&gt;)&lt;/span&gt;
  self._warn&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"No data was collected."&lt;/span&gt;, &lt;span class="nv"&gt;slug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"no-data-collected"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;======================================================&lt;/span&gt; tests coverage &lt;span class="o"&gt;=======================================================&lt;/span&gt;
_____________________________________ coverage: platform linux, python 3.10.12-final-0 ______________________________________

Name                   Stmts   Miss  Cover   Missing
&lt;span class="nt"&gt;----------------------------------------------------&lt;/span&gt;
movies/controller.py      10     10     0%   1-13
movies/service.py         19     19     0%   1-32
movies/tasks.py            0      0   100%
&lt;span class="nt"&gt;----------------------------------------------------&lt;/span&gt;
TOTAL                     29     29     0%
&lt;span class="o"&gt;===================================================&lt;/span&gt; no tests ran &lt;span class="k"&gt;in &lt;/span&gt;0.16s &lt;span class="o"&gt;===================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And just like that we have this beautiful display of Missing tests you've not attended to leading us to the next step ...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unit testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now that we know which files and lines of code require testing based on the coverage report, we will proceed with writing tests for &lt;a href="https://github.com/MrChike/media_app/blob/unit_test/tests/movies/test_controller.py" rel="noopener noreferrer"&gt;controller.py&lt;/a&gt; and &lt;a href="https://github.com/MrChike/media_app/blob/seriesA/tests/movies/test_service.py" rel="noopener noreferrer"&gt;service.py&lt;/a&gt; in the corresponding &lt;code&gt;movies&lt;/code&gt; module under the &lt;code&gt;tests&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Run the command once more:&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;$ &lt;/span&gt;pytest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;env&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; mrchike@practice:~/code/contributions/education/media_app&lt;span class="nv"&gt;$ &lt;/span&gt;pytest
&lt;span class="o"&gt;================================&lt;/span&gt; &lt;span class="nb"&gt;test &lt;/span&gt;session starts &lt;span class="o"&gt;=================================&lt;/span&gt;
platform linux &lt;span class="nt"&gt;--&lt;/span&gt; Python 3.10.12, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/mrchike/code/contributions/education/media_app
configfile: pytest.ini
testpaths: tests/
plugins: anyio-4.9.0, cov-6.1.1
collected 2 items                                                                    

tests/movies/test_controller.py ..                                             &lt;span class="o"&gt;[&lt;/span&gt;100%]

&lt;span class="o"&gt;===================================&lt;/span&gt; tests coverage &lt;span class="o"&gt;===================================&lt;/span&gt;
__________________ coverage: platform linux, python 3.10.12-final-0 __________________

Name                   Stmts   Miss  Cover   Missing
&lt;span class="nt"&gt;----------------------------------------------------&lt;/span&gt;
movies/controller.py      10      0   100%
movies/service.py         19     10    47%   20-32
movies/tasks.py            0      0   100%
&lt;span class="nt"&gt;----------------------------------------------------&lt;/span&gt;
TOTAL                     29     10    66%
&lt;span class="o"&gt;=================================&lt;/span&gt; 2 passed &lt;span class="k"&gt;in &lt;/span&gt;2.35s &lt;span class="o"&gt;==================================&lt;/span&gt;


&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;env&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; mrchike@practice:~/code/contributions/education/media_app&lt;span class="nv"&gt;$ &lt;/span&gt;pytest
&lt;span class="o"&gt;=========================================================&lt;/span&gt; &lt;span class="nb"&gt;test &lt;/span&gt;session starts &lt;span class="o"&gt;==========================================================&lt;/span&gt;
platform linux &lt;span class="nt"&gt;--&lt;/span&gt; Python 3.10.12, pytest-8.3.5, pluggy-1.6.0
rootdir: /home/mrchike/code/contributions/education/media_app
configfile: pytest.ini
testpaths: tests/
plugins: anyio-4.9.0, cov-6.1.1
collected 4 items                                                                                                                      

tests/movies/test_controller.py ..                                                                                               &lt;span class="o"&gt;[&lt;/span&gt; 50%]
tests/movies/test_service.py ..                                                                                                  &lt;span class="o"&gt;[&lt;/span&gt;100%]

&lt;span class="o"&gt;============================================================&lt;/span&gt; tests coverage &lt;span class="o"&gt;============================================================&lt;/span&gt;
___________________________________________ coverage: platform linux, python 3.10.12-final-0 ___________________________________________

Name                   Stmts   Miss  Cover   Missing
&lt;span class="nt"&gt;----------------------------------------------------&lt;/span&gt;
movies/controller.py      10      0   100%
movies/service.py         19      0   100%   
movies/tasks.py            0      0   100%
&lt;span class="nt"&gt;----------------------------------------------------&lt;/span&gt;
TOTAL                     29      0   100%
&lt;span class="o"&gt;==========================================================&lt;/span&gt; 4 passed &lt;span class="k"&gt;in &lt;/span&gt;2.42s &lt;span class="o"&gt;===========================================================&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🏁 Conclusion
&lt;/h2&gt;

&lt;p&gt;In this first part of the series, we've laid the groundwork for building a scalable, production-ready FastAPI application. We covered essential concepts like project structure, modularity, and the flow of requests through various layers of the app. Most importantly, we set up testing strategies to ensure our code is robust and maintainable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Recap:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project Structure:&lt;/strong&gt; We’ve created a clean, scalable folder structure that’s ready for real-world growth.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request Flow:&lt;/strong&gt; We broke down how requests travel through the router, controller, and service layers, ensuring clear responsibility separation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing:&lt;/strong&gt; We integrated &lt;strong&gt;pytest&lt;/strong&gt;, &lt;strong&gt;unittest&lt;/strong&gt;, and &lt;strong&gt;coverage&lt;/strong&gt;, and wrote tests to make sure the code performs as expected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With this solid foundation, we’re well-equipped to scale up the app and handle more advanced &lt;a href="https://github.com/MrChike/media_app/tree/seriesA?tab=readme-ov-file#upcoming-features" rel="noopener noreferrer"&gt;features&lt;/a&gt; in Part 2, such as background tasks for CPU-bound operations. So, stay tuned for that!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Enjoyed this article?&lt;/strong&gt; Connect with me on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/chikeegonu/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🐙 &lt;a href="https://github.com/MrChike" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your support means a lot, if you’d like to buy me a coffee ☕️ to keep me fueled, feel free to check out &lt;a href="https://buymeacoffee.com/mrchike" rel="noopener noreferrer"&gt;this link&lt;/a&gt;. Your generosity would go a long way in helping me continue to create content like this.&lt;/p&gt;

&lt;p&gt;Until next time, happy coding! 👨🏾‍💻🚀&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Previously Written Articles:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;How to Learn Effectively &amp;amp; Efficiently as a Professional in any Field&lt;/em&gt; 🧠⏱️🎯 &lt;strong&gt;[&lt;a href="https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d"&gt;Read here&lt;/a&gt;]&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Build, Innovate &amp;amp; Collaborate: Setting Up TensorFlow for Open-Source Contribution!&lt;/em&gt; 🚀✨ &lt;strong&gt;[&lt;a href="https://dev.to/mrchike/build-innovate-collaborate-setting-up-tensorflow-for-open-source-contribution-2ce6"&gt;Read here&lt;/a&gt;]&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Building a Secure, Scalable Learning Platform with RBAC Features&lt;/em&gt; 🎓🔒📚 &lt;strong&gt;[&lt;a href="https://dev.to/mrchike/building-a-secure-scalable-learning-platform-with-rbac-features-4g0m"&gt;Read here&lt;/a&gt;]&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Setting Up MKDocs for Your Django Project: A Quick Guide!&lt;/em&gt; &lt;strong&gt;[&lt;a href="https://dev.to/mrchike/setting-up-mkdocs-for-your-django-project-a-quick-guide-4jlh"&gt;Read here&lt;/a&gt;]&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;How to Deploy React Portfolio | Project with GitHub Pages as of 2024&lt;/em&gt; &lt;strong&gt;[&lt;a href="https://dev.to/mrchike/how-to-deploy-react-portfolioproject-with-github-pages-as-2024-4a69"&gt;Read here&lt;/a&gt;]&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&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/MrChike/media_app/tree/seriesA" rel="noopener noreferrer"&gt;https://github.com/MrChike/media_app/tree/seriesA&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.omdbapi.com/" rel="noopener noreferrer"&gt;https://www.omdbapi.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ezgif.com/" rel="noopener noreferrer"&gt;https://ezgif.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>discuss</category>
      <category>fastapi</category>
      <category>python</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Mastering the Art of Learning: A Professional’s Guide</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Sun, 20 Apr 2025 14:07:26 +0000</pubDate>
      <link>https://dev.to/mrchike/-1mpa</link>
      <guid>https://dev.to/mrchike/-1mpa</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d" class="crayons-story__hidden-navigation-link"&gt;🧠 Master the Art of Learning Efficiently (A Memo for Lifelong Learners). ⏱️🎯&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mrchike" class="crayons-avatar  crayons-avatar--l  "&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2147140%2F6a3e756f-9c9e-4a62-89c7-c7c04634a9e7.jpg" alt="mrchike profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mrchike" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Mr Chike
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Mr Chike
                
              
              &lt;div id="story-author-preview-content-2415994" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mrchike" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2147140%2F6a3e756f-9c9e-4a62-89c7-c7c04634a9e7.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Mr Chike&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 18 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d" id="article-link-2415994"&gt;
          🧠 Master the Art of Learning Efficiently (A Memo for Lifelong Learners). ⏱️🎯
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/learning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;learning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/agile"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;agile&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              2&lt;span class="hidden s:inline"&gt; comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>productivity</category>
      <category>career</category>
      <category>learning</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>🧠 Master the Art of Learning Efficiently (A Memo for Lifelong Learners). ⏱️🎯</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Fri, 18 Apr 2025 12:07:11 +0000</pubDate>
      <link>https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d</link>
      <guid>https://dev.to/mrchike/how-to-learn-effectively-efficiently-as-a-professional-in-any-field-4l7d</guid>
      <description>&lt;p&gt;This is one topic I’ve been researching and experimenting with for the past five years, ever since I became a software engineer. Although i’m someone who loves to take my time to learn and understand deeply. But unfortunately, my field has taught me some harsh truths I had to learn the hard way through trial and error which almost made me loose it.&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.amazonaws.com%2Fuploads%2Farticles%2Fb3knya91321mazgo47b7.gif" 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.amazonaws.com%2Fuploads%2Farticles%2Fb3knya91321mazgo47b7.gif" alt="Loosing IT" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Business is all about making profit, and management wants solutions as soon as &lt;strong&gt;yesterday&lt;/strong&gt; and  they will micromanage and frustrate the soul right out your body if you don’t deliver.&lt;/li&gt;
&lt;li&gt;Information and technology evolves at a rapid pace, and your ability to grasp new concepts quickly and execute ASAP to make an impact is a critical skill if you ever plan to survive in a highly competitive industry.&lt;/li&gt;
&lt;li&gt;The way you were taught to learn in school just doesn’t cut it in this fast-paced, cutthroat and highly competitive job market you’ve found yourself in.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I’ll be diving into the types of learning and techniques that will help you learn effectively and efficiently. First, let’s talk about the learning process taught in schools and why they’re in the wrong order.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traditional Learning&lt;/li&gt;
&lt;li&gt;Learning by Doing&lt;/li&gt;
&lt;li&gt;Learning by Priority&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🏫🗂️🕰️ &lt;strong&gt;Traditional Learning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the classic "sit in a classroom, follow a Course Outline | Syllabus or Roadmap for 4-6 years" situation. Hopefully, it’s not 10 years in your country! While this approach works well for learning core concepts and fundamentals deeply, it’s pretty ineffective in the real world. Why? Because your brain is designed to &lt;strong&gt;filter out&lt;/strong&gt; what’s not important, which means you’re definitely going to forget everything you learned in Year 1 once you hit Year 2. Lol, and let’s not even talk about what happens by your final year. Let’s face it: your brain has more pressing things to focus on, like &lt;strong&gt;BILLS&lt;/strong&gt; 😭 and life issues.&lt;/p&gt;

&lt;p&gt;👷‍♀️🧪💥 &lt;strong&gt;Learning by Doing&lt;/strong&gt;&lt;br&gt;
Yipee! You’ve just graduated with your certificate, feeling like you can conquer every obstacle in your path until life hits you with the &lt;strong&gt;Sh🔥ryuken!&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Recruiters asking for 7 years of experience for an entry-level role 😭😭&lt;/li&gt;
&lt;li&gt;Endless applications with a whole lot of &lt;strong&gt;“Unfortunatelies”&lt;/strong&gt; (Awwwn! You thought one or two applications would do the trick? Psyche! 🤪).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But finally, after what feels like forever, you land a job (Hopefully your boss ain’t the Wicked Witch of Beverly Hill). Now the real learning begins, the good ol’ &lt;strong&gt;learning by doing&lt;/strong&gt;, aka &lt;strong&gt;on-the-job learning&lt;/strong&gt;. This is where someone more experienced steps in to guide you. They point out your mistakes, you take notes, and you gradually start to level up.&lt;/p&gt;

&lt;p&gt;Which brings us to the next learning process…&lt;/p&gt;

&lt;p&gt;🚨🥵🎯 &lt;strong&gt;Learning by Priority&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the part where it hits you: Uhhhm! I really don’t know as much as I think I did. So, you reflect on the notes you’ve taken, do some research, and start filling in the gaps. &lt;br&gt;
After doing this over and over again, somewhere between 1 to 3 years in, you suddenly become the go-to guy or gal for the job.&lt;/p&gt;

&lt;p&gt;🧠💡 But actually… &lt;strong&gt;&lt;em&gt;the right order of learning looks a little different.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We always think it starts with traditional learning, but in reality, it goes more like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning by Doing&lt;/strong&gt; – You dive in headfirst, make mistakes, and learn on the fly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning by Priority&lt;/strong&gt; – You realize what you &lt;em&gt;don’t&lt;/em&gt; know and start bridging knowledge gaps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traditional Learning&lt;/strong&gt; – Now you take the time to go deeper and truly understand the why behind what you’ve been doing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So just to give you an example to solidify what I’m saying…&lt;/p&gt;

&lt;p&gt;Let’s say you are studying for an exam and you have 3 hours of free time each day. Here’s how you should apply this learning order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learning by Doing – 1hr:30mins:&lt;/strong&gt; You would start with practice questions, simulate exam conditions, and grade yourself. This reveals the gaps in your knowledge.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Learning by Priority – 1hr:&lt;/strong&gt; Then, you would go back to your study materials and read specifically on the topics where you struggled.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Traditional Learning – 30mins:&lt;/strong&gt; Finally, you would take your time going through the material chapter by chapter, to gain deeper understanding.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🎯 The fun part is? This system scales to any goal you want to achieve, not just exams.&lt;/p&gt;

&lt;p&gt;For example, imagine you just stepped into your first leadership role &lt;em&gt;(like ever, like ever ever)&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;You jump in and figure things out as you go (&lt;strong&gt;Learning by Doing&lt;/strong&gt;). Over time, you spot your weaknesses and take note. Then, you look for books or resources that address those specific challenges (&lt;strong&gt;Learning by Priority&lt;/strong&gt;) and just as important as any, you carve out time (30 minutes a day) to read those leadership books chapter by chapter for in-depth understanding and long-term growth (&lt;strong&gt;Traditional Learning&lt;/strong&gt;). 😉&lt;/p&gt;

&lt;p&gt;Now, what this does is it frees you from the mindset of &lt;em&gt;"&lt;/em&gt;&lt;em&gt;I have to know it all or be perfect before I can make an impact&lt;/em&gt;&lt;em&gt;"&lt;/em&gt; which in itself, is a trap.&lt;/p&gt;

&lt;p&gt;You know… like the classic “&lt;strong&gt;&lt;em&gt;I need to wait 365 days to make a decision because it’s the end of the year and I’m all hyped up&lt;/em&gt;&lt;/strong&gt;” move. → New Year, New Me 🤦‍♂️&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🎉&lt;/strong&gt; Drum roll, please...&lt;br&gt;
&lt;strong&gt;🥁&lt;/strong&gt; And the &lt;strong&gt;Best Procrastinator Award goes to... Y🤡U!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Sooooo… on to the next section: &lt;strong&gt;studying techniques&lt;/strong&gt;, which I’ll be listing in this order: &lt;/p&gt;

&lt;p&gt;Todo List → Eisenhower Matrix → Paretho Principle → Eat That Frog → Pomodoro → Delibrate Practice → Feyman Technique → Spaced Repetition → The Feedback Loop&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Todo List&lt;/strong&gt; - All tasks must relocate from your head to paper (H1-B Style) as you can’t always trust your brain to remember everything&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eisenhower Matrix&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Urgent &amp;amp; Important = Prioritize&lt;/li&gt;
&lt;li&gt;Not Urgent but important = Schedule&lt;/li&gt;
&lt;li&gt;Urgent but not important = Delegate&lt;/li&gt;
&lt;li&gt;Not urgent or important = Eliminate&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Pareto Principle -&lt;/strong&gt; The &lt;strong&gt;80/20 Rule&lt;/strong&gt;! - 80% of results come from 20% of the efforts.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Eat That Frog –&lt;/strong&gt; Tackle the most important (and often dreadful) task first, while your energy is at its peak.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Pomodoro Technique&lt;/strong&gt; – Work in focused sessions while eliminating distractions, and take breaks when you're done to cool off.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Deliberate Practice&lt;/strong&gt; – “&lt;em&gt;I fear not the man who has practiced 10,000 kicks once, but I fear the man who has practiced one kick 10,000 times.&lt;/em&gt;” — Bruce Lee&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Feyman Technique -&lt;/strong&gt; if you can’t teach it to 5-year-old, then you probably don't understand it as well as you think you do.&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Spaced Repetition -&lt;/strong&gt; The more you try to recall something from memory at spaced intervals, the more it sticks for good. (&lt;a href="https://ankiweb.net/about" rel="noopener noreferrer"&gt;Anki&lt;/a&gt;, &lt;a href="https://www.notion.com/" rel="noopener noreferrer"&gt;Notion&lt;/a&gt;, and others are great tools for this!)&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;The Feedback Loop&lt;/strong&gt; – This isn’t really a study technique, but more of a system of testing what works and what doesn’t, so you keep twerking, sorry tweaking things until you figure out what works best for you.
Although there is one technique I could have added to the list, but I’ve been able to do without it and still make an impact. That would be &lt;strong&gt;Mind Mapping&lt;/strong&gt;. If you’re a die-hard fan of this technique, feel free to add it to the list. The more, the merrier!&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Now, to bring it to life with an example by putting it all together… Let’s say you have an exam in the next 3 months and have only 3 hours to spare daily. &lt;strong&gt;This is how you should go about it&lt;/strong&gt;. But First! I’ll leave you with a quote from &lt;em&gt;The 7 Habits of Highly Effective People&lt;/em&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"&lt;/strong&gt;&lt;em&gt;If I had seven days to cut down a forest, I’d spend most of it sharpening my tools.&lt;/em&gt;&lt;strong&gt;"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Simply put, &lt;strong&gt;the time spent preparing isn’t time wasted, but time well invested.&lt;/strong&gt; #preach!&lt;/p&gt;

&lt;p&gt;🧠 &lt;strong&gt;Study Game Plan&lt;/strong&gt; (3 Hours Daily for 3 Months)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Preparation&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Research &amp;amp; gather study materials that best fit your learning style (books, audio, video… whatever works for you).&lt;/li&gt;
&lt;li&gt;List all study materials on a &lt;strong&gt;to-do list&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Filter out what’s not needed and prioritize what’s essential using the &lt;strong&gt;Eisenhower Matrix&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Learning by Doing – 1hr 30mins&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Practice with past questions or a study bank under exam time constraints.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Grade yourself.&lt;/p&gt;

&lt;p&gt;After a few sessions, you’ll notice certain topics keep popping up, this is called &lt;strong&gt;pattern recognition&lt;/strong&gt;. It reveals the topics that are most likely to appear in the exam. Yep!, that’s the &lt;strong&gt;Pareto Principle&lt;/strong&gt; in action.&lt;/p&gt;

&lt;p&gt;Jot down these recurring topics, these are your knowledge gaps and your research guide.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Learning by Priority – 1hr&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Now that you’ve identified your high-priority topics, start with the hardest one &lt;strong&gt;when your energy is at its peak&lt;/strong&gt; (well-rested, well-fed &amp;amp; hydrated) → &lt;strong&gt;Eat That Frog&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use focused study-play sessions with zero distractions → &lt;strong&gt;Pomodoro Technique&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;30 mins focus / 5 mins break&lt;/li&gt;
&lt;li&gt;OR 1 hr focus / 10 mins break&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt; &lt;br&gt;
&lt;strong&gt;NB:&lt;/strong&gt; Your break can be anything you genuinely enjoy.&lt;/p&gt;

&lt;p&gt;For me? Some mad afrobeats🔥music, watching comedy skits on TikTok, or a quick match in Call of Duty Mobile. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PS:&lt;/strong&gt;  &lt;em&gt;I’m the best sniper alive, you won’t even see it coming. you just gonna black out&lt;/em&gt; 🎯💀&lt;br&gt;&lt;br&gt;
So, figure out what works for &lt;em&gt;you&lt;/em&gt;, and stick to it. &lt;br&gt;
 &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Be intentional with what you’re studying, focus on what you want to understand, not just skim. → &lt;strong&gt;Deliberate Practice&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pro Tip&lt;/strong&gt;: Spar with 🥷 GPT Sensei. Ask questions. Explain answers. Challenge your understanding. You’ll retain more that way.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Think you finally understand Quantum Computing? Cool. Now… explain it to a 5-year-old &lt;em&gt;without&lt;/em&gt; sounding like an evil Harvard scientist. → &lt;strong&gt;Feynman Technique&lt;/strong&gt;&lt;br&gt;
Yup! you’re about to find out you might not know it as well as you thought. &lt;strong&gt;&lt;em&gt;Simplifying complex concepts enforces deep understanding&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once you’ve understood the concept, create a Q&amp;amp;A model using tools like &lt;a href="https://www.notion.com/" rel="noopener noreferrer"&gt;Notion&lt;/a&gt; or &lt;a href="https://ankiweb.net/about" rel="noopener noreferrer"&gt;Anki&lt;/a&gt; and start testing yourself over time → &lt;strong&gt;Spaced Repetition&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&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.amazonaws.com%2Fuploads%2Farticles%2Fex6svcool0bej6k15a8p.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.amazonaws.com%2Fuploads%2Farticles%2Fex6svcool0bej6k15a8p.png" alt="Spaced Repetition Tools" width="800" height="233"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Traditional Learning -&lt;/strong&gt; 30mins&lt;/p&gt;

&lt;p&gt;Now this is where you take your time and walk through each &lt;strong&gt;chapter&lt;/strong&gt; | &lt;strong&gt;section&lt;/strong&gt; | &lt;strong&gt;module&lt;/strong&gt; to gain a deeper understanding of the material. No rush!&lt;/p&gt;

&lt;p&gt;So why do you need this?&lt;/p&gt;

&lt;p&gt;Well… sometimes, the examiner doesn’t pull questions from the &lt;em&gt;past,&lt;/em&gt; they pull 'em from the &lt;em&gt;future! -&lt;/em&gt; &lt;strong&gt;Uhhh! Ahhh!&lt;/strong&gt; 😱&lt;/p&gt;

&lt;p&gt;That’s when you realize surface-level knowledge won’t cut it. You need true, in-depth understanding to solve complex problems.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Closing Remark:&lt;/strong&gt; Traditional learning had us believing &lt;strong&gt;&lt;em&gt;we need to know it all before we do anything significant&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Real life taught me otherwise:&lt;/p&gt;

&lt;p&gt;→ &lt;strong&gt;Learn by doing&lt;/strong&gt; - Get those squeaky-clean hands dirty.&lt;/p&gt;

&lt;p&gt;→ &lt;strong&gt;Always focus on current priority&lt;/strong&gt; - Of 99 things you can be doing, there's only 1 that needs laser focus&lt;/p&gt;

&lt;p&gt;→ &lt;strong&gt;Deepen your Knowledge&lt;/strong&gt; - Mastery demands depth, and it takes time (that's why traditional learning is best done along side while executing current priority). But depth lets you spot hidden patterns, connect the dots, and give life to new ideas.&lt;/p&gt;

&lt;p&gt;Now, combine that mindset with tools like &lt;strong&gt;Pomodoro&lt;/strong&gt;, &lt;strong&gt;Eisenhower Matrix&lt;/strong&gt;, &lt;strong&gt;Spaced Repetition&lt;/strong&gt;, and others as i've listed...&lt;/p&gt;

&lt;p&gt;You’re not just learning, &lt;strong&gt;you’re evolving.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you found this article helpful, feel free to connect with me → &lt;a href="https://www.linkedin.com/in/chikeegonu/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Until we meet again &lt;strong&gt;Tudulus Wishes! 🤪&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>learning</category>
      <category>productivity</category>
      <category>agile</category>
    </item>
    <item>
      <title>Building a Secure, Scalable Learning Platform with RBAC Features 🎓🔒📚</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Tue, 19 Nov 2024 11:15:02 +0000</pubDate>
      <link>https://dev.to/mrchike/building-a-secure-scalable-learning-platform-with-rbac-features-4g0m</link>
      <guid>https://dev.to/mrchike/building-a-secure-scalable-learning-platform-with-rbac-features-4g0m</guid>
      <description>&lt;p&gt;Before we go all technical and start with 1's and 0's my dear geek!.&lt;br&gt;
Here's a sneak peak of what we are going to be working with.&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.amazonaws.com%2Fuploads%2Farticles%2F2iaapmkaud7sntvd2yjg.gif" 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.amazonaws.com%2Fuploads%2Farticles%2F2iaapmkaud7sntvd2yjg.gif" alt="Project Gif" width="760" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yup!... It's an LMS system, like one of those you don't really see much on the internet as it takes a rich and full approach from course registration to payment with the original &lt;a href="https://www.youtube.com/watch?v=Big_aFLmekI" rel="noopener noreferrer"&gt;course&lt;/a&gt; on Youtube.&lt;/p&gt;

&lt;p&gt;This is where I step in and crank it up a notch like every hired mercenary in tech. So what inspired me to do this? After a thorough search on the internet i realised one thing. You couldn't see this application hosted anywhere and me spidey senses started tingling. I knew this would be a good challenge to make available to the public. So i grabbed my laptop, coffee and the rest was history...&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.amazonaws.com%2Fuploads%2Farticles%2Frsm8mlueck6wn3qn3gqh.gif" 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.amazonaws.com%2Fuploads%2Farticles%2Frsm8mlueck6wn3qn3gqh.gif" alt="Coffee" width="498" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what would you be learning here, how to set up &amp;amp; contribute to this ongoing project. I will be working you through the important parts of the application for easy set-up. So now let's get technical...&lt;/p&gt;

&lt;p&gt;Below are the steps we will be taking to get you up and running.&lt;br&gt;
🥷 Fork &amp;amp; clone &lt;a href="https://github.com/MrChike/LMS" rel="noopener noreferrer"&gt;LMS&lt;/a&gt; repo&lt;br&gt;
⚙️ Setup &amp;amp; Migrate Prisma Schema&lt;br&gt;
🥷 Fork &amp;amp; clone &lt;a href="https://github.com/MrChike/LMS-API" rel="noopener noreferrer"&gt;LMS API&lt;/a&gt; repo&lt;br&gt;
📚 Start creating courses&lt;/p&gt;
&lt;h3&gt;
  
  
  🥷 Fork &amp;amp; clone &lt;a href="https://github.com/MrChike/LMS" rel="noopener noreferrer"&gt;LMS&lt;/a&gt; repo.
&lt;/h3&gt;

&lt;p&gt;Head to the lms repo and do the needful. You would want to also click on watch as more features are being introduced.&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.amazonaws.com%2Fuploads%2Farticles%2Fxtgxohcmafew57n2sdoy.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.amazonaws.com%2Fuploads%2Farticles%2Fxtgxohcmafew57n2sdoy.png" alt="LMS Repo" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy link and clone the repo to your local.&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;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;lms_project &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;lms_project
&lt;span class="nv"&gt;$ &lt;/span&gt;git clone git@github.com:MrChike/LMS.git
Cloning into &lt;span class="s1"&gt;'LMS'&lt;/span&gt;...
remote: Enumerating objects: 1530, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;1185/1185&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;602/602&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Total 1530 &lt;span class="o"&gt;(&lt;/span&gt;delta 546&lt;span class="o"&gt;)&lt;/span&gt;, reused 1025 &lt;span class="o"&gt;(&lt;/span&gt;delta 482&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 345 &lt;span class="o"&gt;(&lt;/span&gt;from 1&lt;span class="o"&gt;)&lt;/span&gt;
Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;1530/1530&lt;span class="o"&gt;)&lt;/span&gt;, 53.13 MiB | 6.74 MiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;588/588&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;git clone https://github.com/MrChike/LMS-API
Cloning into &lt;span class="s1"&gt;'LMS-API'&lt;/span&gt;...
remote: Enumerating objects: 131, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Counting objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;131/131&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Compressing objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;85/85&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
remote: Total 131 &lt;span class="o"&gt;(&lt;/span&gt;delta 75&lt;span class="o"&gt;)&lt;/span&gt;, reused 100 &lt;span class="o"&gt;(&lt;/span&gt;delta 44&lt;span class="o"&gt;)&lt;/span&gt;, pack-reused 0 &lt;span class="o"&gt;(&lt;/span&gt;from 0&lt;span class="o"&gt;)&lt;/span&gt;
Receiving objects: 100% &lt;span class="o"&gt;(&lt;/span&gt;131/131&lt;span class="o"&gt;)&lt;/span&gt;, 31.87 KiB | 238.00 KiB/s, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Resolving deltas: 100% &lt;span class="o"&gt;(&lt;/span&gt;75/75&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your frontend root folder should look like this and if you notice we will be starting with the &lt;code&gt;.env.sample&lt;/code&gt; file as this is important to run the application&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.amazonaws.com%2Fuploads%2Farticles%2F8k622marf4b7fz8gsb3p.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.amazonaws.com%2Fuploads%2Farticles%2F8k622marf4b7fz8gsb3p.png" alt="VSCode" width="800" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rename the &lt;code&gt;.env.sample&lt;/code&gt; file to &lt;code&gt;.env&lt;/code&gt; and populate with the necessary credentials. &lt;strong&gt;NB&lt;/strong&gt;: The link to the external services to populate below are located at the end of this article.&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;NEXT_PUBLIC_APP_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:3000
&lt;span class="nv"&gt;NEXT_PUBLIC_TEACHER_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;NEXT_PUBLIC_BACKEND_API_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://127.0.0.1:8000

&lt;span class="c"&gt;# See the documentation for all the connection string options: https://pris.ly/d/connection-strings&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;protocol://username:password@host:port/database
&lt;span class="nv"&gt;UPLOADTHING_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;UPLOADTHING_APP_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;MUX_TOKEN_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;MUX_TOKEN_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;STRIPE_WEBHOOK_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;STRIPE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ⚙️ Setup &amp;amp; Migrate Prisma Schema
&lt;/h3&gt;

&lt;p&gt;After you're done. run the following prisma 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="nv"&gt;$ &lt;/span&gt;npx prisma generate
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma

✔ Generated Prisma Client &lt;span class="o"&gt;(&lt;/span&gt;v5.3.0&lt;span class="o"&gt;)&lt;/span&gt; to ./node_modules/@prisma/client &lt;span class="k"&gt;in &lt;/span&gt;519ms

Start using Prisma Client &lt;span class="k"&gt;in &lt;/span&gt;Node.js &lt;span class="o"&gt;(&lt;/span&gt;See: https://pris.ly/d/client&lt;span class="o"&gt;)&lt;/span&gt;

import &lt;span class="o"&gt;{&lt;/span&gt; PrismaClient &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'@prisma/client'&lt;/span&gt;
const prisma &lt;span class="o"&gt;=&lt;/span&gt; new PrismaClient&lt;span class="o"&gt;()&lt;/span&gt;

or start using Prisma Client at the edge &lt;span class="o"&gt;(&lt;/span&gt;See: https://pris.ly/d/accelerate&lt;span class="o"&gt;)&lt;/span&gt;

import &lt;span class="o"&gt;{&lt;/span&gt; PrismaClient &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'@prisma/client/edge'&lt;/span&gt;


See other ways of importing Prisma Client: http://pris.ly/d/importing-client

&lt;span class="nv"&gt;$ &lt;/span&gt;npx prisma db push
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource &lt;span class="s2"&gt;"db"&lt;/span&gt;: PostgreSQL database &lt;span class="s2"&gt;"lms"&lt;/span&gt;, schema &lt;span class="s2"&gt;"public"&lt;/span&gt; at &lt;span class="s2"&gt;"192.168.86.133:5432"&lt;/span&gt;

🚀  Your database is now &lt;span class="k"&gt;in &lt;/span&gt;&lt;span class="nb"&gt;sync &lt;/span&gt;with your Prisma schema. Done &lt;span class="k"&gt;in &lt;/span&gt;449ms

✔ Generated Prisma Client &lt;span class="o"&gt;(&lt;/span&gt;v5.3.0&lt;span class="o"&gt;)&lt;/span&gt; to ./node_modules/@prisma/client &lt;span class="k"&gt;in &lt;/span&gt;574ms

┌─────────────────────────────────────────────────────────┐
│  Update available 5.3.0 -&amp;gt; 5.22.0                       │
│  Run the following to update                            │
│    npm i &lt;span class="nt"&gt;--save-dev&lt;/span&gt; prisma@latest                       │
│    npm i @prisma/client@latest                          │
└─────────────────────────────────────────────────────────┘
&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="c"&gt;#########⠂⠂⠂⠂⠂⠂⠂⠂⠂) ⠧ reify:@img/sharp-darwin-arm64: timing reifyNode:node_m&lt;/span&gt;

&lt;span class="nv"&gt;$ &lt;/span&gt;node scripts/seed.ts &lt;span class="c"&gt;#create course categories&lt;/span&gt;
Success
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I prefer to see what i'm working with so i'm using pgadmin to monitor my postgres DB. You can use your prefered tool.&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fkiw009bronzycu2y67h8.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.amazonaws.com%2Fuploads%2Farticles%2Fkiw009bronzycu2y67h8.png" alt="DB" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Or you can run &lt;code&gt;npx prisma studio&lt;/code&gt; command to monitor your database table.&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;$ &lt;/span&gt;npx prisma studio
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Prisma Studio is up on http://localhost:5555
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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.amazonaws.com%2Fuploads%2Farticles%2F69m5caukjhpfr4h10g4o.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.amazonaws.com%2Fuploads%2Farticles%2F69m5caukjhpfr4h10g4o.png" alt="Prisma Studio" width="800" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we have our prisma schema all set up. Let's set up the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  🥷 Fork &amp;amp; clone &lt;a href="https://github.com/MrChike/LMS-API" rel="noopener noreferrer"&gt;LMS API&lt;/a&gt; repo
&lt;/h3&gt;

&lt;p&gt;Clone and navigate to the api folder as seen below&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2F16d4gfnm71t8zrfslfrp.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.amazonaws.com%2Fuploads%2Farticles%2F16d4gfnm71t8zrfslfrp.png" alt="LMS-API" width="800" height="420"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Fwwpv1rjyjvl9q11bs4tb.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.amazonaws.com%2Fuploads%2Farticles%2Fwwpv1rjyjvl9q11bs4tb.png" alt="VScode" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rename the &lt;code&gt;.env.sample&lt;/code&gt; file to &lt;code&gt;.env&lt;/code&gt; and populate with the database credentials. For the SECRET_KEY you can populate that with &lt;a href="https://djecrety.ir/" rel="noopener noreferrer"&gt;Djecrety&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="nv"&gt;SECRET_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;DATABASE_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nv"&gt;CORS_ALLOWED_ORIGINS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:3000
&lt;span class="nv"&gt;CORS_ALLOW_HEADERS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;content-type,Authorization,X-Requested-With,X-CSRFToken
&lt;span class="nv"&gt;CORS_ALLOW_METHODS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;*&lt;/span&gt;default_methods
&lt;span class="nv"&gt;CORS_ORIGIN_WHITELIST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the 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="nv"&gt;$ &lt;/span&gt;python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="nb"&gt;env&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;source env&lt;/span&gt;/bin/activate
&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; requirements.txt
&lt;span class="nv"&gt;$ &lt;/span&gt;python3 manage.py migrate
Operations to perform:
  Apply all migrations: account, admin, auth, contenttypes, sessions
Running migrations:
  Applying account.0001_initial... OK
  Applying account.0002_alter_profile_table... OK
  Applying account.0003_alter_attachment_table_alter_category_table_and_more... OK
  Applying contenttypes.0001_initial... OK

&lt;span class="nv"&gt;$ &lt;/span&gt;python3 manage.py createsuperuser &lt;span class="c"&gt;#populate with your own credentials&lt;/span&gt;
Email: mrchike@mailinator.com
User &lt;span class="nb"&gt;id&lt;/span&gt;: mrchike
First name: chike
Last name: egonu
Password: 
Password &lt;span class="o"&gt;(&lt;/span&gt;again&lt;span class="o"&gt;)&lt;/span&gt;: 
Superuser created successfully.

&lt;span class="nv"&gt;$ &lt;/span&gt;python3 manage.py runserver
Watching &lt;span class="k"&gt;for &lt;/span&gt;file changes with StatReloader
Performing system checks...

System check identified no issues &lt;span class="o"&gt;(&lt;/span&gt;0 silenced&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
November 18, 2024 - 22:29:22
Django version 5.1.3, using settings &lt;span class="s1"&gt;'lms_api.settings'&lt;/span&gt;
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;confirm that user has been created in prisma studio or your preferred database app.&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fkmttenvepasry58p8gzz.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.amazonaws.com%2Fuploads%2Farticles%2Fkmttenvepasry58p8gzz.png" alt="Prisma Studio" width="800" height="125"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that you have created a user and the backend is up and running, we will be moving on to the next step.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vim lms_project/LMS/app/&lt;span class="o"&gt;(&lt;/span&gt;dashboard&lt;span class="o"&gt;)&lt;/span&gt;/&lt;span class="o"&gt;(&lt;/span&gt;routes&lt;span class="o"&gt;)&lt;/span&gt;/&lt;span class="o"&gt;(&lt;/span&gt;root&lt;span class="o"&gt;)&lt;/span&gt;/page.tsx

... &lt;span class="c"&gt;#Update email and password to your created user. I know it's not best practice so i'm working 😜n it. &lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;const fetchUserData &lt;span class="o"&gt;=&lt;/span&gt; async &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;email&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"yours@email.com"&lt;/span&gt;, &lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"yours@password"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  try &lt;span class="o"&gt;{&lt;/span&gt;
    const response &lt;span class="o"&gt;=&lt;/span&gt; await api.post&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/account/token/'&lt;/span&gt;, &lt;span class="o"&gt;{&lt;/span&gt;
      email,
      password,
    &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    console.log&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'app/(dashboard)/(routes)/(root)/page.tsx'&lt;/span&gt;, response.data.userId&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;response.data&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt; catch &lt;span class="o"&gt;(&lt;/span&gt;error&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    console.error&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Error fetching user data:'&lt;/span&gt;, error&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; // Log error &lt;span class="k"&gt;if &lt;/span&gt;any
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Update the &lt;code&gt;NEXT_PUBLIC_TEACHER_ID&lt;/code&gt; environment variable with your newly created userId (in my case mrchike) and run the command &lt;code&gt;npm run dev&lt;/code&gt; or &lt;code&gt;npm run build&lt;/code&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;$ &lt;/span&gt;npm run dev
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; lms-tutorial@0.1.0 dev
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; next dev

- ready started server on 0.0.0.0:3000, url: http://localhost:3000
- info Loaded &lt;span class="nb"&gt;env &lt;/span&gt;from /home/mrchike/code/features/education/LMS/.env
- event compiled client and server successfully &lt;span class="k"&gt;in &lt;/span&gt;3.4s &lt;span class="o"&gt;(&lt;/span&gt;20 modules&lt;span class="o"&gt;)&lt;/span&gt;
- &lt;span class="nb"&gt;wait &lt;/span&gt;compiling...
- event compiled client and server successfully &lt;span class="k"&gt;in &lt;/span&gt;1335 ms &lt;span class="o"&gt;(&lt;/span&gt;20 modules&lt;span class="o"&gt;)&lt;/span&gt;
- &lt;span class="nb"&gt;wait &lt;/span&gt;compiling /middleware &lt;span class="o"&gt;(&lt;/span&gt;client and server&lt;span class="o"&gt;)&lt;/span&gt;...
- event compiled successfully &lt;span class="k"&gt;in &lt;/span&gt;2.2s &lt;span class="o"&gt;(&lt;/span&gt;45 modules&lt;span class="o"&gt;)&lt;/span&gt;
- &lt;span class="nb"&gt;wait &lt;/span&gt;compiling /&lt;span class="o"&gt;(&lt;/span&gt;dashboard&lt;span class="o"&gt;)&lt;/span&gt;/&lt;span class="o"&gt;(&lt;/span&gt;routes&lt;span class="o"&gt;)&lt;/span&gt;/&lt;span class="o"&gt;(&lt;/span&gt;root&lt;span class="o"&gt;)&lt;/span&gt;/page &lt;span class="o"&gt;(&lt;/span&gt;client and server&lt;span class="o"&gt;)&lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After compilation you will be able to access the page and you can...&lt;/p&gt;

&lt;h3&gt;
  
  
  📚 Start creating courses
&lt;/h3&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.amazonaws.com%2Fuploads%2Farticles%2Fat49x0l5t4gd6ha2bbnd.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.amazonaws.com%2Fuploads%2Farticles%2Fat49x0l5t4gd6ha2bbnd.png" alt="Landing Page" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As it stands you've been able to successfully setup the project on your local. I would more than happy to collaborate with you as there's a whole lot of features to be implemented in the pipeline. Hopefully, they wet your appetite...&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Include extra Video Streaming Option for YouTube &amp;amp; Vimeo&lt;/li&gt;
&lt;li&gt;Implement Docker Support for easy support dealing with dependency issues on different OS&lt;/li&gt;
&lt;li&gt;Include Localization Support for students in multiple countries&lt;/li&gt;
&lt;li&gt;Include extra upload platforms like S3&lt;/li&gt;
&lt;li&gt;Live Classroom Collaboration Between students for Brainstorming, Debates and presentations.&lt;/li&gt;
&lt;li&gt;Advanced Logging System with Grafana&lt;/li&gt;
&lt;li&gt;Create a Course Rating System&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A preview of the ongoing project can be found here: &lt;a href="https://next13-lms-platform-eight.vercel.app/search" rel="noopener noreferrer"&gt;https://next13-lms-platform-eight.vercel.app/search&lt;/a&gt;&lt;br&gt;
Looking forward to working with Ya! 🥹&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.diffchecker.com/text-compare/" rel="noopener noreferrer"&gt;https://www.diffchecker.com/text-compare/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.freeconvert.com/video-compressor/" rel="noopener noreferrer"&gt;https://www.freeconvert.com/video-compressor/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ezgif.com/video-to-gif/" rel="noopener noreferrer"&gt;https://ezgif.com/video-to-gif/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.iloveimg.com/" rel="noopener noreferrer"&gt;https://www.iloveimg.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://uploadthing.com/" rel="noopener noreferrer"&gt;https://uploadthing.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mux.com/" rel="noopener noreferrer"&gt;https://www.mux.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stripe.com/" rel="noopener noreferrer"&gt;https://stripe.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://pypi.org/project/git-filter-repo/" rel="noopener noreferrer"&gt;https://pypi.org/project/git-filter-repo/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://djecrety.ir/" rel="noopener noreferrer"&gt;https://djecrety.ir/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>django</category>
      <category>react</category>
      <category>sql</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Build, Innovate &amp; Collaborate: Setting Up TensorFlow for Open Source Contribution! 🚀✨</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Mon, 04 Nov 2024 04:30:13 +0000</pubDate>
      <link>https://dev.to/mrchike/build-innovate-collaborate-setting-up-tensorflow-for-open-source-contribution-2ce6</link>
      <guid>https://dev.to/mrchike/build-innovate-collaborate-setting-up-tensorflow-for-open-source-contribution-2ce6</guid>
      <description>&lt;p&gt;I'm delighted to share with you the process you would take to setup tensorflow on your machine for open source contribution. &lt;br&gt;
This usually takes days to setup and you don't really get a hand held article on the internet for this. &lt;/p&gt;

&lt;p&gt;Soooooo! i've gone out of my way to make this step easy for the beginner who wants to get their hands dirty. Like i'm so exhausted right now 🥴, it's going to be a long one so just grab your coke and popcorn.&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.amazonaws.com%2Fuploads%2Farticles%2F0jmkdd1j36ku27j9esed.gif" 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.amazonaws.com%2Fuploads%2Farticles%2F0jmkdd1j36ku27j9esed.gif" alt="Popcorn" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this case i would be using &lt;code&gt;ubuntu 22.04&lt;/code&gt; but the process would be similar on any machine since we would be making most changes in docker.&lt;/p&gt;

&lt;p&gt;🥷 Fork &amp;amp; clone &lt;a href="https://github.com/tensorflow/tensorflow" rel="noopener noreferrer"&gt;tensorflow&lt;/a&gt; repo.&lt;br&gt;
⚙️ Setup Development environment for contribution.&lt;br&gt;
🫸 Push and create pull request.&lt;/p&gt;


&lt;h3&gt;
  
  
  🥷 Fork &amp;amp; clone &lt;a href="https://github.com/tensorflow/tensorflow" rel="noopener noreferrer"&gt;tensorflow&lt;/a&gt; repo
&lt;/h3&gt;

&lt;p&gt;Head to the tensorflow github page and fork the repo.&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Fapzo9ufg6pgnfwwbbbk6.jpeg" 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.amazonaws.com%2Fuploads%2Farticles%2Fapzo9ufg6pgnfwwbbbk6.jpeg" alt="Tensorflow Repo" width="800" height="421"&gt;&lt;/a&gt;&lt;br&gt;
After doing this you would have your version of the repo for contribution purpose&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2Faylpxaj2o0qo1nwmucof.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.amazonaws.com%2Fuploads%2Farticles%2Faylpxaj2o0qo1nwmucof.png" alt="Personalized Repo" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  ⚙️ Setup Development environment for contribution
&lt;/h3&gt;

&lt;p&gt;Next, would be to download the repo in zip format or clone the repo in your terminal (Http or SSH)&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;$ &lt;/span&gt;git clone https://github.com/MrChike/tensorflow.git
Cloning into &lt;span class="s1"&gt;'tensorflow'&lt;/span&gt;...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After cloning, we would want to connect to the parent repo so to be updated with the latest changes.&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;$ &lt;/span&gt;git remote add upstream git@github.com:tensorflow/tensorflow.git
&lt;span class="nv"&gt;$ &lt;/span&gt;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
origin git@github.com:MrChike/tensorflow.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
origin git@github.com:MrChike/tensorflow.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
upstream git@github.com:tensorflow/tensorflow.git &lt;span class="o"&gt;(&lt;/span&gt;fetch&lt;span class="o"&gt;)&lt;/span&gt;
upstream git@github.com:tensorflow/tensorflow.git &lt;span class="o"&gt;(&lt;/span&gt;push&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git fetch upstream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By doing this we are now connected and up-to-date with tensorflow repo and can checkout the whatever release we would want to contribute to&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;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-r&lt;/span&gt;
origin/HEAD -&amp;gt; origin/master
origin/master
upstream/LakshmiKalaKadali-patch-1
upstream/Lakshmikala_systemconfig
upstream/Surya_-MatrixSetDiagV3_checkfail
upstream/SuryanarayanaY-patch-2
:

&lt;span class="nv"&gt;$ &lt;/span&gt;git tag
v2.17.1
v2.18.0
v2.18.0-rc0

&lt;span class="nv"&gt;$ &lt;/span&gt;git checkout v2.17.1
Updating files: 100% &lt;span class="o"&gt;(&lt;/span&gt;11816/11816&lt;span class="o"&gt;)&lt;/span&gt;, &lt;span class="k"&gt;done&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
Note: switching to &lt;span class="s1"&gt;'v2.17.1'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take it a step further by introducing docker into the picture, Why? 🐔Because! it's important we isolate the environment and it's build dependencies away from our host machine which gives us a playground to break things and experiment for the fun of it. So we would start by mounting a volume from our host machine to the docker container.&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;$ &lt;/span&gt;docker pull tensorflow/tensorflow:latest
&lt;span class="nv"&gt;$ &lt;/span&gt;docker run &lt;span class="nt"&gt;--name&lt;/span&gt; tensorflow_contribution &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/:/tensorflow tensorflow/tensorflow:latest /bin/bash
&lt;span class="nv"&gt;$ &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt upgrade
&lt;span class="nv"&gt;$ &lt;/span&gt;python &lt;span class="nt"&gt;--version&lt;/span&gt;
root@f56d002b5afc:/# python &lt;span class="nt"&gt;--version&lt;/span&gt;
Python 3.11.0rc1

&lt;span class="nv"&gt;$ &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;python3-dev python3-pip
&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-U&lt;/span&gt; pip
&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nt"&gt;--version&lt;/span&gt;
root@f56d002b5afc:/# pip &lt;span class="nt"&gt;--version&lt;/span&gt;
pip 24.3.1 from /usr/local/lib/python3.11/dist-packages/pip &lt;span class="o"&gt;(&lt;/span&gt;python 3.11&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;# if pip doesn't match your python version which in this case is v3.11 then you would have to update pip to match it.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;python3.11 &lt;span class="nt"&gt;-m&lt;/span&gt; pip &lt;span class="nb"&gt;install &lt;/span&gt;&lt;span class="nv"&gt;pip&lt;/span&gt;&lt;span class="o"&gt;==&lt;/span&gt;24.3.1

________                               _______________
___  __/__________________________________  ____/__  /________      __
__  /  _  _ &lt;span class="se"&gt;\_&lt;/span&gt;  __ &lt;span class="se"&gt;\_&lt;/span&gt;  ___/  __ &lt;span class="se"&gt;\_&lt;/span&gt;  ___/_  /_   __  /_  __ &lt;span class="se"&gt;\_&lt;/span&gt; | /| / /
_  /   /  __/  / / /&lt;span class="o"&gt;(&lt;/span&gt;__  &lt;span class="o"&gt;)&lt;/span&gt;/ /_/ /  /   _  __/   _  / / /_/ /_ |/ |/ /
/_/    &lt;span class="se"&gt;\_&lt;/span&gt;__//_/ /_//____/ &lt;span class="se"&gt;\_&lt;/span&gt;___//_/    /_/      /_/  &lt;span class="se"&gt;\_&lt;/span&gt;___/____/|__/


WARNING: You are running this container as root, which can cause new files &lt;span class="k"&gt;in
&lt;/span&gt;mounted volumes to be created as the root user on your host machine.

To avoid this, run the container by specifying your user&lt;span class="s1"&gt;'s userid:

$ docker run -u $(id -u):$(id -g) args...

root@2e306f66dcfe:/# 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You could crank it up a notch with vscode giving your IDE access to your docker container with the &lt;strong&gt;Attach Visual Studio Code&lt;/strong&gt; option or the equivalent in your favourite IDE and make some changes&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.amazonaws.com%2Fuploads%2Farticles%2Fzx1fytmx1pr6772c9u70.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.amazonaws.com%2Fuploads%2Farticles%2Fzx1fytmx1pr6772c9u70.png" alt="Repo" width="800" height="399"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Fw6yj4cjifd8m0ctadaj0.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.amazonaws.com%2Fuploads%2Farticles%2Fw6yj4cjifd8m0ctadaj0.png" alt="Repo" width="800" height="470"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2F9o1op95694mq63z74afu.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.amazonaws.com%2Fuploads%2Farticles%2F9o1op95694mq63z74afu.png" alt="Repo" width="800" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hope you not getting b🙄red!.Now that we have our cloned repo s ynced with the docker container. We could make changes in the &lt;code&gt;tensorflow/&lt;/code&gt; folder and the changes would reflect on the host machine. &lt;/p&gt;

&lt;p&gt;Well now we got it all setup, you would think we all good right? Psyche!!!!! 😂. Stay with me, coz we still gotta loooong way to go amigo. So lest I deviate, back to business...&lt;/p&gt;

&lt;p&gt;The next step would be to run the configure file to build the changes we've made with &lt;code&gt;./configure&lt;/code&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;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;tensorflow/
&lt;span class="nv"&gt;$ &lt;/span&gt;./configure

root@2e306f66dcfe:/tensorflow# ./configure 
Cannot find bazel. Please &lt;span class="nb"&gt;install &lt;/span&gt;bazel/bazelisk.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the dev world, a new error is a sign of progress...&lt;br&gt;
So what's &lt;a href="https://bazel.build/" rel="noopener noreferrer"&gt;bazel&lt;/a&gt;? It's a build tool developed by Google. It helps automate the process of compiling and testing code. So we would be installing it as instructed in the &lt;a href="https://bazel.build/install/ubuntu" rel="noopener noreferrer"&gt;documentation&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="nv"&gt;$ &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;apt-transport-https curl gnupg &lt;span class="nt"&gt;-y&lt;/span&gt;
curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://bazel.build/bazel-release.pub.gpg | gpg &lt;span class="nt"&gt;--dearmor&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;bazel-archive-keyring.gpg
&lt;span class="nb"&gt;mv &lt;/span&gt;bazel-archive-keyring.gpg /usr/share/keyrings 
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"deb [arch=amd64 signed-by=/usr/share/keyrings/bazel-archive-keyring.gpg] https://storage.googleapis.com/bazel-apt stable jdk1.8"&lt;/span&gt; | &lt;span class="nb"&gt;tee&lt;/span&gt; /etc/apt/sources.list.d/bazel.list

&lt;span class="nv"&gt;$ &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install &lt;/span&gt;bazel
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we try to run the &lt;code&gt;configure&lt;/code&gt; file again&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;root@f56d002b5afc:/tensorflow# ./configure 
WARNING: current bazel installation is not a release version.
Please specify the location of python. &lt;span class="o"&gt;[&lt;/span&gt;Default is /usr/bin/python3]: 


Found possible Python library paths:
  /usr/lib/python3/dist-packages
  /usr/local/lib/python3.10/dist-packages
Please input the desired Python library path to use.  Default is &lt;span class="o"&gt;[&lt;/span&gt;/usr/lib/python3/dist-packages]

Do you wish to build TensorFlow with ROCm support? &lt;span class="o"&gt;[&lt;/span&gt;y/N]: N
No ROCm support will be enabled &lt;span class="k"&gt;for &lt;/span&gt;TensorFlow.

Do you wish to build TensorFlow with CUDA support? &lt;span class="o"&gt;[&lt;/span&gt;y/N]: N
No CUDA support will be enabled &lt;span class="k"&gt;for &lt;/span&gt;TensorFlow.

Do you want to use Clang to build TensorFlow? &lt;span class="o"&gt;[&lt;/span&gt;Y/n]: Y
Clang will be used to compile TensorFlow.

Please specify the path to clang executable. &lt;span class="o"&gt;[&lt;/span&gt;Default is &lt;span class="o"&gt;]&lt;/span&gt;: 


Invalid clang path.  cannot be found. Note that TensorFlow now requires clang to compile. You may override this behavior by setting &lt;span class="nv"&gt;TF_NEED_CLANG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0
Please specify the path to clang executable. &lt;span class="o"&gt;[&lt;/span&gt;Default is &lt;span class="o"&gt;]&lt;/span&gt;: 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point we've meet another blocker, so what's clang? Clang is a compiler for the C, C++, and Objective-C programming languages used as the compiler for building TensorFlow from source which helps compile the C++ components of TensorFlow efficiently and provides useful diagnostics. So we would be installing it from the &lt;a href="https://www.tensorflow.org/install/source" rel="noopener noreferrer"&gt;guide&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="nv"&gt;$ &lt;/span&gt;wget https://github.com/llvm/llvm-project/releases/download/llvmorg-17.0.2/clang+llvm-17.0.2-x86_64-linux-gnu-ubuntu-22.04.tar.xz

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xvf&lt;/span&gt; clang+llvm-17.0.2-x86_64-linux-gnu-ubuntu-22.04.tar.xz
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; clang+llvm-17.0.2-x86_64-linux-gnu-ubuntu-22.04/&lt;span class="k"&gt;*&lt;/span&gt; /usr
&lt;span class="nv"&gt;$ &lt;/span&gt;clang &lt;span class="nt"&gt;--version&lt;/span&gt;

root@f56d002b5afc:/tensorflow# clang &lt;span class="nt"&gt;--version&lt;/span&gt;
clang version 17.0.2 &lt;span class="o"&gt;(&lt;/span&gt;https://github.com/llvm/llvm-project b2417f51dbbd7435eb3aaf203de24de6754da50e&lt;span class="o"&gt;)&lt;/span&gt;
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/bin

&lt;span class="nv"&gt;$ &lt;/span&gt;which clang 

root@f56d002b5afc:/tensorflow# which clang
/usr/bin/clang
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we know path in which clang has been installed, let's run the &lt;code&gt;configure&lt;/code&gt; file again and include the path&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;$ &lt;/span&gt;./configure
root@f56d002b5afc:/tensorflow# ./configure 
WARNING: current bazel installation is not a release version.
Please specify the location of python. &lt;span class="o"&gt;[&lt;/span&gt;Default is /usr/bin/python3]: 


Found possible Python library paths:
  /usr/lib/python3/dist-packages
  /usr/local/lib/python3.10/dist-packages
Please input the desired Python library path to use.  Default is &lt;span class="o"&gt;[&lt;/span&gt;/usr/lib/python3/dist-packages]

Do you wish to build TensorFlow with ROCm support? &lt;span class="o"&gt;[&lt;/span&gt;y/N]: N
No ROCm support will be enabled &lt;span class="k"&gt;for &lt;/span&gt;TensorFlow.

Do you wish to build TensorFlow with CUDA support? &lt;span class="o"&gt;[&lt;/span&gt;y/N]: N
No CUDA support will be enabled &lt;span class="k"&gt;for &lt;/span&gt;TensorFlow.

Do you want to use Clang to build TensorFlow? &lt;span class="o"&gt;[&lt;/span&gt;Y/n]: Y
Clang will be used to compile TensorFlow.

Please specify the path to clang executable. &lt;span class="o"&gt;[&lt;/span&gt;Default is /usr/bin/clang]: 


You have Clang 17.0.2 installed.

Please specify optimization flags to use during compilation when bazel option &lt;span class="s2"&gt;"--config=opt"&lt;/span&gt; is specified &lt;span class="o"&gt;[&lt;/span&gt;Default is &lt;span class="nt"&gt;-Wno-sign-compare&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;: 


Would you like to interactively configure ./WORKSPACE &lt;span class="k"&gt;for &lt;/span&gt;Android builds? &lt;span class="o"&gt;[&lt;/span&gt;y/N]: N
Not configuring the WORKSPACE &lt;span class="k"&gt;for &lt;/span&gt;Android builds.

Preconfigured Bazel build configs. You can use any of the below by adding &lt;span class="s2"&gt;"--config=&amp;lt;&amp;gt;"&lt;/span&gt; to your build command. See .bazelrc &lt;span class="k"&gt;for &lt;/span&gt;more details.
        &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mkl            &lt;span class="c"&gt;# Build with MKL support.&lt;/span&gt;
        &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;mkl_aarch64    &lt;span class="c"&gt;# Build with oneDNN and Compute Library for the Arm Architecture (ACL).&lt;/span&gt;
        &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;monolithic     &lt;span class="c"&gt;# Config for mostly static monolithic build.&lt;/span&gt;
        &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;numa           &lt;span class="c"&gt;# Build with NUMA support.&lt;/span&gt;
        &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;dynamic_kernels        &lt;span class="c"&gt;# (Experimental) Build kernels into separate shared objects.&lt;/span&gt;
        &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;v1             &lt;span class="c"&gt;# Build with TensorFlow 1 API instead of TF 2 API.&lt;/span&gt;
Preconfigured Bazel build configs to DISABLE default on features:
        &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nogcp          &lt;span class="c"&gt;# Disable GCP support.&lt;/span&gt;
        &lt;span class="nt"&gt;--config&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;nonccl         &lt;span class="c"&gt;# Disable NVIDIA NCCL support.&lt;/span&gt;
Configuration finished
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have clang installed let's build our code to reflect changes. This is the format bazel usually takes &lt;br&gt;
&lt;code&gt;bazel build //path/to/folder:file_target --repo_env=WHEEL_NAME=your_personalized_build_name&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;To add some knowlege to your database, When you run pip install tensorflow, you typically don’t see a .whl extension in the command or output because pip handles the download, extraction, and installation of the wheel file seamlessly in the background. However, behind the scenes, pip is indeed downloading a .whl file from PyPI and using it for the installation. So to continue with our bazel installation&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;$ &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;patchelf
&lt;span class="nv"&gt;$ &lt;/span&gt;bazel build //tensorflow/tools/pip_package:wheel &lt;span class="nt"&gt;--repo_env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;WHEEL_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tensorflow_cpu

root@f56d002b5afc:/tensorflow# bazel build //tensorflow/tools/pip_package:wheel &lt;span class="nt"&gt;--repo_env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;WHEEL_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tensorflow_cpu
ERROR: The project you&lt;span class="s1"&gt;'re trying to build requires Bazel 6.5.0 (specified in /tensorflow/.bazelversion), but it wasn'&lt;/span&gt;t found &lt;span class="k"&gt;in&lt;/span&gt; /usr/bin.

You can &lt;span class="nb"&gt;install &lt;/span&gt;the required Bazel version via apt:
  &lt;span class="nb"&gt;sudo &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;sudo &lt;/span&gt;apt &lt;span class="nb"&gt;install &lt;/span&gt;bazel-6.5.0

If this doesn&lt;span class="s1"&gt;'t work, check Bazel'&lt;/span&gt;s installation instructions &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="nb"&gt;help&lt;/span&gt;:
  https://bazel.build/install/ubuntu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to install the exact bazel version the tensorflow project is using as suggested in the terminal and rerun the bazel 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="nv"&gt;$ &lt;/span&gt;apt update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt &lt;span class="nb"&gt;install &lt;/span&gt;bazel-6.5.0
&lt;span class="nv"&gt;$ &lt;/span&gt;bazel build //tensorflow/tools/pip_package:wheel &lt;span class="nt"&gt;--repo_env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;WHEEL_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tensorflow_cpu

root@f56d002b5afc:/tensorflow# bazel build //tensorflow/tools/pip_package:wheel &lt;span class="nt"&gt;--repo_env&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;WHEEL_NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;tensorflow_cpu
Extracting Bazel installation...
Starting &lt;span class="nb"&gt;local &lt;/span&gt;Bazel server and connecting to it...
Analyzing: target //tensorflow/tools/pip_package:wheel &lt;span class="o"&gt;(&lt;/span&gt;544 packages loaded, 22399&lt;span class="se"&gt;\&lt;/span&gt;
 targets configured&lt;span class="o"&gt;)&lt;/span&gt;
    INFO: Found 1 target...
&lt;span class="o"&gt;[&lt;/span&gt;809 / 6,002] 2 actions running
    Compiling src/idl_gen_php.cpp &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;tool]&lt;span class="p"&gt;;&lt;/span&gt; 3s &lt;span class="nb"&gt;local
    &lt;/span&gt;Compiling src/ssl/tls_record.cc &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="k"&gt;for &lt;/span&gt;tool]&lt;span class="p"&gt;;&lt;/span&gt; 1s &lt;span class="nb"&gt;local
    &lt;/span&gt;INFO: Elapsed &lt;span class="nb"&gt;time&lt;/span&gt;: 368.128s, Critical Path: 317.42s
INFO: 5 processes: 1 internal, 4 local.
INFO: Build completed successfully, 5 total actions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; There are three versions for possible build.. CPU, GPU &amp;amp; TPU. This tutorial focused on CPU and for the first build it took me 24hrs+, and upon subsequent builds in minutes because the first build has been cached in the &lt;strong&gt;bazel&lt;/strong&gt; folder.&lt;/p&gt;

&lt;p&gt;So now your changes are being compiled and after that we can install the compiled version in our tensorflow changes in the terminal.&lt;br&gt;
&lt;code&gt;pip install path/to/wheel&lt;/code&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;$ &lt;/span&gt;pip uninstall tensorflow &lt;span class="c"&gt;# If you are removing an already installed custom tensorflow build, it would be that build name instead. In my case, tensorflow_cpu.&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;bazel-bin/tensorflow/tools/pip_package/wheel_house/tensorflow_cpu-2.17.1-cp311-cp311-linux_x86_64.whl

&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;pwd
&lt;/span&gt;root@f56d002b5afc:/# &lt;span class="nb"&gt;pwd&lt;/span&gt;
/
root@f56d002b5afc:/# python
Python 3.11.0rc1 &lt;span class="o"&gt;(&lt;/span&gt;main, Aug 12 2022, 10:02:14&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;GCC 11.2.0] on linux
Type &lt;span class="s2"&gt;"help"&lt;/span&gt;, &lt;span class="s2"&gt;"copyright"&lt;/span&gt;, &lt;span class="s2"&gt;"credits"&lt;/span&gt; or &lt;span class="s2"&gt;"license"&lt;/span&gt; &lt;span class="k"&gt;for &lt;/span&gt;more information.
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; import tensorflow as tf
2024-11-04 02:41:20.894095: I tensorflow/core/util/port.cc:153] oneDNN custom operations are on. You may see slightly different numerical results due to floating-point round-off errors from different computation orders. To turn them off, &lt;span class="nb"&gt;set &lt;/span&gt;the environment variable &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nv"&gt;TF_ENABLE_ONEDNN_OPTS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt;
2024-11-04 02:41:21.211472: I tensorflow/core/platform/cpu_feature_guard.cc:210] This TensorFlow binary is optimized to use available CPU instructions &lt;span class="k"&gt;in &lt;/span&gt;performance-critical operations.
To &lt;span class="nb"&gt;enable &lt;/span&gt;the following instructions: AVX2 AVX_VNNI FMA, &lt;span class="k"&gt;in &lt;/span&gt;other operations, rebuild TensorFlow with the appropriate compiler flags.
HELLO WORLD!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see the &lt;code&gt;HELLO WORLD!&lt;/code&gt; changes made in the &lt;code&gt;tensorflow/python/keras/models.py&lt;/code&gt; module now reflects in our compiled version of tensorflow. The next step would be to commit our changes, push and create a pull request. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt; The community has it's &lt;a href="https://www.tensorflow.org/community/contribute" rel="noopener noreferrer"&gt;code of conduct&lt;/a&gt; you have to follow to push so i would suggest you familiarize yourself with it before creating your pull request. So let's assume are familiar with this and create our pull request&lt;/p&gt;

&lt;h3&gt;
  
  
  🫸 Push and create pull request
&lt;/h3&gt;

&lt;p&gt;So now that everything is set, let's do the needful&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;$ &lt;/span&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Initial Commit"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; git push
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now head to the branch you've created on your github repo and create pull request as seen in the screenshots below&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.amazonaws.com%2Fuploads%2Farticles%2Fxa9wv43jr1ae424bnhwh.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.amazonaws.com%2Fuploads%2Farticles%2Fxa9wv43jr1ae424bnhwh.png" alt="Contribute" width="800" height="400"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Fer1w9znujpgtvb50kppc.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.amazonaws.com%2Fuploads%2Farticles%2Fer1w9znujpgtvb50kppc.png" alt="Contribute" width="800" height="419"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you have completed the full tutorial.&lt;br&gt;
What's left is to collaborate, contribute, solve issues and network in the community..... If you found this article helpful, i would appreciate that you engage in the comment section. 😇&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://emojifinder.com/" rel="noopener noreferrer"&gt;https://emojifinder.com/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.emojisearch.app/" rel="noopener noreferrer"&gt;https://www.emojisearch.app/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://emojipedia.org/" rel="noopener noreferrer"&gt;https://emojipedia.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dillinger.io/" rel="noopener noreferrer"&gt;https://dillinger.io/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/tensorflow/tensorflow" rel="noopener noreferrer"&gt;https://github.com/tensorflow/tensorflow&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://annotely.com/editor" rel="noopener noreferrer"&gt;https://annotely.com/editor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tensorflow.org/install/source" rel="noopener noreferrer"&gt;https://www.tensorflow.org/install/source&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hub.docker.com/r/tensorflow/tensorflow/" rel="noopener noreferrer"&gt;https://hub.docker.com/r/tensorflow/tensorflow/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://bazel.build/install/ubuntu" rel="noopener noreferrer"&gt;https://bazel.build/install/ubuntu&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.tensorflow.org/community/contribute" rel="noopener noreferrer"&gt;https://www.tensorflow.org/community/contribute&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ezgif.com/" rel="noopener noreferrer"&gt;https://ezgif.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tensorflow</category>
      <category>python</category>
      <category>opensource</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Setting Up MKDocs for Your Django Project: A Quick Guide!</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Sat, 19 Oct 2024 22:07:13 +0000</pubDate>
      <link>https://dev.to/mrchike/setting-up-mkdocs-for-your-django-project-a-quick-guide-4jlh</link>
      <guid>https://dev.to/mrchike/setting-up-mkdocs-for-your-django-project-a-quick-guide-4jlh</guid>
      <description>&lt;p&gt;After scouring back and forth the world wide web looking for who's content to devour it came to my notice that this content is the first of it's kind so I would first like to give a special shoutout to my Mom, my Dad 😭😭😭. &lt;/p&gt;

&lt;p&gt;So to kickoff, i would start by highlighting the steps to take to get it done. (You know like begin with the end in mind)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create Django Project&lt;/li&gt;
&lt;li&gt;Install MkDocs &amp;amp; Build Documentation Folder&lt;/li&gt;
&lt;li&gt;Include Documentation Folder in &lt;code&gt;STATICFILES_DIRS&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Register Documentation Folder for Template Rendering&lt;/li&gt;
&lt;li&gt;Setup Url Configuration for public visibility&lt;/li&gt;
&lt;li&gt;Setup MKDocs Configuration &lt;/li&gt;
&lt;li&gt;Insert Static Blocks in HTML File for Static File Management&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build your app...&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create Django Project&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;django-admin startproject google_docx
&lt;span class="nb"&gt;cd &lt;/span&gt;google_docx/
python3 &lt;span class="nt"&gt;-m&lt;/span&gt; venv &lt;span class="nb"&gt;env
source env&lt;/span&gt;/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Install MkDocs &amp;amp; Build Documentation Folder
&lt;/li&gt;
&lt;/ul&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;mkdocs
mkdocs new docs
&lt;span class="nb"&gt;cd &lt;/span&gt;docs
mkdocs build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And now to take a breather before we continue, feel free to go gossip with caroline at the coffee corner, hopefully it doesn't come back to bite you. &lt;/p&gt;

&lt;p&gt;Done with the talk? Let's continue then&lt;br&gt;
Below is currently the file structure of the documentation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docs/
├── docs
│   └── index.md
├── mkdocs.yml
└── site
    ├── 404.html
    ├── css
    │   ├── base.css
    │   ├── bootstrap.min.css
    │   ├── bootstrap.min.css.map
    │   ├── brands.min.css
    │   ├── fontawesome.min.css
    │   ├── solid.min.css
    │   └── v4-font-face.min.css
    ├── img
    │   ├── favicon.ico
    │   └── grid.png
    ├── index.html
    ├── js
    │   ├── base.js
    │   ├── bootstrap.bundle.min.js
    │   ├── bootstrap.bundle.min.js.map
    │   └── darkmode.js
    ├── search
    │   ├── lunr.js
    │   ├── main.js
    │   ├── search_index.json
    │   └── worker.js
    ├── sitemap.xml
    ├── sitemap.xml.gz
    └── webfonts
        ├── fa-brands-400.ttf
        ├── fa-brands-400.woff2
        ├── fa-regular-400.ttf
        ├── fa-regular-400.woff2
        ├── fa-solid-900.ttf
        ├── fa-solid-900.woff2
        ├── fa-v4compatibility.ttf
        └── fa-v4compatibility.woff2
google_docx/
├── asgi.py
├── __init__.py
├── settings.py
├── urls.py
└── wsgi.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So to proceed, we would be heading to the next step.....&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Include Documentation Folder in &lt;code&gt;STATICFILES_DIRS&lt;/code&gt; &amp;amp; Register Documentation Folder for Template Rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Update the following in the &lt;code&gt;settings.py&lt;/code&gt; file
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;STATIC_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;static/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;
&lt;span class="n"&gt;STATIC_ROOT&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="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_DIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;STATIC_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;STATICFILES_DIRS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="n"&gt;BASE_DIR&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;docs/site&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# mkdocs static directory
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="n"&gt;TEMPLATES&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;BACKEND&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;django.template.backends.django.DjangoTemplates&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;DIRS&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;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BASE_DIR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;docs/site&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 directory for HTML template rendering
&lt;/span&gt;        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;APP_DIRS&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;OPTIONS&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;context_processors&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;django.template.context_processors.debug&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;django.template.context_processors.request&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;django.contrib.auth.context_processors.auth&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;django.contrib.messages.context_processors.messages&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="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;ul&gt;
&lt;li&gt;Setup &lt;code&gt;urls.py&lt;/code&gt; Configuration for public visibility
&lt;/li&gt;
&lt;/ul&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;django.contrib&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;admin&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.urls&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;django.views.generic&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;TemplateView&lt;/span&gt;

&lt;span class="n"&gt;urlpatterns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;path&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;admin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;docs/&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TemplateView&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;as_view&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;template_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;index.html&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;ul&gt;
&lt;li&gt;Setup MKDocs Configuration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Update the &lt;code&gt;mkdocs.yml&lt;/code&gt; file&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;site_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Google Docx Documentation&lt;/span&gt; &lt;span class="c1"&gt;# Project Doc Name&lt;/span&gt;
&lt;span class="na"&gt;site_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;site&lt;/span&gt; 
&lt;span class="na"&gt;site_url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://127.0.0.1:8000/docs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;run the mkdocs build command&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;mkdocs build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Insert Static Blocks in HTML File for Static File Management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;NB:&lt;/strong&gt;_ mkdocs by default generates index.html but django can only load static files like css and js with &lt;code&gt;{% load static %}&lt;/code&gt; in html files. So keep in mind that when you update the document and build you would have to rerun this process._&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt; &lt;span class="na"&gt;data-bs-theme=&lt;/span&gt;&lt;span class="s"&gt;"light"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"utf-8"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;http-equiv=&lt;/span&gt;&lt;span class="s"&gt;"X-UA-Compatible"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"IE=edge"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"None"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

        {% load static %}
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"canonical"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"http://127.0.0.1:8003/docs/"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"shortcut icon"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'img/favicon.ico' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Google Docx Documentation&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'css/bootstrap.min.css' %}"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'css/fontawesome.min.css' %}"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'css/brands.min.css' %}"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'css/solid.min.css' %}"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'css/v4-font-face.min.css' %}"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'css/base.css' %}"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"hljs-light"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github.min.css"&lt;/span&gt; &lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;link&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"hljs-dark"&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"stylesheet"&lt;/span&gt; &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/styles/github-dark.min.css"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.8.0/highlight.min.js"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;hljs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;highlightAll&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt; 
    &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'js/bootstrap.bundle.min.js' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
     &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;base_url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="nx"&gt;shortcuts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;help&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;191&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;78&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;previous&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;search&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;83&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'js/base.js' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"{% static 'search/main.js' %}"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final outcome as you'll see below that it's up and running and the code can be found in &lt;a href="https://github.com/MrChike/django_mkdocs" rel="noopener noreferrer"&gt;django_mkdocs&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Fbyrso1e06bea3k9lcfx0.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.amazonaws.com%2Fuploads%2Farticles%2Fbyrso1e06bea3k9lcfx0.png" alt=" " width="800" height="204"&gt;&lt;/a&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.amazonaws.com%2Fuploads%2Farticles%2Fbny94jkf0aji77dd4r1l.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.amazonaws.com%2Fuploads%2Farticles%2Fbny94jkf0aji77dd4r1l.png" alt=" " width="800" height="489"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for your attention so far and would love you to know i'm open to feedback and collaboration. &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>django</category>
      <category>documentation</category>
      <category>developers</category>
    </item>
    <item>
      <title>How to deploy React Portfolio|Project with Github Pages as @ 2024</title>
      <dc:creator>Mr Chike</dc:creator>
      <pubDate>Mon, 30 Sep 2024 14:07:34 +0000</pubDate>
      <link>https://dev.to/mrchike/how-to-deploy-react-portfolioproject-with-github-pages-as-2024-4a69</link>
      <guid>https://dev.to/mrchike/how-to-deploy-react-portfolioproject-with-github-pages-as-2024-4a69</guid>
      <description>&lt;p&gt;Going through the years of tech it’s always interesting to see how things keep evolving. It used to be a whole lot of hassle to deploy applications but I must say it’s really awesome how Github integrated this feature to make life easy. So as a no BS guy, let’s get straight to the point.&lt;/p&gt;

&lt;p&gt;If you’ll rather not build things from scratch, then here is an already existing &lt;a href="https://mrchike.github.io/chikeegonu/" rel="noopener noreferrer"&gt;portfolio&lt;/a&gt; inspired by the Github design. Feel free to fork and update. Below are the steps&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create Portfolio&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;npx create-react-app portfolio&lt;/code&gt;&lt;br&gt;
&lt;code&gt;cd portfolio&lt;/code&gt;&lt;br&gt;
&lt;code&gt;npm install gh-pages --save-dev&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Head to Github account and create repo&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2F2t8yjgbultuhwxlwgrby.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.amazonaws.com%2Fuploads%2Farticles%2F2t8yjgbultuhwxlwgrby.png" alt=" " width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update the package.json to reflect commands.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;"homepage": "https://&amp;lt;username&amp;gt;.github.io/&amp;lt;repository-name&amp;gt;"&lt;br&gt;
"scripts": {&lt;br&gt;
  "predeploy": "npm run build",&lt;br&gt;
  "deploy": "gh-pages -d build"&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Commit and push changes, then build &amp;amp; deploy.&lt;br&gt;
&lt;code&gt;git remote add origin git@github.com:&amp;lt;username&amp;gt;/&amp;lt;repository-name&amp;gt;.git&lt;br&gt;
git add . &amp;amp;&amp;amp; git commit -m "initial commit"&lt;br&gt;
git push --set-upstream origin master&lt;br&gt;
npm run build&lt;br&gt;
npm run deploy&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;View your live website at https://.github.io/ and in my case…&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2F05k313oofhwfups33jjl.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.amazonaws.com%2Fuploads%2Farticles%2F05k313oofhwfups33jjl.png" alt=" " width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
