<?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: Nitesh Kumar</title>
    <description>The latest articles on DEV Community by Nitesh Kumar (@niteshkmdev).</description>
    <link>https://dev.to/niteshkmdev</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%2F735165%2F739e8418-2345-4929-9d7d-2222523f3d52.png</url>
      <title>DEV Community: Nitesh Kumar</title>
      <link>https://dev.to/niteshkmdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/niteshkmdev"/>
    <language>en</language>
    <item>
      <title>Building a Local AI Development Stack with LiteLLM + AWS Bedrock + Open WebUI</title>
      <dc:creator>Nitesh Kumar</dc:creator>
      <pubDate>Mon, 16 Mar 2026 06:49:32 +0000</pubDate>
      <link>https://dev.to/niteshkmdev/building-a-local-ai-development-stack-with-litellm-aws-bedrock-open-webui-4npp</link>
      <guid>https://dev.to/niteshkmdev/building-a-local-ai-development-stack-with-litellm-aws-bedrock-open-webui-4npp</guid>
      <description>&lt;p&gt;&lt;em&gt;How I replaced multiple AI SaaS subscriptions with one simple self‑hosted gateway.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;Over the past few months I kept experimenting with different AI tools.&lt;/p&gt;

&lt;p&gt;Chat apps. Coding assistants. Agent platforms. Most of them were impressive — but almost all of them required &lt;strong&gt;separate subscriptions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After a while it became obvious that many of these tools are simply thin layers on top of the same foundation models.&lt;/p&gt;

&lt;p&gt;So instead of paying for multiple platforms, I decided to build a &lt;strong&gt;single local AI stack&lt;/strong&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses &lt;strong&gt;AWS Bedrock&lt;/strong&gt; for model access&lt;/li&gt;
&lt;li&gt;Uses &lt;strong&gt;LiteLLM&lt;/strong&gt; as a unified gateway&lt;/li&gt;
&lt;li&gt;Uses &lt;strong&gt;Open WebUI&lt;/strong&gt; as a chat interface&lt;/li&gt;
&lt;li&gt;Connects to &lt;strong&gt;VS Code agents&lt;/strong&gt; for coding&lt;/li&gt;
&lt;li&gt;Runs locally using &lt;strong&gt;Docker&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result ended up being cleaner than expected.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;The full flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Open WebUI / VS Code Agents
            │
            ▼
        LiteLLM Gateway
            │
            ▼
        AWS Bedrock
 (Claude, DeepSeek, Qwen, etc)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key idea is &lt;strong&gt;LiteLLM acting as a gateway&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;LiteLLM exposes an &lt;strong&gt;OpenAI‑compatible API&lt;/strong&gt;, which means almost every AI tool can connect to it without needing Bedrock‑specific integrations.&lt;/p&gt;

&lt;p&gt;That single layer simplifies the entire ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1 — Project Structure
&lt;/h2&gt;

&lt;p&gt;I started with a simple project directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AI/
 └── litellm/
     ├── config.yaml
     ├── docker-compose.yml
     └── .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;LiteLLM runs alongside &lt;strong&gt;Redis&lt;/strong&gt; and &lt;strong&gt;Postgres&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;These are used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;usage tracking&lt;/li&gt;
&lt;li&gt;gateway state&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 2 — Docker Compose Setup
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;litellm/docker-compose.yml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;postgres&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres:16&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;litellm-postgres&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_USER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;litellm&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;litellm&lt;/span&gt;
      &lt;span class="na"&gt;POSTGRES_DB&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;litellm&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres_data:/var/lib/postgresql/data&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;55432:5432"&lt;/span&gt;

  &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis:7&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;litellm-redis&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;56379:6379"&lt;/span&gt;

  &lt;span class="na"&gt;litellm&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io/berriai/litellm:main-latest&lt;/span&gt;
    &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;litellm&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;unless-stopped&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4010:4000"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./config.yaml:/app/config.yaml&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;postgres://litellm:litellm@postgres:5432/litellm&lt;/span&gt;
      &lt;span class="na"&gt;REDIS_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
      &lt;span class="na"&gt;REDIS_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;6379&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;postgres&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;redis&lt;/span&gt;
    &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;--config /app/config.yaml&lt;/span&gt;

&lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;postgres_data&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3 — LiteLLM Configuration
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;config.yaml&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;general_settings&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stream_response&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;master_key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sk-admin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;master_key&lt;/code&gt; acts as the &lt;strong&gt;admin API key for the gateway&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4 — Start LiteLLM
&lt;/h2&gt;

&lt;p&gt;From inside the &lt;code&gt;litellm&lt;/code&gt; directory:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Once everything starts, the LiteLLM dashboard is available at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:4010
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 5 — Add AWS Bedrock Credentials
&lt;/h2&gt;

&lt;p&gt;Inside the LiteLLM dashboard navigate to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Models + Endpoints → LLM Credentials
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then click:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Select provider:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Fill the required fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Access Key ID&lt;/li&gt;
&lt;li&gt;AWS Secret Access Key&lt;/li&gt;
&lt;li&gt;AWS Region&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once saved, LiteLLM can start communicating with Bedrock.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 6 — Register Bedrock Models
&lt;/h2&gt;

&lt;p&gt;Next I added the models I wanted LiteLLM to expose.&lt;/p&gt;

&lt;p&gt;Navigate to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Models + Endpoints → Add Model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Provider:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;us.deepseek.r1-v1:0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mapping configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Public Model Name: us.deepseek.r1-v1:0
LiteLLM Model Name: us.deepseek.r1-v1:0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Select your credential and click:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;If everything is configured correctly you should see:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Then click:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;I repeated this for multiple Bedrock models.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 7 — Create an API Key
&lt;/h2&gt;

&lt;p&gt;LiteLLM allows generating API keys for client applications.&lt;/p&gt;

&lt;p&gt;Navigate to:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Create a key such as:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;This key will be used by tools like &lt;strong&gt;Open WebUI&lt;/strong&gt; or &lt;strong&gt;VS Code agents&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 8 — Run Open WebUI
&lt;/h2&gt;

&lt;p&gt;To get a ChatGPT‑style interface I used &lt;strong&gt;Open WebUI&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Run it with Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-p&lt;/span&gt; 3000:8080 &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;--name&lt;/span&gt; openwebui &lt;span class="se"&gt;\&lt;/span&gt;
ghcr.io/open-webui/open-webui:main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open the interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create an account on first launch.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 9 — Connect Open WebUI to LiteLLM
&lt;/h2&gt;

&lt;p&gt;Inside Open WebUI go to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Settings → Connections → OpenAI API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Configure:&lt;/p&gt;

&lt;p&gt;Base URL&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:4010
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;API Key&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;After saving, Open WebUI automatically loads all models registered in LiteLLM.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Result
&lt;/h2&gt;

&lt;p&gt;At this point the stack looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Open WebUI
     ↓
LiteLLM Gateway
     ↓
AWS Bedrock Models
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From a single interface I can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;switch between models&lt;/li&gt;
&lt;li&gt;test prompts&lt;/li&gt;
&lt;li&gt;track token usage&lt;/li&gt;
&lt;li&gt;monitor costs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Using It with Coding Agents
&lt;/h2&gt;

&lt;p&gt;Because LiteLLM exposes an &lt;strong&gt;OpenAI compatible API&lt;/strong&gt;, it integrates directly with developer tools.&lt;/p&gt;

&lt;p&gt;For example in VS Code tools like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Continue.dev&lt;/li&gt;
&lt;li&gt;OpenCode&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Configuration simply requires:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Base URL: http://localhost:4010
API Key: sk-dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets the same Bedrock models power coding workflows.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Setup Works Well
&lt;/h2&gt;

&lt;p&gt;A few reasons I ended up liking this architecture:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No vendor lock‑in&lt;/li&gt;
&lt;li&gt;Pay only for inference&lt;/li&gt;
&lt;li&gt;One API for multiple models&lt;/li&gt;
&lt;li&gt;Works with most AI tooling&lt;/li&gt;
&lt;li&gt;Fully self‑hosted gateway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;LiteLLM effectively becomes the &lt;strong&gt;central router for every AI tool I use&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;The AI tooling ecosystem moves extremely fast. Most products are simply wrappers around the same models.&lt;/p&gt;

&lt;p&gt;Building a small modular stack turned out to be more flexible than relying on several separate platforms.&lt;/p&gt;

&lt;p&gt;Now I have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a local chat interface&lt;/li&gt;
&lt;li&gt;coding agents inside my editor&lt;/li&gt;
&lt;li&gt;access to Bedrock models&lt;/li&gt;
&lt;li&gt;a single gateway controlling everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All running locally with Docker while using AWS only for inference.&lt;/p&gt;

&lt;p&gt;If you're experimenting with AI development, agents, or multi‑model workflows, this setup is a solid foundation.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you build something similar or improve this stack, I'd love to see how others are approaching it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>aws</category>
      <category>llm</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Deploy Static Sites to AWS S3 Using GitHub Actions (Next.js, React, Vue, Astro)</title>
      <dc:creator>Nitesh Kumar</dc:creator>
      <pubDate>Tue, 22 Jul 2025 15:17:14 +0000</pubDate>
      <link>https://dev.to/niteshkmdev/deploy-static-sites-to-aws-s3-using-github-actions-nextjs-react-vue-astro-3dd0</link>
      <guid>https://dev.to/niteshkmdev/deploy-static-sites-to-aws-s3-using-github-actions-nextjs-react-vue-astro-3dd0</guid>
      <description>&lt;p&gt;&lt;strong&gt;Have you ever wondered how to automatically build and deploy your static site projects without relying on platforms like Vercel or Netlify?&lt;/strong&gt; If so, you're in the right place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In this article, we'll walk through how to set up &lt;strong&gt;GitHub Actions&lt;/strong&gt; to build and deploy your static website directly to &lt;strong&gt;AWS S3&lt;/strong&gt;, giving you full control over your CI/CD pipeline — no third-party hosting required.&lt;/p&gt;

&lt;h3&gt;
  
  
  You might be wondering — &lt;strong&gt;what exactly is CI/CD?&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;CI/CD stands for &lt;strong&gt;Continuous Integration&lt;/strong&gt; and &lt;strong&gt;Continuous Deployment&lt;/strong&gt;. It’s a development practice that automates the process of building, testing, and deploying your code every time you push changes to your repository.&lt;/p&gt;

&lt;p&gt;Instead of manually uploading files to a server every time you make updates, CI/CD pipelines handle that for you. This means &lt;strong&gt;fewer interruptions, fewer mistakes, and more time to focus on building,&lt;/strong&gt; not deploying.&lt;/p&gt;

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

&lt;p&gt;Before we get started, make sure you have the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Account: You will need an AWS account to create an S3 bucket and host your site.&lt;/li&gt;
&lt;li&gt;GitHub Account: Required to access GitHub Actions.&lt;/li&gt;
&lt;li&gt;Project: A git initialized project to deploy. This guide is framework-agnostic, so you can use any Node.js-based project that generates a static site (e.g., React.js with CRA or Vite, Next.js with next export)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example Project Setup&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In this guide, I am taking a Vite-React project as an example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest react-auto-deploy &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Understanding GitHub Actions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a Workflow?
&lt;/h3&gt;

&lt;p&gt;A &lt;strong&gt;workflow&lt;/strong&gt; in GitHub Actions is an automated process that runs one or more jobs. It's defined in a &lt;code&gt;.yml&lt;/code&gt; (YAML) file inside the &lt;code&gt;.github/workflows/&lt;/code&gt; directory of your repository.&lt;/p&gt;

&lt;p&gt;Each workflow can be triggered by specific GitHub events such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pushes&lt;/strong&gt; to a branch (e.g., pushing code to &lt;code&gt;main&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pull requests&lt;/strong&gt; (e.g., opening a PR to review changes)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Manual triggers&lt;/strong&gt; (e.g., running it with a button click using &lt;code&gt;workflow_dispatch&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scheduled triggers&lt;/strong&gt; (e.g., every day at midnight using &lt;code&gt;cron&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Releases&lt;/strong&gt;, issue comments, or other custom events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example workflow file structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight perl"&gt;&lt;code&gt;&lt;span class="nv"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nv"&gt;deploy&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;├──&lt;/span&gt; &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;github&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;   &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nv"&gt;workflows&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;span class="err"&gt;│&lt;/span&gt;       &lt;span class="err"&gt;└──&lt;/span&gt; &lt;span class="nv"&gt;deploy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;yml&lt;/span&gt;   &lt;span class="err"&gt;←&lt;/span&gt; &lt;span class="nv"&gt;your&lt;/span&gt; &lt;span class="nv"&gt;workflow&lt;/span&gt; &lt;span class="nv"&gt;definition&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;A workflow file defines &lt;strong&gt;what should happen and when&lt;/strong&gt;, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install dependencies&lt;/li&gt;
&lt;li&gt;Build your site&lt;/li&gt;
&lt;li&gt;Run tests&lt;/li&gt;
&lt;li&gt;Deploy to AWS S3 or other platforms&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Step-by-Step Guide&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create an S3 bucket.

&lt;ul&gt;
&lt;li&gt;Go to the &lt;a href="https://s3.console.aws.amazon.com/s3/" rel="noopener noreferrer"&gt;AWS S3 Console&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click "Create bucket”&lt;/li&gt;
&lt;li&gt;Enter a unique bucket name (e.g., my-static-site)&lt;/li&gt;
&lt;li&gt;Choose a region&lt;/li&gt;
&lt;li&gt;Uncheck "Block all public access" under permissions&lt;/li&gt;
&lt;li&gt;Confirm the warning checkbox&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Create bucket"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Enable Static Website Hosting&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Go to the "Properties" tab&lt;/li&gt;
&lt;li&gt;Scroll to "Static website hosting”&lt;/li&gt;
&lt;li&gt;Click "Edit”&lt;/li&gt;
&lt;li&gt;Enable "Static website hosting”&lt;/li&gt;
&lt;li&gt;set index document: &lt;code&gt;index.html&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click "Save changes”&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Make Files Public &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to the "Permissions" tab&lt;/li&gt;
&lt;li&gt;Scroll to "Bucket policy"&lt;/li&gt;
&lt;li&gt;Click "Edit", and paste the following policy (replace your-bucket-name):
&lt;/li&gt;
&lt;/ul&gt;

&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"PublicReadGetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::your-bucket-name/*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

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



&lt;p&gt;Replace &lt;code&gt;your-bucket-name&lt;/code&gt; with your unique bucket name. This step makes your bucket publicly accessible.&lt;/p&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Go to GitHub and create your repository&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Create a .github/workflows/deploy.yaml file at the root of your project (locally or on GitHub)&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Paste the following config (I will explain the config below)&lt;br&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and Upload So Sure Dashboard&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;deploy-stagging&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# step 1&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

        &lt;span class="c1"&gt;# step 2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Use Node.js 20.x&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;

         &lt;span class="c1"&gt;# step 3&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

        &lt;span class="c1"&gt;#step 4&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Create .env file&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;cat &amp;lt;&amp;lt;EOF &amp;gt; ./.env&lt;/span&gt;
          &lt;span class="s"&gt;${{ secrets.ENV }}&lt;/span&gt;
          &lt;span class="s"&gt;EOF&lt;/span&gt;

        &lt;span class="c1"&gt;#step 5&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build project&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;

        &lt;span class="c1"&gt;#step 6&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Configure AWS credentials&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aws-actions/configure-aws-credentials@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;aws-access-key-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_ACCESS_KEY_ID }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-secret-access-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_SECRET_ACCESS_KEY }}&lt;/span&gt;
          &lt;span class="na"&gt;aws-region&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.AWS_REGION }}&lt;/span&gt;

        &lt;span class="c1"&gt;#step 7&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Upload dist to S3&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
          &lt;span class="s"&gt;aws s3 sync dist/ s3://${{ secrets.AWS_S3_BUCKET }}/ --delete&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The first section sets the name and trigger for the workflow. Whenever  code is pushed to the main branch, the workflow will automatically run the defined jobs.&lt;/p&gt;

&lt;p&gt;In the jobs section, the first three steps clone the repository to the GitHub Actions container (running Ubuntu-latest), install Node.js, and download all the node_modules required to build the project.&lt;/p&gt;

&lt;p&gt;You can skip the &lt;code&gt;- name: Create .env file&lt;/code&gt; step if you don't have any environment variables. This step takes the repository secret &lt;code&gt;ENV&lt;/code&gt; and creates a &lt;code&gt;.env&lt;/code&gt; file at the root of the project.&lt;/p&gt;

&lt;p&gt;In the next step, the project is built. It's important to set up the correct scripts in &lt;code&gt;package.json&lt;/code&gt; to make your project run properly.&lt;/p&gt;

&lt;p&gt;The next step configures the AWS client to use your account via the AWS CLI.&lt;/p&gt;

&lt;p&gt;Finally, step 7 uploads the output folder to your S3 bucket.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Before you commit and push the workflow file, set up the repository secrets on GitHub.&lt;/li&gt;
&lt;li&gt;Navigate to your repository on GitHub and click the Settings tab.
&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%2Fe8imt0mbmq1m1xpzllkr.png" alt=" " width="662" height="100"&gt;
&lt;/li&gt;
&lt;li&gt;In the Security section, navigate to Secrets and Variables &amp;gt; Actions.
&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%2Fnpvb0ecehl2ftuvji6nq.png" alt=" " width="379" height="257"&gt;
&lt;/li&gt;
&lt;li&gt;Here, set up all the secrets used in the above workflow file. 
&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%2F5wv9wzm60k9rz5ua4x8j.png" alt=" " width="800" height="539"&gt;
&lt;/li&gt;
&lt;li&gt;Be careful and set up the same variables as used in the YAML file &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; , &lt;code&gt;AWS_REGION&lt;/code&gt; , &lt;code&gt;AWS_S3_BUCKET&lt;/code&gt; , &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; , &lt;code&gt;ENV&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;AWS_S3_BUCKET&lt;/code&gt; is your s3 bucket name&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_REGION&lt;/code&gt; is your s3 bucket region&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;AWS_ACCESS_KEY_ID&lt;/code&gt; and &lt;code&gt;AWS_SECRET_ACCESS_KEY&lt;/code&gt; can be generated from the AWS console IAM role.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ENV&lt;/code&gt; all your .env file variables needed at build time. Copy all the contents of the .env file and paste it here as the value&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that you've set up your GitHub repository with the necessary secrets and workflow file, it's time to commit your changes and see the automation in action. The next time you push to the main branch, GitHub Actions will automatically build your project and deploy it to AWS S3.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Testing Your Deployment&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;After pushing your code, you can monitor the workflow execution by going to the "Actions" tab in your GitHub repository. You should see your workflow running, and once completed successfully, your website will be live on your S3 bucket's URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Access Your Site&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Go back to the &lt;strong&gt;"Properties"&lt;/strong&gt; tab&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;"Static website hosting"&lt;/strong&gt;, copy the &lt;strong&gt;"Bucket website endpoint"&lt;/strong&gt; (e.g., &lt;code&gt;http://your-bucket-name.s3-website-us-east-1.amazonaws.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Open it in your browser — your site should be live!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Common Issues and Troubleshooting&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When implementing this deployment pipeline, you might encounter a few common issues. Here are some troubleshooting tips to help you resolve them quickly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Permission Errors&lt;/strong&gt;: Ensure your IAM user has the necessary permissions for S3 operations (s3:PutObject, s3:GetObject, s3:DeleteObject).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build Failures&lt;/strong&gt;: Check your workflow logs carefully. Most build failures are due to missing dependencies or environment variables.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache Issues&lt;/strong&gt;: If your updates aren't showing up, you might need to configure cache invalidation for your S3 bucket, especially if you're using CloudFront.&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;And that’s it! You’ve just set up automatic deployment for your static site using GitHub Actions and AWS S3. No more manual uploads — push your code and let GitHub do the rest. It saves time, reduces errors, and keeps your workflow smooth.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>cicd</category>
      <category>aws</category>
      <category>githubactions</category>
    </item>
    <item>
      <title>Geeks For Geeks - Problem of the Day | POTD | 18 Aug</title>
      <dc:creator>Nitesh Kumar</dc:creator>
      <pubDate>Fri, 18 Aug 2023 05:14:20 +0000</pubDate>
      <link>https://dev.to/niteshkmdev/geeks-for-geeks-problem-of-the-day-potd-18-aug-fje</link>
      <guid>https://dev.to/niteshkmdev/geeks-for-geeks-problem-of-the-day-potd-18-aug-fje</guid>
      <description>&lt;h2&gt;
  
  
  &lt;a href="https://practice.geeksforgeeks.org/problems/leaders-in-an-array-1587115620/1" rel="noopener noreferrer"&gt;Leaders in an array&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Given an array A of positive integers. Your task is to find the leaders in the array. An element of array is leader if it is greater than or equal to all the elements to its right side. The rightmost element is always a leader.&lt;br&gt;
&lt;strong&gt;Example 1:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; n = 6 A[] = {16,17,4,3,5,2}&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 17 5 2 &lt;strong&gt;Explanation:&lt;/strong&gt; The first leader is 17  as it is greater than all the elements to its right.  Similarly, the next &lt;br&gt;
leader is 5. The right most element  is always a leader so it is also &lt;br&gt;
included.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Example 2:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Input:&lt;/strong&gt; n = 5 A[] = {1,2,3,4,0}&lt;br&gt;
&lt;strong&gt;Output:&lt;/strong&gt; 4 0&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Explanation:&lt;/strong&gt; 0 is the rightmost element   and 4 is the only element which is greater   than all the elements to its right.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Your Task:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
You don't need to read input or print anything. The task is to complete the function &lt;strong&gt;leader&lt;/strong&gt;() which takes array A and n as input parameters and returns an array of leaders in order of their appearance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected Time Complexity:&lt;/strong&gt; O(n)&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Expected Auxiliary Space:&lt;/strong&gt; O(n)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Constraints:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
1 &amp;lt;= n &amp;lt;= 107&lt;br&gt;&lt;br&gt;
0 &amp;lt;= Ai &amp;lt;= 107&lt;br&gt;
&lt;a href="https://practice.geeksforgeeks.org/problems/leaders-in-an-array-1587115620/1" rel="noopener noreferrer"&gt;Link to the Question&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;h2&gt;
  
  
  Approach:
&lt;/h2&gt;

&lt;p&gt;The idea is last element is always going to be the Leader(as there is no element on it's right) and if we can find an element greator than it on left than it's also leader.In this way we get the leader's in reverse;&lt;/p&gt;

&lt;h2&gt;
  
  
  Algorithm:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  intialize a vector/array with the last elemtent of the array&lt;/li&gt;
&lt;li&gt;  maintain a variable of last Leader&lt;/li&gt;
&lt;li&gt;  traverse the array in reverse and if an element greator than the last leader is encountered update last leader and push it to the resulting vector/array&lt;/li&gt;
&lt;li&gt;  Doing so we get the leader array in reverse so simply reverse the array and return it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Time Complexity: time to traverse + time to reverse = O(N) + O(N/2) = O(N);&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Space Complexity: O(N) as all element can be leader in worst case of array being sorted in reverse order.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  c++ code:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; vector&amp;lt;int&amp;gt; leaders(int a[], int n){
        // Code here
        vector&amp;lt;int&amp;gt; res = {a[n-1]};

        int crL = a[n-1];

        for(int i = n-2;i&amp;gt;=0;i--){
            if(crL&amp;lt;=a[i]){
                crL = a[i];
                res.push_back(crL);
            }

        }

       reverse(res.begin(),res.end());
        return res;

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

&lt;/div&gt;



</description>
    </item>
    <item>
      <title>Create a Todo List App with React-Native and Styled components</title>
      <dc:creator>Nitesh Kumar</dc:creator>
      <pubDate>Thu, 03 Aug 2023 10:09:03 +0000</pubDate>
      <link>https://dev.to/niteshkmdev/create-a-todo-list-app-with-react-native-and-styled-components-3gog</link>
      <guid>https://dev.to/niteshkmdev/create-a-todo-list-app-with-react-native-and-styled-components-3gog</guid>
      <description>&lt;p&gt;A todo list is a simple but useful app that helps you keep track of your tasks and goals. It allows you to add, edit, delete, and mark items as done. In this article, we will learn how to create a todo list app with React Native, a popular framework for building cross-platform mobile apps using JavaScript and React.&lt;/p&gt;

&lt;p&gt;React Native is a framework that lets you use React, a library for building user interfaces, to create native apps for iOS and Android. React Native uses native components instead of web components, which means you can access the features and performance of the native platform. React Native also supports hot reloading and live reloading, which means you can see the changes in your app instantly without rebuilding it.&lt;/p&gt;

&lt;p&gt;To create a todo list app with React Native, we will follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Set up the development environment and install the dependencies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create the main App component that will render the todo list and the input field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a custom Task component that will display each todo item and handle the editing and deleting actions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the useState hook to manage the state of the app, such as the list of tasks and the current input value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use the useEffect hook to save and load the tasks from the local storage using AsyncStorage.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Add some styling and icons to make the app look nicer.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's see how to implement each step in detail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Set up the development environment and install the dependencies
&lt;/h2&gt;

&lt;p&gt;To start building our app, we need to set up our development environment and install some dependencies. We will use Expo, a tool that simplifies the process of developing and testing React Native apps. Expo provides a set of tools and services that let you run your app on your device or simulator without installing any native dependencies.&lt;/p&gt;

&lt;p&gt;To install Expo, we need to have Node.js and npm installed on our system. You can download them from &lt;a href="https://dev.to^1^"&gt;here&lt;/a&gt;. Then, we can run the following command in our terminal:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install --global expo-cli&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will install the Expo command line interface (CLI) globally on our system.&lt;/p&gt;

&lt;p&gt;Next, we need to create a new project using Expo. We can do this by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;expo init TodoList&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will create a new folder called TodoList with some boilerplate code and configuration files. We can choose a template for our project from the options that Expo provides. For this tutorial, we will use the blank template, which gives us a minimal setup.&lt;/p&gt;

&lt;p&gt;Then, we need to navigate to our project folder and start the development server by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cd TodoList&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;expo start&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will open a web page with a QR code and some options to run our app. We can scan the QR code with our device using the Expo Go app, which we can download from &lt;a href="https://dev.to^2^"&gt;here&lt;/a&gt; for iOS or &lt;a href="https://dev.to^3^"&gt;here&lt;/a&gt; for Android. Alternatively, we can use an emulator or simulator on our computer by clicking on the Run on iOS simulator or Run on Android device/emulator buttons.&lt;/p&gt;

&lt;p&gt;Before we start coding, we need to install some additional dependencies for our app. We will use styled-components, a library that lets us write CSS in JavaScript, to style our components. We will also use react-native-vector-icons, a library that provides us with icons for our app. To install these dependencies, we need to run:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install styled-components react-native-vector-icons&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We also need to link the react-native-vector-icons library to our project by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;expo install @expo/vector-icons&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This will ensure that the icons are available for our app.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Create the main App component that will render the todo list and the input field
&lt;/h2&gt;

&lt;p&gt;Now that we have set up our project and installed our dependencies, we can start coding our app. We will use Visual Studio Code as our code editor, but you can use any editor of your choice.&lt;/p&gt;

&lt;p&gt;We will start by creating the main App component that will render the todo list and the input field. To do this, we need to open the App.js file in our project folder and replace its content with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Import React and useState hook&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StatusBar&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Import styled-components&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components/native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Import Task component&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/Task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@react-native-async-storage/async-storage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Create a container component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="s2"&gt;`
  flex: 1;

  background-color: #e8eaed;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create an input component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;&lt;span class="s2"&gt;`
  padding: 15px;

  padding-left: 55px;

  border-color: #c0c0c0;

  border-width: 1px;

  border-radius: 60px;

  width: 90%;

  margin: 20px;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create an icon component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Icon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="s2"&gt;`
  width: 30px;

  height: 30px;

  position: absolute;

  top: 35px;

  left: 30px;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a list component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ScrollView&lt;/span&gt;&lt;span class="s2"&gt;`
  margin: 20px;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create the main App component&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Define the state for the input value&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Define the state for the list of tasks&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="c1"&gt;// Define a function to handle the input change&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Define a function to handle the submit action&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Check if the input is not empty&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Create a new task object&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

        &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

        &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="c1"&gt;// Update the list of tasks&lt;/span&gt;

      &lt;span class="nf"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;newTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

      &lt;span class="c1"&gt;// Reset the input value&lt;/span&gt;

      &lt;span class="nf"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Save tasks to local storage&lt;/span&gt;

    &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tasks&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="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Load tasks from local storage&lt;/span&gt;

    &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Check if value is not null&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Parse value into an array and update tasks state variable&lt;/span&gt;

        &lt;span class="nf"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// Render the container component&lt;/span&gt;

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StatusBar&lt;/span&gt;
        &lt;span class="na"&gt;animated&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;backgroundColor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#c0c0c0"&lt;/span&gt;
        &lt;span class="na"&gt;barStyle&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dark-content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;showHideTransition&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fade&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Input&lt;/span&gt;
        &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;onChangeText&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Enter a task"&lt;/span&gt;
        &lt;span class="na"&gt;onSubmitEditing&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Icon&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./assets/favicon.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Task&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Let's break down what this code does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, we import React and the useState hook from "react". The useState hook allows us to manage the state of our component, which is the data that changes over time. We will use it to store the input value and the list of tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we import styled from "styled-components/native". This allows us to create custom components using CSS syntax. We will use it to style our container, input, icon, and list components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, we import Task from "./components/Task". This is a custom component that we will create later to display each todo item. We will pass it the task object as a prop.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After that, we create a container component using styled.View. This is a basic component that renders a view that can contain other components. We give it a flex: 1 property, which means it will take up all the available space in its parent. We also give it a background-color: #e8eaed property, which sets its background color to a light gray.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we create an input component using styled.TextInput. This is a component that renders an input field that can accept user input. We give it some padding, border, border-radius, width, and margin properties to make it look nice. We also give it a padding-left: 55px property, which creates some space for the icon component that we will add later.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, we create an icon component using styled.Image. This is a component that renders an image from a source file. We give it some width, height, position, top, and left properties to position it on top of the input component. We will use this icon as a button to add new tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we create a list component using styled.ScrollView. This is a component that renders a scrollable view that can contain other components. We give it some margin to create some space around it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After that, we create the main App component and export it as default. This is the root component of our app that will render all the other components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the App component, we define two state variables using the useState hook: input and tasks. The input variable holds the current value of the input field, and the tasks variable holds an array of task objects. Each task object has an id, a title, and a done property. The id is a unique identifier for each task, the title is the text of the task, and the done is a boolean value that indicates whether the task is completed or not. We also define two setter functions for each state variable: setInput and setTasks. These functions allow us to update the state variables with new values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we define two functions to handle the input change and submit actions: handleChange and handleSubmit. The handleChange function takes a value as an argument and updates the input state variable with that value. The handleSubmit function checks if the input value is not empty and creates a new task object with that value as its title. It also generates a random id for the new task and sets its done property to false. Then, it updates the tasks state variable by&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 3: Create a custom Task component that will display each todo item and handle the editing and deleting actions
&lt;/h2&gt;

&lt;p&gt;In this step, we will create a custom Task component that will render each todo item in our list. We will also add some functionality to edit, delete, and mark the tasks as done. To do this, we need to create a new file called Task.js in the components folder and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Import React and useState hook&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Import styled-components&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components/native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Import icons from react-native-vector-icons&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AntDesign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Feather&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@expo/vector-icons&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a container component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="s2"&gt;`
  flex-direction: row;

  align-items: center;

  background-color: #fff;

  padding: 15px;

  margin-bottom: 20px;

  border-radius: 10px;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a text component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="s2"&gt;`
  font-size: 18px;

  margin-left: 15px;

  flex: 1;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create an input component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;&lt;span class="s2"&gt;`
  font-size: 18px;

  margin-left: 15px;

  flex: 1;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create an icon container component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IconContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TouchableOpacity&lt;/span&gt;&lt;span class="s2"&gt;`
  width: 30px;

  height: 30px;

  align-items: center;

  justify-content: center;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Create the Task component and export it as default&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Define the state for the editing mode&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;editing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEditing&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Define the state for the edited title&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Define a function to handle the edit action&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleEdit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Toggle the editing mode&lt;/span&gt;

    &lt;span class="nf"&gt;setEditing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;editing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Update the title with the edited value&lt;/span&gt;

    &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// TODO: Save the edited task to the local storage&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Define a function to handle the input change&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Update the title state variable with the input value&lt;/span&gt;

    &lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Define a function to handle the delete action&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleDelete&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO: Delete the task from the local storage and update the tasks state variable in the App component&lt;/span&gt;

    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Delete &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Define a function to handle the done action&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleDone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO: Toggle the done property of the task in the local storage and update the tasks state variable in the App component&lt;/span&gt;

    &lt;span class="nf"&gt;alert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Done &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="c1"&gt;// Render the container component and pass the task id as a key prop&lt;/span&gt;

    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IconContainer&lt;/span&gt; &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleDone&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AntDesign&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkcircle&lt;/span&gt;&lt;span class="dl"&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;checkcircleo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#55BCF6"&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IconContainer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;editing&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChangeText&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;
          &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;textDecorationLine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;line-through&lt;/span&gt;&lt;span class="dl"&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;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IconContainer&lt;/span&gt; &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleEdit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Feather&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;editing&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;check&lt;/span&gt;&lt;span class="dl"&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;edit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#55BCF6"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IconContainer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;IconContainer&lt;/span&gt; &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleDelete&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AntDesign&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"delete"&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#55BCF6"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;IconContainer&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;



&lt;p&gt;Let's break down what this code does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;First, we import React and the useState hook from "react". The useState hook allows us to manage the state of our component. We will use it to store the editing mode and the edited title of each task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we import styled from "styled-components/native". This allows us to create custom components using CSS syntax. We will use it to style our container, text, input, and icon container components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, we import AntDesign and Feather from "@expo/vector-icons". These are two sets of icons that we can use in our app. We will use them to render the check, edit, and delete icons for each task.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After that, we create a container component using styled.View. This is a basic component that renders a view that can contain other components. We give it a flex-direction: row property, which means it will arrange its children horizontally. We also give it an align-items: center property, which means it will align its children vertically in the center. We also give it some background-color, padding, margin-bottom, and border-radius properties to make it look nice.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we create a text component using styled.Text. This is a component that renders some text. We give it a font-size: 18px property, which sets its font size to 18 pixels. We also give it a margin-left: 15px property, which creates some space on the left. We also give it a flex: 1 property, which means it will take up all the remaining space in its parent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, we create an input component using styled.TextInput. This is a component that renders an input field that can accept user input. We give it the same properties as the text component, except for the margin-left property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we create an icon container component using styled.TouchableOpacity. This is a component that renders a view that can respond to touch events. We give it some width, height, align-items, and justify-content properties to position it as a square with an icon in the center.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;After that, we create the Task component and export it as default. This is the custom component that we will use to display each todo item in our list. We pass it the task object as a prop from the App component.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Inside the Task component, we define two state variables using the useState hook: editing and title. The editing variable holds a boolean value that indicates whether the task is in editing mode or not. The title variable holds the current value of the task title. We also define two setter functions for each state variable: setEditing and setTitle. These functions allow us to update the state variables with new values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Next, we define four functions to handle the edit, delete, done, and input change actions: handleEdit, handleDelete, handleDone, and handleChange. The handleEdit function toggles the editing mode and updates the title with the edited value. The handleDelete function deletes the task from the local storage and updates the tasks state variable in the App component. The handleDone function toggles the done property of the task in the local storage and updates the tasks state variable in the App component. The handleChange function updates the title state variable with the input value.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, we return some JSX code that renders the container component with some icon container components and either a text or an input component depending on the editing mode.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's how we create a custom Task component that will display each todo item and handle the editing and deleting actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Use the useState hook to manage the state of the app, such as the list of tasks and the current input value
&lt;/h2&gt;

&lt;p&gt;In this step, we will learn how to use the useState hook to manage the state of our app. The state is the data that changes over time in our app, such as the list of tasks and the current input value. The useState hook is a function that lets us create and update state variables in our functional components.&lt;/p&gt;

&lt;p&gt;To use the useState hook, we need to import it from "react" at the top of our file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then, we need to call it inside our component and pass it an initial value for our state variable. The useState hook returns an array with two elements: the state variable and a setter function. We can use array destructuring to assign them to some names, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialValue&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The state variable holds the current value of our state, and the setState function allows us to update it with a new value. We can use any name we want for these variables, as long as they are meaningful and consistent.&lt;/p&gt;

&lt;p&gt;For example, in our App component, we have two state variables: input and tasks. The input variable holds the current value of the input field, and the tasks variable holds an array of task objects. We initialize them with an empty string and an empty array, respectively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can use these state variables in our component to render the input field and the list of tasks. For example, we can pass the input value as a prop to the Input component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Input&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can also map over the tasks array and render a Task component for each item:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Task&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;))}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;To update our state variables, we need to call the setter functions with a new value. For example, in our handleChange function, we update the input state variable with the value that we get from the onChangeText prop of the Input component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="nf"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Similarly, in our handleSubmit function, we update the tasks state variable by creating a new task object with the input value as its title and adding it to the beginning of the tasks array:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;newTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nf"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can also pass these setter functions as props to other components that need to update our state. For example, we can pass the setTasks function as a prop to the Task component, so that it can delete or mark a task as done:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Task&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setTasks&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;That's how we use the useState hook to manage the state of our app. The useState hook allows us to create and update state variables in our functional components without using classes or lifecycle methods. It also ensures that our components re-render when our state changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Use the useEffect hook to save and load the tasks from the local storage using AsyncStorage
&lt;/h2&gt;

&lt;p&gt;In this step, we will learn how to use the useEffect hook to save and load the tasks from the local storage using AsyncStorage. The useEffect hook is a function that lets us perform side effects in our functional components, such as fetching data, updating the document title, or saving data to the local storage. AsyncStorage is a module that provides us with a simple and asynchronous API to store and retrieve data from the local storage of our device.&lt;/p&gt;

&lt;p&gt;To use the useEffect hook, we need to import it from "react" at the top of our file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Then, we need to call it inside our component and pass it a callback function and an optional dependency array. The callback function is where we write our side effect code, and the dependency array is where we specify the variables that our side effect depends on. The useEffect hook will run the callback function after every render of our component, unless we provide a dependency array. If we provide a dependency array, the useEffect hook will only run the callback function when one of the variables in the array changes.&lt;/p&gt;

&lt;p&gt;For example, in our App component, we want to save the tasks state variable to the local storage whenever it changes. To do this, we need to use the useEffect hook with a callback function that calls AsyncStorage.setItem with a key and a value. The key is a string that identifies our data, and the value is a string that represents our data. We can use JSON.stringify to convert our tasks array into a string. We also need to pass [tasks] as the dependency array, so that the useEffect hook only runs when tasks changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Save tasks to local storage&lt;/span&gt;

&lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tasks&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="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Similarly, we want to load the tasks state variable from the local storage when our component mounts for the first time. To do this, we need to use another useEffect hook with a callback function that calls AsyncStorage.getItem with a key. The key is the same string that we used to save our data. The AsyncStorage.getItem method returns a promise that resolves with a value or null if no data is found. We can use JSON.parse to convert the value into an array and update our tasks state variable with it. We also need to pass an empty array as the dependency array, so that the useEffect hook only runs once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Load tasks from local storage&lt;/span&gt;

&lt;span class="nx"&gt;AsyncStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Check if value is not null&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Parse value into an array and update tasks state variable&lt;/span&gt;

&lt;span class="nf"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&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;p&gt;To use AsyncStorage, we need to import it from "@react-native-async-storage/async-storage" at the top of our file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;AsyncStorage&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@react-native-async-storage/async-storage&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We also need to install it as a dependency by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install @react-native-async-storage/async-storage&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;That's how we use the useEffect hook to save and load the tasks from the local storage using AsyncStorage. The useEffect hook allows us to perform side effects in our functional components without using classes or lifecycle methods. It also ensures that our side effects are consistent with our state and props. AsyncStorage allows us to store and retrieve data from the local storage of our device in an asynchronous way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6: Add some styling and icons to make the app look nicer
&lt;/h2&gt;

&lt;p&gt;In this step, we will learn how to add some styling and icons to make our app look nicer. We will use styled-components, a library that lets us write CSS in JavaScript, to style our components. We will also use react-native-vector-icons, a library that provides us with icons for our app.&lt;/p&gt;

&lt;p&gt;To use styled-components, we need to install it as a dependency by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install styled-components&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, we need to import it from "styled-components/native" at the top of our file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components/native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;To use react-native-vector-icons, we need to install it as a dependency by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install react-native-vector-icons&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, we need to link it to our project by running:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;expo install @expo/vector-icons&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then, we need to import the icons that we want to use from "@expo/vector-icons" at the top of our file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AntDesign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Feather&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@expo/vector-icons&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can use styled-components to create custom components using CSS syntax. For example, we can create a container component using styled.View:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="s2"&gt;`

flex: 1;

background-color: #e8eaed;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can also use styled-components to style existing components, such as TextInput or Image. For example, we can create an input component using styled.TextInput:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;&lt;span class="s2"&gt;`

padding: 15px;

padding-left: 55px;

border-color: #c0c0c0;

border-width: 1px;

border-radius: 60px;

width: 250px;

margin: 20px;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can use react-native-vector-icons to render icons from different sets, such as AntDesign or Feather. For example, we can render an icon from AntDesign using the AntDesign component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;AntDesign&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"checkcircle"&lt;/span&gt; &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#55BCF6"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;We can also use props such as name, size, and color to customize the icon.&lt;/p&gt;

&lt;p&gt;Let's see how we can use these libraries to style our app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Styling the App component
&lt;/h3&gt;

&lt;p&gt;In the App component, we will style the container, input, icon, and list components.&lt;/p&gt;

&lt;p&gt;The container component is a basic component that renders a view that can contain other components. We will give it a flex: 1 property, which means it will take up all the available space in its parent. We will also give it a background-color: #e8eaed property, which sets its background color to a light gray.&lt;/p&gt;

&lt;p&gt;The input component is a component that renders an input field that can accept user input. We will give it some padding, border, border-radius, width, and margin properties to make it look nice. We will also give it a padding-left: 55px property, which creates some space for the icon component that we will add later.&lt;/p&gt;

&lt;p&gt;The icon component is a component that renders an image from a source file. We will give it some width, height, position, top, and left properties to position it on top of the input component. We will use this icon as a button to add new tasks.&lt;/p&gt;

&lt;p&gt;The list component is a component that renders a scrollable view that can contain other components. We will give it some margin to create some space around it.&lt;/p&gt;

&lt;p&gt;Here is the code for the App component with styling:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Import React and useState hook&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Import styled-components&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components/native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Import Task component&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Task&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./components/Task&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create a container component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="s2"&gt;`

flex: 1;

background-color: #e8eaed;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create an input component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;&lt;span class="s2"&gt;`

padding: 15px;

padding-left: 55px;

border-color: #c0c0c0;

border-width: 1px;

border-radius: 60px;

width: 250px;

margin: 20px;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create an icon component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Icon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Image&lt;/span&gt;&lt;span class="s2"&gt;`

width: 30px;

height: 30px;

position: absolute;

top: 35px;

left: 30px;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create a list component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;List&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ScrollView&lt;/span&gt;&lt;span class="s2"&gt;`

margin: 20px;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create the main App component&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Define the state for the input value&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;



&lt;span class="c1"&gt;// Define the state for the list of tasks&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;



&lt;span class="c1"&gt;// Define a function to handle the input change&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="nf"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;



&lt;span class="c1"&gt;// Define a function to handle the submit action&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Check if the input is not empty&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Create a new task object&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

&lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;



&lt;span class="c1"&gt;// Update the list of tasks&lt;/span&gt;

&lt;span class="nf"&gt;setTasks&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;newTask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;



&lt;span class="c1"&gt;// Reset the input value&lt;/span&gt;

&lt;span class="nf"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;



&lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;

&lt;span class="c1"&gt;// Render the container component&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

// Render the input component and pass the input value and change handler as props

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Input&lt;/span&gt;

&lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="na"&gt;onChangeText&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Enter a task"&lt;/span&gt;

&lt;span class="na"&gt;onSubmitEditing&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

// Render the icon component and pass the source as a prop

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Icon&lt;/span&gt; &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./assets/add.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

// Render the list component

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

// Map over the tasks array and render a Task component for each item

&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Task&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;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;h3&gt;
  
  
  Styling the Task component
&lt;/h3&gt;

&lt;p&gt;In the Task component, we will style the container, text, input, and icon container components. We will also use icons from react-native-vector-icons to render the check, edit, and delete icons for each task.&lt;/p&gt;

&lt;p&gt;The container component is a basic component that renders a view that can contain other components. We will give it a flex-direction: row property, which means it will arrange its children horizontally. We will also give it an align-items: center property, which means it will align its children vertically in the center. We will also give it some background-color, padding, margin-bottom, and border-radius properties to make it look nice.&lt;/p&gt;

&lt;p&gt;The text component is a component that renders some text. We will give it a font-size: 18px property, which sets its font size to 18 pixels. We will also give it a margin-left: 15px property, which creates some space on the left. We will also give it a flex: 1 property, which means it will take up all the remaining space in its parent.&lt;/p&gt;

&lt;p&gt;The input component is a component that renders an input field that can accept user input. We will give it the same properties as the text component, except for the margin-left property.&lt;/p&gt;

&lt;p&gt;The icon container component is a component that renders a view that can respond to touch events. We will give it some width, height, align-items, and justify-content properties to position it as a square with an icon in the center.&lt;/p&gt;

&lt;p&gt;We will use icons from AntDesign and Feather to render the check, edit, and delete icons for each task. We will use props such as name, size, and color to customize the icons.&lt;/p&gt;

&lt;p&gt;Here is the code for the Task component with styling and icons:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;
&lt;span class="c1"&gt;// Import React and useState hook&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Import styled-components&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;styled-components/native&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Import icons from react-native-vector-icons&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AntDesign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Feather&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@expo/vector-icons&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create a container component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;View&lt;/span&gt;&lt;span class="s2"&gt;`

flex-direction: row;

align-items: center;

background-color: #fff;

padding: 15px;

margin-bottom: 20px;

border-radius: 10px;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create a text component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="s2"&gt;`

font-size: 18px;

margin-left: 15px;

flex: 1;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create an input component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TextInput&lt;/span&gt;&lt;span class="s2"&gt;`

font-size: 18px;

margin-left: 15px;

flex: 1;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create an icon container component using styled-components&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;IconContainer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TouchableOpacity&lt;/span&gt;&lt;span class="s2"&gt;`

width: 30px;

height: 30px;

align-items: center;

justify-content: center;

`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;



&lt;span class="c1"&gt;// Create the Task component and export it as default&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Define the state for the editing mode&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;editing&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setEditing&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;



&lt;span class="c1"&gt;// Define the state for the edited title&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;



&lt;span class="c1"&gt;// Define a function to handle the edit action&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleEdit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Toggle the editing mode&lt;/span&gt;

&lt;span class="nf"&gt;setEditing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;editing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Update the title with the edited value&lt;/span&gt;

&lt;span class="nf"&gt;setTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// TODO: Save the edited task to the local storage&lt;/span&gt;

&lt;span class="p"&gt;};&lt;/span&gt;



&lt;span class="c1"&gt;// Define a function to handle the input change&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

&lt;span class="c1"&gt;// Update the title state variable&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The project structure for the todo list app using React Native is as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The root folder of the project is called TodoList, which contains some configuration files and folders generated by Expo, such as app.json, package.json, node_modules, etc.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The src folder contains the source code of our app, which consists of two files: App.js and Task.js. App.js is the main file that renders the app component, which contains the input field and the list of tasks. Task.js is the file that defines the task component, which displays each todo item and handles the editing and deleting actions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The assets folder contains the image files that we use in our app, such as add.png, which is the icon for adding new tasks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The components folder contains the custom components that we create using styled-components, such as Container, Input, Icon, List, Text, and IconContainer. These components are used to style our app and make it look nicer.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a diagram that shows the project structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
TodoList
├── assets
│ └── favicon.png
├── src
│ └── Task.js
├── App.js
├── app.json
├── package.json
└── node_modules

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;I hope this helps you understand the project structure of our app. If you have any questions or feedback, please let me know in the comments below.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You're very welcome! I'm glad you enjoyed reading my articles and learned something new. I appreciate your feedback and support. Thank you for being a loyal reader of my blog. 😊&lt;/p&gt;

&lt;p&gt;If you want to read more of my articles, you can follow me. You can also follow me on &lt;a href="https://twitter.com/Niteshk16279976" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and &lt;a href="https://www.instagram.com/nitesh.kumar.mishra/" rel="noopener noreferrer"&gt;Instagram&lt;/a&gt; to get the latest updates on my work. I hope to see you again soon! 🙌&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>reactnative</category>
      <category>android</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Firebase Express React Nodejs (FERN stack) Chating Application | (PWA) Full Stack application (tutorial part 1)</title>
      <dc:creator>Nitesh Kumar</dc:creator>
      <pubDate>Sun, 23 Jan 2022 14:50:43 +0000</pubDate>
      <link>https://dev.to/niteshkmdev/firebase-express-react-nodejs-fern-stack-chating-application-pwa-full-stack-application-tutorial-part-1-32ma</link>
      <guid>https://dev.to/niteshkmdev/firebase-express-react-nodejs-fern-stack-chating-application-pwa-full-stack-application-tutorial-part-1-32ma</guid>
      <description>&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%2Fhd2r0ebpxoy4cwzmemew.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%2Fhd2r0ebpxoy4cwzmemew.jpeg" alt="FERN STACK IMAGE" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is FERN Stack?
&lt;/h2&gt;

&lt;p&gt;FERN Stack is a Collection of Technology used to build an application it contain &lt;a href="https://firebase.google.com" rel="noopener noreferrer"&gt;Firebase&lt;/a&gt;, &lt;a href="https://expressjs.com/" rel="noopener noreferrer"&gt;ExpressJs&lt;/a&gt;, &lt;a href="https://reactjs.org/" rel="noopener noreferrer"&gt;ReactJs&lt;/a&gt; and &lt;a href="https://nodejs.org/en/" rel="noopener noreferrer"&gt;Nodejs&lt;/a&gt;. In this application we are going to use firebase as database and for authentication servise . ExpressJs for backend server and ReactJs for Frontend.&lt;br&gt;
We will also use Heroku for hosting our WEB APP.&lt;/p&gt;
&lt;h2&gt;
  
  
  About our Project
&lt;/h2&gt;

&lt;p&gt;.&lt;br&gt;
we are going to build a Chat application with &lt;a href="https://en.wikipedia.org/wiki/End-to-end_encryption" rel="noopener noreferrer"&gt;end-to-end encryption&lt;/a&gt;. This application can be installed on android devise like native app that's the power of PWA. Here is the demo of what we are going to build.&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%2Fdoj9no09s6xyajp39022.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%2Fdoj9no09s6xyajp39022.jpeg" alt="Preview Screenshot" width="540" height="1200"&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%2Fpkxk1eflq7y0d9ju5ijr.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%2Fpkxk1eflq7y0d9ju5ijr.jpeg" alt="Preview Screenshot" width="540" height="1200"&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%2F7yyrpzmqotdum4u0fitu.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%2F7yyrpzmqotdum4u0fitu.jpeg" alt="Preview Screenshot" width="540" height="1200"&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%2Fkl9mhcrauo2s42pibgkg.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%2Fkl9mhcrauo2s42pibgkg.jpeg" alt="Preview Screenshot" width="540" height="1200"&gt;&lt;/a&gt;&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%2F4jvp2orimb4whwfy6s08.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%2F4jvp2orimb4whwfy6s08.jpeg" alt="Preview Screenshot" width="540" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So this is the app we are going to build this app exactly look like as show in the above images. for the complete sourse code check the &lt;a href="https://github.com/Nktech-Official/message" rel="noopener noreferrer"&gt;github repositry&lt;/a&gt; . you can also check  my  &lt;a href="https://github.com/Nktech-Official/" rel="noopener noreferrer"&gt;github&lt;/a&gt; account for more such projects.&lt;/p&gt;
&lt;h2&gt;
  
  
  What's in this part (Part 1)?
&lt;/h2&gt;

&lt;p&gt;In this Part we will setup our environment for FERN Stack, and create file structure of our app. we will also build our homepage. you can download all the images/icon and resourse from the github repo.&lt;/p&gt;
&lt;h3&gt;
  
  
  Download NodeJs.
&lt;/h3&gt;

&lt;p&gt;First of all we need nodjs installed on our pc. you can download it from &lt;a href="https://nodejs.org/en/download/" rel="noopener noreferrer"&gt;https://nodejs.org/en/download/&lt;/a&gt; download LTS version &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%2Fblogger.googleusercontent.com%2Fimg%2Fa%2FAVvXsEg_R0h_G9QB5Ko7QJwIUDWktDv_3nf1yOIZZ7Cclyv4zKc06xqY8tPgL9007E5XSJcxE6zDYf79Nu4MWshcVEE37J3otqM82Ad686sdNWpk_bKE1U9Ew22Za0Y054Pgj-boK9CD6qSh5RNkn2lUJHCflVhvHa86ZlzpmVKgogTez5_Ylp1OCcAiHNsiqA%3Ds1560" 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%2Fblogger.googleusercontent.com%2Fimg%2Fa%2FAVvXsEg_R0h_G9QB5Ko7QJwIUDWktDv_3nf1yOIZZ7Cclyv4zKc06xqY8tPgL9007E5XSJcxE6zDYf79Nu4MWshcVEE37J3otqM82Ad686sdNWpk_bKE1U9Ew22Za0Y054Pgj-boK9CD6qSh5RNkn2lUJHCflVhvHa86ZlzpmVKgogTez5_Ylp1OCcAiHNsiqA%3Ds1560" alt="Download NodeJs Lts" width="1560" height="839"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you go any error in installation please leave a comment i will reach you as soon as possible.&lt;br&gt;
Project Setup.&lt;/p&gt;

&lt;p&gt;Create a directory and open a terminal inside the directory .&lt;br&gt;
run the following command to create your react app.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;npx create-react-app message-frontend --template cra-template-pwa&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here message-frontend is the name of application you can choose any name of your choise.&lt;/p&gt;

&lt;p&gt;open the current directory in the code editor i am going to use VS-Code . &lt;br&gt;
Note:- open the directory containig folder message-forntend and not the message-frontend folder itself.&lt;/p&gt;

&lt;p&gt;This will look something like this&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%2Fblogger.googleusercontent.com%2Fimg%2Fa%2FAVvXsEhONFVhnfhh48fJUJk0fSRtg_SzO0LkhCxQGALd07W_CtRS7ak68IreWysk_RrIY6wakJ7PpWfMubDVnK_OpjntwCzrgec7hY1BZkfvFPGmtIfON4uhxk6ZErctN5lV9cHU_RPcMOq1HNkGZhQ-awr6LJXgxBsb5bZn48ak_bUB4ve9Tr-z3ajchmZjVw%3Dw640-h230" 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%2Fblogger.googleusercontent.com%2Fimg%2Fa%2FAVvXsEhONFVhnfhh48fJUJk0fSRtg_SzO0LkhCxQGALd07W_CtRS7ak68IreWysk_RrIY6wakJ7PpWfMubDVnK_OpjntwCzrgec7hY1BZkfvFPGmtIfON4uhxk6ZErctN5lV9cHU_RPcMOq1HNkGZhQ-awr6LJXgxBsb5bZn48ak_bUB4ve9Tr-z3ajchmZjVw%3Dw640-h230" alt="Vs Code" width="638" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now open Terminal and run command &lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm init -y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;this will initialize a nodejs prject outside our app the idea is to setup backend in the parent folder of our react frontend now your project look's something like this&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%2Fblogger.googleusercontent.com%2Fimg%2Fa%2FAVvXsEgwReqJHyW5i2_7YtuXJroxY-ijvb9bRx_Vlt0hAdyhO3rPA8eP57b67GLnDAl3047c0u1kh7rTUxYVVjuV2MWNhGO1sUPs6s4jnm7-CslukBspi521wZ9tiXjzVWvnIapWuNI5GIAiFGNz-RObro_Ee6CmAr7feHT3-emfk9WRHeXpsK6vzmjLlr2b0g%3Dw640-h310" 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%2Fblogger.googleusercontent.com%2Fimg%2Fa%2FAVvXsEgwReqJHyW5i2_7YtuXJroxY-ijvb9bRx_Vlt0hAdyhO3rPA8eP57b67GLnDAl3047c0u1kh7rTUxYVVjuV2MWNhGO1sUPs6s4jnm7-CslukBspi521wZ9tiXjzVWvnIapWuNI5GIAiFGNz-RObro_Ee6CmAr7feHT3-emfk9WRHeXpsK6vzmjLlr2b0g%3Dw640-h310" alt="vs code image" width="640" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;add this two lines in the script tag of package.json of root folder &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%2Fblogger.googleusercontent.com%2Fimg%2Fa%2FAVvXsEjzPwwS3ybgSOsWng4Eq-GbxYdXxIxTU7V2tYKRM38U6tvjouJQw7y_Ivi8N3eVJChCZs8OjgJc_dFpt7f9IL5L3fJ6G8bHUaD73-1HfSTN6HPBPA6K7_e-7ODotOECHUCk2v1YgEaAaSKx0Zrxu0ejuiih5IqqxEXrGNn0M4XuleMVURP1rlWZeAiekw%3Dw640-h254" 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%2Fblogger.googleusercontent.com%2Fimg%2Fa%2FAVvXsEjzPwwS3ybgSOsWng4Eq-GbxYdXxIxTU7V2tYKRM38U6tvjouJQw7y_Ivi8N3eVJChCZs8OjgJc_dFpt7f9IL5L3fJ6G8bHUaD73-1HfSTN6HPBPA6K7_e-7ODotOECHUCk2v1YgEaAaSKx0Zrxu0ejuiih5IqqxEXrGNn0M4XuleMVURP1rlWZeAiekw%3Dw640-h254" alt="package.json" width="640" height="254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a file named &lt;code&gt;index.js&lt;/code&gt; in root of the project. &lt;br&gt;
Create a file name &lt;code&gt;.env&lt;/code&gt; for writing environment variables &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%2F9zt25lnolhxzi3crchau.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%2F9zt25lnolhxzi3crchau.png" alt="file structre" width="309" height="317"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's install some packages using yarn but before that we need to install yarn using npm. yarn and npm are both the package manager for nodejs but yarn is more optimized so we are going to use yarn you can use npm all the command used with yarn can also  be used with npm.&lt;/p&gt;

&lt;p&gt;use command's &lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install -g yarn&lt;/code&gt; &lt;br&gt;
&lt;code&gt;yarn add express express-session firebase-admin dotenv&lt;/code&gt;&lt;br&gt;
now your file structure looks like this &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%2F4bjkbhkhm5jqq3dwban4.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%2F4bjkbhkhm5jqq3dwban4.png" alt="file vs code" width="303" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;if you got  &lt;code&gt;package-lock.json&lt;/code&gt;   file then delete it . this can happen if you used npm command but if you are planning to use npm then don't delete it. &lt;/p&gt;

&lt;p&gt;your package.json file is updated after the command you run check these linese are added inside dependencies .&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%2Fbjm4x9gd51t5b915xobt.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%2Fbjm4x9gd51t5b915xobt.png" alt="package.json dependencies" width="480" height="236"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;add following code inside your index.js file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const dotenv = require("dotenv");
const express = require("express");
const session = require("express-session");
const app = express();
dotenv.config()
const port = process.env.PORT || 8081;
app.use(express.json());
app.use(
    session({
        secret: process.env.serverSession_secret, //Read's value from .env file 
        resave: false,
        saveUninitialized: true,
        cookie: { expires: new Date(253402300000000) }
    })
);

app.listen(port, () =&amp;gt; {
    console.log(`App listening on http://localhost:${port} !`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;1.First line import's dotenv the packages help us to read value from .env file used to set environment variables&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;next two liens import express and express-session package used to make server and handel server session respectively.&lt;/li&gt;
&lt;li&gt;Then we initialize our express app in the next line.&lt;/li&gt;
&lt;li&gt;then we have configured dotenv in the next line&lt;/li&gt;
&lt;li&gt;After that we have added port number which reads from .env file if none is given it use 8081 as default port to run the server &lt;/li&gt;
&lt;li&gt;Then we have added middle-ware's &lt;code&gt;express.json()&lt;/code&gt; and &lt;code&gt;session()&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;express.json()&lt;/code&gt; parse the request body to json format and session middle ware used to handle session . &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Add this line in your .env file here the environment variables are set in the form of key-value pair &lt;br&gt;
like thie  &lt;code&gt;key=value&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;serverSession_secret=my_secret_key_genereted_using_some_Hash_function
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;here serverSession_secret   is the key and  my_secret_key_genereted_using_some_Hash_function&lt;br&gt;
 is teh value here the value is suppose to be secrete so you can choose any secret value and don't push this .env file to the git repositry you can move the file ./message-frontend/.gitignore to the root of the &lt;br&gt;
Before moving &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%2F4jknj76v6ddlvj0te1uj.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%2F4jknj76v6ddlvj0te1uj.png" alt="Before moving" width="217" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After Moving&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%2Fdtcjsswkjh73r0io7b3m.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%2Fdtcjsswkjh73r0io7b3m.png" alt="After Moving" width="235" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and add the &lt;code&gt;.env&lt;/code&gt; file to &lt;code&gt;.gitignore&lt;/code&gt;  file like this:&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%2F4m0dwih6jz7e4e91y27d.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%2F4m0dwih6jz7e4e91y27d.png" alt=".gitignore" width="636" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;by doing this git will ignore &lt;code&gt;.env&lt;/code&gt; file .&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:- Read full Article &lt;a href="https://nktechnicals.blogspot.com/2022/01/firebase-express-react-nodejs-fern.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

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