<?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: eugene musebe</title>
    <description>The latest articles on DEV Community by eugene musebe (@musebe).</description>
    <link>https://dev.to/musebe</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%2F46918%2F75feabc6-e2e7-48fc-bec0-5d898ee1e1c0.jpeg</url>
      <title>DEV Community: eugene musebe</title>
      <link>https://dev.to/musebe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/musebe"/>
    <language>en</language>
    <item>
      <title>Meet the Cloudinary Creators Community: A New Space for Developers Building with Media</title>
      <dc:creator>eugene musebe</dc:creator>
      <pubDate>Mon, 23 Feb 2026 14:13:47 +0000</pubDate>
      <link>https://dev.to/cloudinary/from-cloud-to-crowd-introducing-the-cloudinary-creators-community-3g8e</link>
      <guid>https://dev.to/cloudinary/from-cloud-to-crowd-introducing-the-cloudinary-creators-community-3g8e</guid>
      <description>&lt;p&gt;The wait is finally over! We’re honored and excited to pull back the curtain on a project that has been fueling our passion for months: the &lt;a href="https://cloudinary.com/developers/community?utm_source=dev-dot-to&amp;amp;utm_content=community-post" rel="noopener noreferrer"&gt;Cloudinary Creators Community&lt;/a&gt; (CCC).&lt;/p&gt;

&lt;p&gt;At Cloudinary, we know that the leap from finishing a coding tutorial to landing your dream role can feel like a massive chasm. That’s why we created the CCC. We aren't just building a community; we’re building a bridge to help you cross that gap and step into your future as a leader in the tech industry.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Vision: ‘From Cloud to Crowd’
&lt;/h2&gt;

&lt;p&gt;Our mission is captured in four simple words: &lt;strong&gt;from Cloud to Crowd&lt;/strong&gt;,a phrase coined by one of our community members, Jerome Hardaway.&lt;/p&gt;

&lt;p&gt;This program is specifically designed for the dreamers and the doers, the early-career developers, the brave career-changers, and the media-savvy creators who are ready to shape the future of the visual web. Whether you're just starting to understand how images and videos power the internet or you're already building complex apps, we’re here to empower you with the tools, mentorship, and global network you need to grow from a learner into a &lt;strong&gt;recognized Cloudinary Creator.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;At the heart of everything we do are our three core values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learn.&lt;/strong&gt; Master the fundamentals of modern media management and high-performance web development through structured, accessible education.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build.&lt;/strong&gt; Turn that knowledge into action! We provide the platform for you to ship real-world projects that make your portfolio shine.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect.&lt;/strong&gt; Join a vibrant, global ecosystem of peers and industry experts who are all rooting for your success.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We believe that when you combine the right tools with a supportive community, there’s no limit to what you can create. Ready to see how we’re making it happen?&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 1: Education
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Joining the Community: Two Pathways
&lt;/h3&gt;

&lt;p&gt;We want to make sure the CCC is accessible while maintaining the high-quality mentorship that makes this program special. There are two exciting ways to join us:&lt;/p&gt;

&lt;h3&gt;
  
  
  The Partner Pathway
&lt;/h3&gt;

&lt;p&gt;We’re incredibly proud to launch in collaboration with global nonprofits that are changing the face of tech. If you’re a member of &lt;a href="https://gssoc.girlscript.org/" rel="noopener noreferrer"&gt;&lt;strong&gt;GirlScript&lt;/strong&gt;&lt;/a&gt;, &lt;strong&gt;&lt;a href="https://developersinvogue.org/" rel="noopener noreferrer"&gt;Developers in Vogue&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://vetswhocode.io/" rel="noopener noreferrer"&gt;Vets Who Code&lt;/a&gt;&lt;/strong&gt;, &lt;strong&gt;&lt;a href="https://www.hackyourfuture.dk/" rel="noopener noreferrer"&gt;Hack Your Future&lt;/a&gt;&lt;/strong&gt;, or &lt;a href="https://www.tampadevs.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Tampa Devs&lt;/strong&gt;&lt;/a&gt;, you have a direct seat at the table! We work closely with these organizations to provide dedicated spots for their communities.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Individual Pathway
&lt;/h3&gt;

&lt;p&gt;Are you an independent builder ready to level up? You can join, too! Simply dive into our "&lt;a href="https://training.cloudinary.com/courses/devrel-c2c-next?utm_source=dev-dot-to&amp;amp;utm_content=community-post" rel="noopener noreferrer"&gt;&lt;strong&gt;Cloud to Crowd&lt;/strong&gt;&lt;/a&gt;" course at the Cloudinary Academy. Once you’ve mastered the material and passed the exam, you can submit an application to join our priority waitlist for the next available cohort.&lt;/p&gt;

&lt;p&gt;Because we keep our cohorts selective to ensure everyone gets the support they need, these spots are highly coveted, so bring your A-game!&lt;/p&gt;

&lt;h2&gt;
  
  
  Phase 2: Activation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Discord: Our Digital Headquarters
&lt;/h3&gt;

&lt;p&gt;Discord is where Phase 2 happens. Once inside, you get access to private channels, technical support, and our Developer Relations staff. To keep the community vibrant, we have a 30-day rule: &lt;strong&gt;New members must introduce themselves within their first month to keep their seat.&lt;/strong&gt; You have 14 days to accept your invitation. We also monitor activity. After 60 days of silence, your status becomes inactive, and after 90 days, your spot is released to a new learner on the waitlist. This ensures our headquarters is full of creators ready to ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  Selectivity and Waitlist Management
&lt;/h2&gt;

&lt;p&gt;To guarantee quality mentorship, we limit active seats. This keeps our environment high-performing and focused. We operate on a bi-annual model with two intake cycles. If seats are full, you’ll join our priority waitlist. We monitor activity closely and invite waitlisted learners as spots open, ensuring every creator gets the support they deserve. Even if you’re not yet onboarded as an official Cloudinary Creator, however, please join us on Discord to engage with the community and participate in our fun activities such as hackathons and challenges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Membership Benefits and Rewards
&lt;/h2&gt;

&lt;p&gt;Your growth is rewarded at every stage. As a recognized creator, you gain access to a toolkit designed to power your professional portfolio.&lt;/p&gt;

&lt;p&gt;The journey includes a one-year renewable &lt;strong&gt;Ambassador Plan&lt;/strong&gt; to ensure your personal projects perform at their best. We also celebrate your milestones with exclusive &lt;strong&gt;digital badges&lt;/strong&gt; via Holopin, giving you a way to showcase your education and project achievements to your network.&lt;/p&gt;

&lt;p&gt;Beyond the tech, you’ll join an ecosystem built on mentorship. This includes dedicated office hours for technical Q&amp;amp;A, tailored career advice, and networking opportunities within the broader Cloudinary partner network. And to welcome you properly, once you’ve made your first meaningful engagement on Discord, we’ll ship the official CCC &lt;strong&gt;Swag Pack&lt;/strong&gt; directly to your door.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Engagement Path (12 Points/Year)
&lt;/h2&gt;

&lt;p&gt;We value builders over observers. To keep your creator status active, we use a simple point system with &lt;strong&gt;a goal of 12 points per year&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You earn &lt;strong&gt;5 points&lt;/strong&gt; for shipping a project and &lt;strong&gt;3&lt;/strong&gt; for joining a mini-community hackathon. Attending events earns you &lt;strong&gt;2 points&lt;/strong&gt;, while smaller acts like helping a peer solve a bug or joining a weekly standup earn &lt;strong&gt;1 point&lt;/strong&gt;. This path ensures our creators stay sharp, connected, and consistently moving forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Community Life and Activities
&lt;/h2&gt;

&lt;p&gt;The activation phase is where the energy truly shifts. We keep the momentum high with hackathons and mini challenges designed to test your skills and reward your creativity with exciting prizes.&lt;/p&gt;

&lt;p&gt;Our regular Demo Days give you a global stage to showcase your projects to the community and beyond. To track your progress, we use gamification through leaderboards and badges to celebrate our most active contributors. When you need help or career advice, our live office hours provide direct access to the experts who can help you solve technical challenges and plan your next big move.&lt;/p&gt;

&lt;h2&gt;
  
  
  Professionalism and Governance
&lt;/h2&gt;

&lt;p&gt;A community this vibrant thrives on respect. Our Code of Conduct ensures that every member feels included and supported as they grow. We prioritize kindness and helpfulness, creating a professional network where everyone can advance their career safely.&lt;/p&gt;

&lt;p&gt;This is a long-term partnership. To renew your spot each year, we look for continued growth through new project submissions and engagement with your peers. Staying connected means dropping into Discord at least once every 60 days to share your progress.&lt;/p&gt;

&lt;p&gt;We’re ready to build the future of the visual web with you. Visit our &lt;a&gt;Community page&lt;/a&gt; to find your path and start your journey from learner to creator today. Let's go!&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Cloudinary ❤️ developers&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Ready to level up your media workflow? Start using Cloudinary for free and build better visual experiences today.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;👉 &lt;strong&gt;&lt;a href="https://cloudinary.com/users/register_free?utm_campaign=5266-&amp;amp;utm_medium=employee_referral&amp;amp;utm_source=dev-dot-to&amp;amp;utm_content=cloud-to-crowd" rel="noopener noreferrer"&gt;Create your free account&lt;/a&gt;&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>community</category>
      <category>webdev</category>
      <category>ai</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Streamlining Your Next.js Projects with Supabase and Drizzle ORM</title>
      <dc:creator>eugene musebe</dc:creator>
      <pubDate>Sat, 02 Mar 2024 10:50:17 +0000</pubDate>
      <link>https://dev.to/musebe/streamlining-your-nextjs-projects-with-supabase-and-drizzle-orm-4gam</link>
      <guid>https://dev.to/musebe/streamlining-your-nextjs-projects-with-supabase-and-drizzle-orm-4gam</guid>
      <description>&lt;p&gt;This guide showcases how to build an efficient application using Supabase for data handling, complemented by Drizzle ORM for advanced database schema management in TypeScript. Starting with database seeding, we aim to demonstrate effective data retrieval, leveraging Drizzle ORM's intuitive blend of SQL-like and relational data access. Drizzle ORM not only simplifies database interactions but also introduces a suite of tools to enhance development workflows, setting the foundation for a productive and streamlined development experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Step 1: Setting Up Your Next.js Environment&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To start your Next.js project, execute the command &lt;code&gt;npx create-next-app@latest syncleaf&lt;/code&gt;. This quickly sets up a fresh Next.js application named &lt;code&gt;syncleaf&lt;/code&gt;&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="nx"&gt;npx&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;latest&lt;/span&gt; &lt;span class="nx"&gt;syncleaf&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configuring Drizzle ORM and Environment Variables
&lt;/h2&gt;

&lt;p&gt;Proceed by installing Drizzle ORM, PostgreSQL, and dotenv with the command below in your project directory:&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="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;drizzle&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;orm&lt;/span&gt; &lt;span class="nx"&gt;postgres&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This step incorporates Drizzle ORM for handling database schemas, &lt;strong&gt;&lt;code&gt;postgres&lt;/code&gt;&lt;/strong&gt; for interacting with the PostgreSQL database, and &lt;strong&gt;&lt;code&gt;dotenv&lt;/code&gt;&lt;/strong&gt; for environment variable management, all crucial for a secure and efficient database connection.&lt;/p&gt;

&lt;p&gt;Following this, enhance your development workflow by adding Drizzle Kit as a development dependency:&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="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt; &lt;span class="nx"&gt;drizzle&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;kit&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;D&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of Drizzle Kit as a magic tool that helps you build and change your database, kind of like building with LEGOs. You tell it how you want your database to look using a special code, and it creates a set of instructions to make or change the database just like that. If you decide to change how your database should look, Drizzle Kit figures out what new instructions are needed and keeps everything organized and safe, so you can always go back and see what changes you made. Plus, you can work on different parts of your database in separate pieces or even work on many databases at once. And if you already have a database, Drizzle Kit can quickly understand how it's built and help you make changes to it super fast!&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Setting Up Your Supabase Project&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Initiate your Supabase project setup by first logging in at &lt;a href="https://app.supabase.io/"&gt;Supabase Login&lt;/a&gt;. Once logged in, select "New Project" and name it "Syncleaf." It's essential to generate and save a secure database password for later use. Choose the server region that offers the best performance for your target audience. After filling in all the required fields, click "Create new project." Securely store the database password as you will need it for your &lt;code&gt;.env&lt;/code&gt; file to establish a database connection.&lt;/p&gt;

&lt;p&gt;For a visual guide, refer to the image provided below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7ewbxm9k1k9bj1ry5bm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb7ewbxm9k1k9bj1ry5bm.png" alt="Supabase" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating your project, you'll be taken to a screen displaying all necessary API keys and configuration details, including your project URL, anon key for client interactions, and service role key for backend operations. These are crucial for connecting your Next.js app securely with Supabase, so make sure to accurately copy them into your &lt;code&gt;.env&lt;/code&gt; file for future use.&lt;/p&gt;




&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F29t96d6hgoeivac580o6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F29t96d6hgoeivac580o6.png" alt="Supabase_main" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Configure Environment Variables&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Create a &lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt; file at the root of your project to securely store your database credentials. These values are provided by Supabase as highlighted above :&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="nx"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nx"&gt;NEXT_PUBLIC_SUPABASE_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nx"&gt;NEXT_PUBLIC_SUPABASE_ANON_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nx"&gt;SERVICE_ROLE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;
&lt;span class="nx"&gt;PW&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Drizzle Configuration Setup&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;drizzle.config.ts&lt;/code&gt; file at the root of your project to configure Drizzle ORM's interaction with your database. &lt;/p&gt;

&lt;p&gt;Here is the content for the configuration 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;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Config&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="s1"&gt;drizzle-kit&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.env&lt;/span&gt;&lt;span class="dl"&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;🔴 Cannot find database url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/lib/supabase/schema.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./migrations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;driver&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;dbCredentials&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt; &lt;span class="o"&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="nx"&gt;satisfies&lt;/span&gt; &lt;span class="nx"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration file serves as a map for Drizzle ORM, pointing it to the location of your database schema files, where to store migration files, and which database driver to use. It also securely pulls in the database connection string from your &lt;strong&gt;&lt;code&gt;.env&lt;/code&gt;&lt;/strong&gt; file. This setup is essential for enabling Drizzle ORM to manage your database schema and migrations effectively.&lt;/p&gt;

&lt;p&gt;Following the structure outlined in our &lt;strong&gt;&lt;code&gt;drizzle.config.ts&lt;/code&gt;&lt;/strong&gt; configuration, let's proceed to create the files and directories:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Defining the Database Schema&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For schema definition, place a &lt;strong&gt;&lt;code&gt;schema.ts&lt;/code&gt;&lt;/strong&gt; file within the &lt;strong&gt;&lt;code&gt;src/lib/supabase/&lt;/code&gt;&lt;/strong&gt; directory. To set up this file and its required directory structure, execute the command:&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="nx"&gt;mkdir&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;touch&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;strong&gt;&lt;code&gt;schema.ts&lt;/code&gt;&lt;/strong&gt; file is used to define and export data models that closely represent the structure of your database tables. These models facilitate type-safe database operations, ensuring that the data types used in your application match those in your database. This approach significantly enhances development efficiency by enabling autocompletion, reducing runtime errors, and making the codebase easier to understand and maintain.&lt;/p&gt;

&lt;p&gt;Add this to it:&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;pgTable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;timestamp&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;drizzle-orm/pg-core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pgTable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;product&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="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;uuid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultRandom&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;primaryKey&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;notNull&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&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="na"&gt;precision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;scale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; 
    &lt;span class="na"&gt;quantity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;integer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;quantity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="na"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;created_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultNow&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;updated_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;updated_at&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;defaultNow&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;This code snippet employs &lt;code&gt;drizzle-orm/pg-core&lt;/code&gt; to create a &lt;code&gt;product&lt;/code&gt; table model for PostgreSQL integration with Supabase, ensuring operations adhere to specified data types and schema constraints. This method enhances the reliability and scalability of your application's data layer without detailing individual fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Database Connection and Utility Functions
&lt;/h2&gt;

&lt;p&gt;Continuing with our setup, we'll now add a &lt;strong&gt;&lt;code&gt;db.ts&lt;/code&gt;&lt;/strong&gt; file to the &lt;strong&gt;&lt;code&gt;src/lib/supabase&lt;/code&gt;&lt;/strong&gt; directory, crucial for our database connection and utility functions. This step simplifies database interactions, improving maintainability and scalability.&lt;/p&gt;

&lt;p&gt;To create the &lt;strong&gt;&lt;code&gt;db.ts&lt;/code&gt;&lt;/strong&gt; 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="nx"&gt;touch&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prepares us to define our connection and utilities.&lt;/p&gt;

&lt;p&gt;Add the following content to the &lt;strong&gt;&lt;code&gt;db.ts&lt;/code&gt;&lt;/strong&gt; file to set up your database connection and utilities:&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;drizzle&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="s1"&gt;drizzle-orm/postgres-js&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;postgres&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;postgres&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;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&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="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../../migrations/schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;❌ Error: Database URL is not specified in the environment variables.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;postgres&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;max&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;drizzle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Database connection successfully established.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This script sets up the database connection using &lt;strong&gt;&lt;code&gt;drizzle-ORM&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;&lt;code&gt;postgres&lt;/code&gt;&lt;/strong&gt;, with configurations managed via environment variables. It ensures the &lt;strong&gt;&lt;code&gt;DATABASE_URL&lt;/code&gt;&lt;/strong&gt; is available, initializes the connection, and indicates a successful setup. The &lt;strong&gt;&lt;code&gt;drizzle&lt;/code&gt;&lt;/strong&gt; client is then made available for application-wide usage.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Enhancing Database Management with Drizzle Scripts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To efficiently manage and interact with your database using Drizzle, add the following scripts to your &lt;strong&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/strong&gt;. These scripts provide convenient commands for database operations such as schema synchronization, introspection, generation, migration, and seeding:&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;push&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;drizzle-kit push:pg&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;pull&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;drizzle-kit introspect:pg&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;generate&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;drizzle-kit generate:pg&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;drop&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;drizzle-kit drop&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;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;drizzle-kit check:pg&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;up&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;drizzle-kit up:pg&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;migrate&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;npx tsx scripts/migrations/migration.ts&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;studio&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;drizzle-kit studio&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;seed&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;npx tsx scripts/seed.ts&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;These scripts simplify the process of keeping your database schema in sync with your codebase, managing migrations, and seeding data for development and testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Generating Migration Files for PostgreSQL with Drizzle&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Execute the &lt;strong&gt;&lt;code&gt;npm run generate&lt;/code&gt;&lt;/strong&gt; command to initiate migration file creation:&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="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="nx"&gt;generate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running &lt;strong&gt;&lt;code&gt;npm run generate&lt;/code&gt;&lt;/strong&gt; triggers &lt;strong&gt;&lt;code&gt;drizzle-kit generate:pg&lt;/code&gt;&lt;/strong&gt;, analyzing your PostgreSQL schema and auto-generating a migration file for streamlined schema management. Following this command, a &lt;strong&gt;&lt;code&gt;migrations&lt;/code&gt;&lt;/strong&gt; folder will be created at the root of your project, as directed by the &lt;strong&gt;&lt;code&gt;out: './migrations'&lt;/code&gt;&lt;/strong&gt; setting in &lt;strong&gt;&lt;code&gt;drizzle.config.ts&lt;/code&gt;&lt;/strong&gt;, ensuring an organized approach to tracking database schema changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Setting Up the Migration Script&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To organize your project's migration scripts, first create a &lt;code&gt;scripts&lt;/code&gt; folder at the root of your project directory, then add a &lt;code&gt;migrations&lt;/code&gt; folder within it, and finally create a &lt;code&gt;migration.ts&lt;/code&gt; file inside this folder. Use the following command to set up this structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; scripts/migrations &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;touch &lt;/span&gt;scripts/migrations/migration.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command ensures the necessary directories and files are created in your project, ready for you to add your migration logic.&lt;/p&gt;

&lt;p&gt;Add the following content to your &lt;code&gt;migration.ts&lt;/code&gt; file to handle database migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../../src/lib/supabase/db&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;migrate&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="s1"&gt;drizzle-orm/postgres-js/migrator&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;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&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;migrateDatabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;🚀 Starting database migration...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;migrate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;migrationsFolder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;migrations&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;✅ Successfully completed the database migration.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;❌ Error during the database migration:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

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

&lt;/div&gt;



&lt;p&gt;This script initializes the environment variables, then defines and executes a function to migrate the database using &lt;code&gt;drizzle-ORM&lt;/code&gt;. It logs the start and successful completion of the migration process or catches and logs any errors encountered, ensuring a clear status update during the migration process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Executing the Migration Script
&lt;/h2&gt;

&lt;p&gt;To execute the migration script and apply your database changes, run the following command:&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="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="nx"&gt;migrate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Upon successful execution, you'll notice new files within the &lt;strong&gt;&lt;code&gt;migrations&lt;/code&gt;&lt;/strong&gt; folder, indicating that the migration scripts have been generated and run. Additionally, by checking your Supabase database, you should find the &lt;strong&gt;&lt;code&gt;products&lt;/code&gt;&lt;/strong&gt; table created, complete with all the fields you've previously defined.&lt;/p&gt;

&lt;p&gt;For a more interactive view of your database schema and to manage your data directly, use the command:&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="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;run&lt;/span&gt; &lt;span class="nx"&gt;studio&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will launch Drizzle-Kit Studio, utilizing your project's Drizzle configuration file to connect to your database. Drizzle Studio provides a user-friendly interface for browsing your database, as well as adding, deleting, and updating entries according to your defined Drizzle SQL schema.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Populating the Products Table with Seed Data&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With the products table in place, it's time to populate it with some sample data. To achieve this, we'll utilize the &lt;strong&gt;&lt;code&gt;faker&lt;/code&gt;&lt;/strong&gt; library to generate realistic product information seamlessly. This approach not only simplifies the process of creating diverse data sets but also enhances the testing and development experience by providing a rich dataset to work with.&lt;/p&gt;

&lt;p&gt;Ensure &lt;strong&gt;&lt;code&gt;faker&lt;/code&gt;&lt;/strong&gt; is installed in your project by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @faker-js/faker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, create the &lt;strong&gt;&lt;code&gt;seed.ts&lt;/code&gt;&lt;/strong&gt; file by executing the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;touch &lt;/span&gt;scripts/seed.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, add the following contents to your &lt;strong&gt;&lt;code&gt;seed.ts&lt;/code&gt;&lt;/strong&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;import &lt;span class="o"&gt;{&lt;/span&gt; drizzle &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'drizzle-orm/node-postgres'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; Pool &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'pg'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="o"&gt;{&lt;/span&gt; product &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'../src/lib/supabase/schema'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
import &lt;span class="o"&gt;{&lt;/span&gt; faker &lt;span class="o"&gt;}&lt;/span&gt; from &lt;span class="s1"&gt;'@faker-js/faker'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
import &lt;span class="k"&gt;*&lt;/span&gt; as dotenv from &lt;span class="s1"&gt;'dotenv'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

dotenv.config&lt;span class="o"&gt;({&lt;/span&gt; path: &lt;span class="s1"&gt;'./.env'&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;process.env.DATABASE_URL&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    console.error&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'DATABASE_URL not found in .env'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    process.exit&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

const main &lt;span class="o"&gt;=&lt;/span&gt; async &lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    const pool &lt;span class="o"&gt;=&lt;/span&gt; new Pool&lt;span class="o"&gt;({&lt;/span&gt;
        connectionString: process.env.DATABASE_URL,
    &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    const db &lt;span class="o"&gt;=&lt;/span&gt; drizzle&lt;span class="o"&gt;(&lt;/span&gt;pool&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    const productsData &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;let &lt;/span&gt;i &lt;span class="o"&gt;=&lt;/span&gt; 0&lt;span class="p"&gt;;&lt;/span&gt; i &amp;lt; 20&lt;span class="p"&gt;;&lt;/span&gt; i++&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        productsData.push&lt;span class="o"&gt;({&lt;/span&gt;
            name: faker.commerce.productName&lt;span class="o"&gt;()&lt;/span&gt;,
            description: faker.commerce.productDescription&lt;span class="o"&gt;()&lt;/span&gt;,
            price: faker.commerce.price&lt;span class="o"&gt;({&lt;/span&gt; min: 100, max: 1000, dec: 2, symbol: &lt;span class="s1"&gt;''&lt;/span&gt; &lt;span class="o"&gt;})&lt;/span&gt;, 
            quantity: faker.number.int&lt;span class="o"&gt;({&lt;/span&gt; min: 1, max: 100 &lt;span class="o"&gt;})&lt;/span&gt;, 
            image: faker.image.url&lt;span class="o"&gt;()&lt;/span&gt;, 
        &lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    console.log&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Seed start'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    await db.insert&lt;span class="o"&gt;(&lt;/span&gt;product&lt;span class="o"&gt;)&lt;/span&gt;.values&lt;span class="o"&gt;(&lt;/span&gt;productsData&lt;span class="o"&gt;)&lt;/span&gt;.execute&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    console.log&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Seed done'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    await pool.end&lt;span class="o"&gt;()&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

main&lt;span class="o"&gt;()&lt;/span&gt;.catch&lt;span class="o"&gt;((&lt;/span&gt;error&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    console.error&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Failed to seed products:'&lt;/span&gt;, error&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    process.exit&lt;span class="o"&gt;(&lt;/span&gt;1&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;})&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;To populate your database with 20 unique product entries, execute the command &lt;code&gt;npm run seed&lt;/code&gt;. This command triggers a script that connects to your database, generates product entries using faker, and inserts them into the products table, creating a foundational dataset for development and testing.&lt;/p&gt;

&lt;p&gt;After running &lt;code&gt;npm run seed&lt;/code&gt;, review your Supabase database or drizzle-kit studio to confirm the successful population of product entries, as shown in the provided screenshot. This confirms the success of your migration and seeding efforts, setting the stage for application development.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbfirnurg7h6jikxse74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjbfirnurg7h6jikxse74.png" alt="drizzle_studio" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Wrapping Up&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In conclusion, leveraging Drizzle ORM has empowered us to streamline database population, schema evolution, and data manipulation seamlessly. This efficiency has greatly expedited our development journey, furnishing us with a sturdy groundwork for constructing and expanding our application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GitHub Repository - &lt;a href="https://github.com/musebe/Drizzle-supabase"&gt;https://github.com/musebe/Drizzle-supabase&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Deployed Demo - &lt;a href="https://drizzle-supabase.vercel.app/"&gt;https://drizzle-supabase.vercel.app/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Supabase - &lt;a href="https://supabase.io/"&gt;https://supabase.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Drizzle ORM Documentation - &lt;a href="https://orm.drizzle.team/"&gt;https://orm.drizzle.team/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Drizzle ORM Kit Documentation - &lt;a href="https://orm.drizzle.team/kit-docs/overview"&gt;https://orm.drizzle.team/kit-docs/overview&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>ClerkDocs for VSCode: Essential Snippets for Clerk Components</title>
      <dc:creator>eugene musebe</dc:creator>
      <pubDate>Fri, 18 Aug 2023 12:05:39 +0000</pubDate>
      <link>https://dev.to/musebe/clerkdocs-for-vscode-essential-snippets-for-clerk-components-ho1</link>
      <guid>https://dev.to/musebe/clerkdocs-for-vscode-essential-snippets-for-clerk-components-ho1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Introducing the &lt;a href="https://marketplace.visualstudio.com/items?itemName=Musebe.clerkdocs-snippets"&gt;ClerkDocs&lt;/a&gt; VSCode Extension: Your essential toolkit for Next.js development. Dive into a curated collection of snippets tailored for Clerk components, optimized for both JavaScript and TypeScript environments. With the debut of version 1.0.0 focusing on Next.js, we're gearing up to roll out support for additional language SDKs in the near future. Boost your productivity and elevate your coding experience with ClerkDocs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why ClerkDocs is Essential
&lt;/h2&gt;

&lt;p&gt;ClerkDocs offers developers a set of snippets for easy integration of Clerk components into Next.js applications. This tool streamlines the development process, allowing for faster and error-free setups. By simplifying the integration, developers can concentrate on crafting robust Next.js applications with advanced user management. From authentication to user profiles, ClerkDocs provides quick access to dependable snippets, minimizing development time and potential mistakes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Snippet Collection&lt;/strong&gt;: A diverse range of snippets tailored for Clerk components.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Ease of Use&lt;/strong&gt;: Intuitive design for quick integration into Next.js projects.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Compatibility&lt;/strong&gt;: Optimized for Next.js(js/ts) with plans for broader SDK support in future updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation Guide
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; Open your VSCode and head to the extensions store.&lt;/li&gt;
&lt;li&gt; Search for "ClerkDocs" to locate the extension.&lt;/li&gt;
&lt;li&gt; Click on "Install" to add it to your VSCode.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Alternatively, you can directly download it from the &lt;a href="https://marketplace.visualstudio.com/items?itemName=Musebe.clerkdocs-snippets"&gt;VSCode Marketplace&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Snippets Overview
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/hackit-africa/image/upload/v1692367937/clerkdocs.pdf"&gt;Download the PDF version of Clerk Snippets for Next.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This table provides a comprehensive overview of the Clerk snippets available for Next.js.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;No&lt;/th&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;clerkImport&lt;/td&gt;
&lt;td&gt;Snippet for Clerk import with cursor placement for components&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;clerkUp&lt;/td&gt;
&lt;td&gt;Snippet for Clerk SignUp page in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;clerkIn&lt;/td&gt;
&lt;td&gt;Snippet for Clerk SignIn page in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;clerkOutBtn&lt;/td&gt;
&lt;td&gt;Snippet for Clerk SignOutButton in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;clerkUserBtn&lt;/td&gt;
&lt;td&gt;Snippet for Clerk UserButton in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;clerkUserProfile&lt;/td&gt;
&lt;td&gt;Snippet for Clerk UserProfile in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;clerkOrgP&lt;/td&gt;
&lt;td&gt;Snippet for Clerk OrganizationProfile in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;clerkOrgC&lt;/td&gt;
&lt;td&gt;Snippet for Clerk CreateOrganization in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;clerkOrgS&lt;/td&gt;
&lt;td&gt;Snippet for Clerk OrganizationSwitcher in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;clerkMiddleware&lt;/td&gt;
&lt;td&gt;Snippet for Clerk middleware setup in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;clerkEnv&lt;/td&gt;
&lt;td&gt;Snippet for Clerk environment variables in Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;clerkAuth&lt;/td&gt;
&lt;td&gt;Snippet for using the auth() helper function with Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;clerkCurrentUser&lt;/td&gt;
&lt;td&gt;Snippet for fetching the current user using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;clerkGetAuthAPI&lt;/td&gt;
&lt;td&gt;Snippet for using the getAuth() helper with Clerk in a Next.js API route.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;clerkClientAPI&lt;/td&gt;
&lt;td&gt;Snippet for using the &lt;code&gt;clerkClient&lt;/code&gt; helper with Clerk in a Next.js API route.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;clerkUseAuth&lt;/td&gt;
&lt;td&gt;Snippet for using the &lt;code&gt;useAuth&lt;/code&gt; hook with Clerk in a Next.js application.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;clerkUseUser&lt;/td&gt;
&lt;td&gt;Snippet for using the &lt;code&gt;useUser&lt;/code&gt; hook with Clerk in a Next.js application.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;clerkProvider&lt;/td&gt;
&lt;td&gt;Snippet for using the &lt;code&gt;&amp;lt;ClerkProvider&amp;gt;&lt;/code&gt; component with Clerk in a Next.js application.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;clerkUseOrg&lt;/td&gt;
&lt;td&gt;Snippet for accessing the current active organization's attributes using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;clerkUseOrgList&lt;/td&gt;
&lt;td&gt;Snippet for accessing the list of available Organizations and OrganizationMemberships the user belongs to using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;clerkUserList&lt;/td&gt;
&lt;td&gt;Snippet for retrieving a list of users using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;clerkUserListOrd&lt;/td&gt;
&lt;td&gt;Snippet for retrieving an ordered and filtered list of users using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;clerkGetUser&lt;/td&gt;
&lt;td&gt;Snippet for retrieving a single user by their ID using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;clerkGetUserCount&lt;/td&gt;
&lt;td&gt;Snippet for retrieving the total number of users or the total number of users matching a specific query using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;clerkUpdateUser&lt;/td&gt;
&lt;td&gt;Snippet for updating a user with a given ID and provided attribute values using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;26&lt;/td&gt;
&lt;td&gt;clerkDeleteUser&lt;/td&gt;
&lt;td&gt;Snippet for deleting a user with a given ID using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;27&lt;/td&gt;
&lt;td&gt;clerkCreateOrg&lt;/td&gt;
&lt;td&gt;Snippet for creating an organization using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;clerkCreateOrgInv&lt;/td&gt;
&lt;td&gt;Snippet for creating an organization invitation using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;29&lt;/td&gt;
&lt;td&gt;clerkCreateOrgMem&lt;/td&gt;
&lt;td&gt;Snippet for creating an organization member using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;clerkDeleteOrg&lt;/td&gt;
&lt;td&gt;Snippet for deleting an organization using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;31&lt;/td&gt;
&lt;td&gt;clerkDeleteOrgMem&lt;/td&gt;
&lt;td&gt;Snippet for deleting an organization member using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;clerkGetOrg&lt;/td&gt;
&lt;td&gt;Snippet for retrieving an organization using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;33&lt;/td&gt;
&lt;td&gt;clerkGetOrgList&lt;/td&gt;
&lt;td&gt;Snippet for retrieving a list of organizations using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;34&lt;/td&gt;
&lt;td&gt;clerkGetOrgMemList&lt;/td&gt;
&lt;td&gt;Snippet for retrieving a list of organization members using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;35&lt;/td&gt;
&lt;td&gt;clerkGetPendOrgInv&lt;/td&gt;
&lt;td&gt;Snippet for retrieving a list of pending organization invites using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;36&lt;/td&gt;
&lt;td&gt;clerkRevokeOrgInv&lt;/td&gt;
&lt;td&gt;Snippet for revoking an organization invite using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;td&gt;clerkUpdateOrg&lt;/td&gt;
&lt;td&gt;Snippet for updating an organization using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;38&lt;/td&gt;
&lt;td&gt;clerkUpdateOrgMeta&lt;/td&gt;
&lt;td&gt;Snippet for updating organization metadata using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;39&lt;/td&gt;
&lt;td&gt;clerkUpOrgMemMeta&lt;/td&gt;
&lt;td&gt;Snippet for updating organization member metadata using Clerk in Next.js.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Your Input Matters!
&lt;/h3&gt;

&lt;p&gt;Your experience with ClerkDocs matters to me. I encourage you to share your thoughts, suggestions, and any feedback you might have regarding the extension. Your insights will help me refine and enhance ClerkDocs for an even better user experience.&lt;/p&gt;

&lt;p&gt;If you encounter any issues or have specific recommendations, please don't hesitate to &lt;a href="https://github.com/musebe/clerk-vscode-snippets/issues"&gt;open an issue on our GitHub repository&lt;/a&gt;. Your active participation will greatly contribute to the continuous improvement of ClerkDocs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open-Source Contributions
&lt;/h3&gt;

&lt;p&gt;I'm proud to share that ClerkDocs is an open-source project. If you're a developer eager to contribute, I wholeheartedly welcome your expertise! Whether you're looking to improve existing features, suggest new ones, or report bugs, your input is invaluable. Dive into the code, make enhancements, or simply share your innovative ideas. Together, we can make ClerkDocs the ultimate extension for Clerk components in Next.js.&lt;/p&gt;

&lt;p&gt;For those interested in contributing or exploring the codebase, you can find the project on &lt;a href="https://github.com/musebe/clerk-vscode-snippets"&gt;GitHub &lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Links and Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=Musebe.clerkdocs-snippets"&gt;ClerkDocs on VSCode Marketplace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/musebe/clerk-vscode-snippets"&gt;ClerkDocs GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://clerk.com/docs"&gt;Clerk Official Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/"&gt;Next.js Official Website&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>clerk</category>
      <category>snippets</category>
      <category>vscode</category>
      <category>authentication</category>
    </item>
    <item>
      <title>Implementing Role-Based Access Control in Next.js App Router using Clerk Organizations</title>
      <dc:creator>eugene musebe</dc:creator>
      <pubDate>Mon, 31 Jul 2023 18:52:21 +0000</pubDate>
      <link>https://dev.to/musebe/implementing-role-based-access-control-in-nextjs-app-router-using-clerk-organizations-566g</link>
      <guid>https://dev.to/musebe/implementing-role-based-access-control-in-nextjs-app-router-using-clerk-organizations-566g</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;It is crucial to protect user data and control access to various application features in the dynamic world of web development. RBAC, or role-based access control, has become a well-liked and successful method of controlling permissions within web applications. RBAC enables developers to design a customised and secure user experience by assigning specific roles to users and defining their access rights in accordance with those roles. In this article, we'll examine how RBAC is implemented in the Next.js App Router using Clerk, a cutting-edge platform for user management and authentication.&lt;/p&gt;

&lt;p&gt;We will look at how &lt;a href="https://clerk.com" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; uses &lt;a href="https://clerk.com/docs/organizations/overview" rel="noopener noreferrer"&gt;Organizations&lt;/a&gt; to simplify user authentication and role assignment, thereby streamlining RBAC integration into Next.js applications. Following this comprehensive guide will equip developers to build web applications that prioritise security and provide a tailored experience to each user based on their assigned role.&lt;/p&gt;

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

&lt;p&gt;Make sure you have the following prerequisites in place before implementing Role-Based Access Control in the app using Next.js and Clerk:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fundamentals of web development (HTML, CSS, and JavaScript).&lt;/li&gt;
&lt;li&gt;Basic understanding of React/Next.js.&lt;/li&gt;
&lt;li&gt;Node.js and npm must be installed.&lt;/li&gt;
&lt;li&gt;A code editor (Visual Studio Code).&lt;/li&gt;
&lt;li&gt;Git for version control -  optional.&lt;/li&gt;
&lt;li&gt;An account with &lt;a href="https://clerk.com" rel="noopener noreferrer"&gt;Clerk.com&lt;/a&gt; for authentication.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these prerequisites in place, you can use Clerk to implement Role-Based Access Control in your Next.js application. If you haven't met any of these requirements, take the time to do so before proceeding with the tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Github Repository and Live Demo
&lt;/h2&gt;

&lt;p&gt;You can access the source code of the application on GitHub at &lt;a href="https://github.com/musebe/nextjs-clerk-organizations-rbac-authentication" rel="noopener noreferrer"&gt;https://github.com/musebe/nextjs-clerk-organizations-rbac-authentication&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;To see the completed application in action, visit &lt;a href="https://nextjs-clerk-organizations-rbac-authentication.vercel.app" rel="noopener noreferrer"&gt;https://nextjs-clerk-organizations-rbac-authentication.vercel.app&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up Clerk and Clerk Organizations
&lt;/h2&gt;

&lt;p&gt;The first step in using Clerk is to create a Clerk account. You can do this by going to &lt;a href="https://clerk.com" rel="noopener noreferrer"&gt;clerk.com&lt;/a&gt; and creating a free account. You will be prompted to create a new application within your account after signing in. This application will serve as your starting point for exploring and utilising Clerk's various features and capabilities, which are highlighted below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688676392%2Fnew-setup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688676392%2Fnew-setup.png" title="Clerk Dashboard" alt="Clerk Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After signing in, click the 'Add application' button. Give your app a name and select all of the 'Social authentication' methods you want your users to use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688676948%2FApplication_name.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688676948%2FApplication_name.png" title="Clerk Dashboard" alt="Application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Clerk Organizations
&lt;/h3&gt;

&lt;p&gt;Now, it's time to create an organization. In Clerk, organizations serve as shared accounts, enabling collaboration among members across shared resources. Within an organization, there are members with elevated privileges, responsible for managing access to the organization's data and resources. These privileged members have the authority to grant or revoke permissions, ensuring seamless cooperation and secure control over the organization's assets.&lt;/p&gt;

&lt;p&gt;To create an organization in Clerk after logging in and being on the home dashboard, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Click on the "Create Organization" button, and a new form or modal will appear, prompting you to provide the necessary information for the organization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fill in the required details for the organization, such as the organization name, logo, and any other relevant information.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on the &lt;code&gt;Create&lt;/code&gt; button to finalize the creation of the organization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clerk will then create the organization, and you will be redirected to the newly created organization's dashboard.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1690759651%2Fcreate-org.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1690759651%2Fcreate-org.png" alt="Organizations Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding members to an Organization
&lt;/h3&gt;

&lt;p&gt;To add members to the Clerk organization, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Navigate to the &lt;code&gt;Members&lt;/code&gt; section: After selecting the organization in Clerk's dashboard, navigate to the "Members" section, this is where user management is handled.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click on &lt;code&gt;Add Members&lt;/code&gt;: Look for the "Add Members" button within the "Members" section and click on it to initiate the process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A pop-up form will appear: Once you click on "Add Members," a pop-up window will show up on your screen, providing a form to input the necessary details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Search for the user: In the pop-up form, you can search for the specific user you want to add to the organization. Enter their email address or username in the search field.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choose a role: For each user you add, you can assign them a role within the organization. Clerk typically offers two roles: &lt;code&gt;admin&lt;/code&gt; and &lt;code&gt;basic_member&lt;/code&gt;. Select the appropriate role for the user based on their level of access and permissions.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;admin - The &lt;code&gt;admin&lt;/code&gt; role grants complete access to all organisational resources. Members with the admin role have administrator privileges and can fully manage organisations and memberships in organisations.

&lt;ul&gt;
&lt;li&gt;basic_member - The &lt;code&gt;basic_member&lt;/code&gt; role is the default role for an organization's users. The availability of organisational resources is restricted. Basic members cannot manage organisations or memberships in organisations, but they can view information about the organisation and its members.&lt;/li&gt;
&lt;li&gt; Click &lt;code&gt;Add&lt;/code&gt; : Once you have verified the details, click the "Add" or "Confirm" button to finalize the addition of the user to the organization with the specified role.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1690762184%2Fmembers.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1690762184%2Fmembers.png" alt="Add Member"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Congratulations! You have successfully created an organization in Clerk. From the organization dashboard, you can manage users, roles, and other resources associated with the organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js Setup
&lt;/h2&gt;

&lt;p&gt;Now to the fun part! Let's spin up a new Next.js project to get started with implementing Role-Based Access Control (RBAC). To do this, simply navigate to the directory of your choice and run the following command in your terminal or command prompt:&lt;/p&gt;

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

npx create-next-app my-rbac-app


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

&lt;/div&gt;

&lt;p&gt;Replace &lt;code&gt;my-rbac-app&lt;/code&gt; with your desired project name. This command will set up a new Next.js project for you with all the necessary configurations to begin building your RBAC-enabled web application.&lt;/p&gt;

&lt;p&gt;The best part is that starting from Next.js version 13, Tailwind CSS comes pre-configured by default, saving you the trouble of installing it separately. With Next.js and Tailwind CSS ready to go, you can now focus on integrating RBAC using Clerk into your freshly created Next.js project. So, let's get started and secure your web application with personalized user access and permissions!&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating Clerk with Next.js
&lt;/h2&gt;

&lt;p&gt;The next step after creating the Next.js project and having Tailwind CSS set up is to integrate Clerk into your application for handling user authentication and role-based access control. Follow these steps to proceed:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Install Clerk SDK: Use npm or yarn to install the Clerk SDK in your Next.js project. The Clerk SDK provides the necessary tools to authenticate users and manage roles. Run the following command in your project's root directory:&lt;/li&gt;
&lt;/ol&gt;

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

npm install @clerk/nextjs


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

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Initialize Clerk in your Next.js App: Import the Clerk SDK into your Next.js application and initialize it with your Clerk API credentials. This step enables your application to interact with Clerk's authentication services. In Next 13 using the app router, the initialization is done in the &lt;code&gt;layout.js&lt;/code&gt;  file as highlighted below : &lt;/li&gt;
&lt;/ol&gt;

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

// app/layout.js
import '@styles/globals.css';
import { ClerkProvider } from '@clerk/nextjs';


export const metadata = {
  title: 'Clerk-Organizations',
  description: 'Clerk Role-Based Authentication Using Organizations',
};

export default function RootLayout({ children }) {
  return (
    &amp;lt;ClerkProvider&amp;gt;
      &amp;lt;html lang='en'&amp;gt;
        &amp;lt;body&amp;gt;
          &amp;lt;div className='main'&amp;gt;
            &amp;lt;div className='gradient' /&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;main className='app'&amp;gt;
            {children}
          &amp;lt;/main&amp;gt;
        &amp;lt;/body&amp;gt;
      &amp;lt;/html&amp;gt;
    &amp;lt;/ClerkProvider&amp;gt;
  );
}



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

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Obtain Clerk API Credentials: To initialize the Clerk SDK, you'll need API credentials specific to your Clerk organization. Retrieve these credentials from the Clerk dashboard on the left sidebar under the &lt;code&gt;API Keys&lt;/code&gt; tab. Copy the keys and paste them in the &lt;code&gt;.env&lt;/code&gt; file we are going to create .&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688677690%2FAPI-Keys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688677690%2FAPI-Keys.png" title="Clerk Dashboard" alt="Api_Keys"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In your Next.js project's root directory, generate a new file named &lt;code&gt;.env.local&lt;/code&gt;. Once created, paste the &lt;code&gt;CLERK_PUBLISHABLE_KEY&lt;/code&gt; and &lt;code&gt;CLERK_SECRET_KEY&lt;/code&gt; environment variables that you previously copied from the Clerk dashboard into this &lt;code&gt;.env.local&lt;/code&gt; file. Storing these keys in the &lt;code&gt;.env.local&lt;/code&gt; file ensures that your sensitive credentials are securely accessible by your Next.js application during runtime, safeguarding them from being exposed in your codebase. Remember to refrain from sharing or committing the &lt;code&gt;.env.local&lt;/code&gt; file to version control to maintain the confidentiality of your environment variables.&lt;/li&gt;
&lt;/ol&gt;

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

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="&amp;lt;Your Publishable Key&amp;gt;"
CLERK_SECRET_KEY="&amp;lt;Your Clerk Secret Key&amp;gt;"


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

&lt;/div&gt;

&lt;p&gt;Having completed the setup and configurations as described above, it is now time to begin establishing the application layout in the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application Layout
&lt;/h2&gt;

&lt;p&gt;The next step is to create the application layout and pages. We will organize our pages using the folder-based approach provided by Next.js 13. Inside the &lt;code&gt;app&lt;/code&gt; directory, we shall create three separate folders named &lt;code&gt;Profile&lt;/code&gt;, &lt;code&gt;Users&lt;/code&gt;, and &lt;code&gt;Admin&lt;/code&gt;, each containing a &lt;code&gt;page.jsx&lt;/code&gt; file. These files will serve as the components for our respective pages. In the &lt;code&gt;Profile&lt;/code&gt; page, we will provide users with personalized information and options to manage their accounts. The &lt;code&gt;Users&lt;/code&gt; page will display general user-related data and interactions. Lastly, the &lt;code&gt;Admin&lt;/code&gt; page will serve as a dashboard for administrators, granting them access to oversee and control various aspects of the application. This organized structure will enhance code maintainability and make it easier to extend our Next.js app as it grows in functionality.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;app&lt;/code&gt; directory, create three separate folders for each page: &lt;code&gt;Profile&lt;/code&gt;, &lt;code&gt;Users&lt;/code&gt;, and &lt;code&gt;Admin&lt;/code&gt;. Within each folder, create a &lt;code&gt;page.jsx&lt;/code&gt; file with the content for each page.&lt;/p&gt;

&lt;p&gt;Here's how you directory structure should look like :&lt;/p&gt;

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

- your-nextjs-app
  - app
    - profile
      - page.jsx
    - users
      - page.jsx
    - admin
      - page.jsx



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

&lt;/div&gt;

&lt;p&gt;Now, let's update the content of each &lt;code&gt;page.jsx&lt;/code&gt; file accordingly:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;code&gt;Profile/page.jsx&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

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

const Profile = () =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Welcome to the Profile Page!&amp;lt;/h1&amp;gt;
      {/* Add any content or components specific to the Profile page here */}
    &amp;lt;/div&amp;gt;
  );
};

export default Profile;



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

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Users/page.jsx&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

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

const Users = () =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Welcome to the Users Page!&amp;lt;/h1&amp;gt;
      {/* Add any content or components specific to the Users page here */}
    &amp;lt;/div&amp;gt;
  );
};

export default Users;



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

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Admin/page.jsx&lt;/code&gt;:&lt;/li&gt;
&lt;/ol&gt;

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

const Admin = () =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Welcome to the Admin Page!&amp;lt;/h1&amp;gt;
      {/* Add any content or components specific to the Admin page here */}
    &amp;lt;/div&amp;gt;
  );
};

export default Admin;



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

&lt;/div&gt;

&lt;p&gt;Now, the pages will be accessible using the following URLs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Profile: &lt;code&gt;http://localhost:3000/profile&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Users: &lt;code&gt;http://localhost:3000/users&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;  Admin: &lt;code&gt;http://localhost:3000/admin&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This organized approach will ensure a clear separation of concerns and make it easier to manage and scale your Next.js app.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navbar
&lt;/h3&gt;

&lt;p&gt;Onto the Navbar! Let's begin by creating a &lt;code&gt;components&lt;/code&gt; folder at the root of your Next.js app. Inside this new folder, we will place a file named &lt;code&gt;Navbar.jsx&lt;/code&gt; to contain our Navbar component. This step will help us organize and manage reusable components more efficiently.&lt;/p&gt;

&lt;p&gt;Here's what the folder structure will look like after completing this step:&lt;/p&gt;

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

- your-nextjs-app
  - components
    - Navbar.jsx
  - app
    - Profile
      - page.jsx
    - Users
      - page.jsx
    - Admin
      - page.jsx
  - pages
    ... other pages if any ...



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

&lt;/div&gt;

&lt;p&gt;Once the &lt;code&gt;components&lt;/code&gt; folder is created, paste the content below into the new &lt;code&gt;Navbar.jsx&lt;/code&gt; file located inside the &lt;code&gt;components&lt;/code&gt; folder.&lt;/p&gt;

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

import Link from 'next/link';

const Navbar = () =&amp;gt; {
  const links = [
    { title: 'Profile', url: '/profile' },
    { title: 'Dashboard', url: '/user' },
    { title: 'Admin Dashboard', url: '/admin', role: 'admin' },
    // Add more placeholder links as needed
  ];

  return (
    &amp;lt;header className='text-gray-600 body-font bg-white shadow'&amp;gt;
      &amp;lt;div className='container mx-auto flex flex-wrap p-5 flex-col md:flex-row items-center justify-between'&amp;gt;
        &amp;lt;div className='flex items-center'&amp;gt;
          &amp;lt;a
            href='/'
            className='flex title-font font-medium items-center text-gray-900'
          &amp;gt;
            &amp;lt;svg
              xmlns='http://www.w3.org/2000/svg'
              fill='none'
              stroke='currentColor'
              strokeLinecap='round'
              strokeLinejoin='round'
              strokeWidth='2'
              className='w-10 h-10 text-white p-2 bg-indigo-500 rounded-full'
              viewBox='0 0 24 24'
            &amp;gt;
              &amp;lt;path d='M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5'&amp;gt;&amp;lt;/path&amp;gt;
            &amp;lt;/svg&amp;gt;
            &amp;lt;span className='ml-3 text-xl'&amp;gt;SecureClerk&amp;lt;/span&amp;gt;
          &amp;lt;/a&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;nav className='md:ml-auto md:mr-auto flex flex-wrap items-center text-base justify-center'&amp;gt;
          &amp;lt;Link href='/profile'&amp;gt;
            &amp;lt;div className='mr-5 cursor-pointer hover:text-gray-900'&amp;gt;
              Profile
            &amp;lt;/div&amp;gt;
          &amp;lt;/Link&amp;gt;
          &amp;lt;Link href='/user'&amp;gt;
            &amp;lt;div className='mr-5 cursor-pointer hover:text-gray-900'&amp;gt;
              Dashboard
            &amp;lt;/div&amp;gt;
          &amp;lt;/Link&amp;gt;
          &amp;lt;Link href='/admin'&amp;gt;
            &amp;lt;div className='mr-5 cursor-pointer hover:text-gray-900'&amp;gt;
              Admin Dashboard
            &amp;lt;/div&amp;gt;
          &amp;lt;/Link&amp;gt;
          {/* Add more links directly here as needed */}
        &amp;lt;/nav&amp;gt;
        &amp;lt;div className='md:flex items-center'&amp;gt;
          &amp;lt;a href='/sign-in'&amp;gt;
            &amp;lt;button className='text-white bg-indigo-500 border-0 py-2 px-4 focus:outline-none hover:bg-indigo-600 rounded text-base mr-4'&amp;gt;
              Login
            &amp;lt;/button&amp;gt;
          &amp;lt;/a&amp;gt;
          &amp;lt;a href='/sign-up'&amp;gt;
            &amp;lt;button className='text-white bg-indigo-500 border-0 py-2 px-4 focus:outline-none hover:bg-indigo-600 rounded text-base'&amp;gt;
              Sign Up
            &amp;lt;/button&amp;gt;
          &amp;lt;/a&amp;gt;
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/header&amp;gt;
  );
};

export default Navbar;



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

&lt;/div&gt;

&lt;p&gt;The next step is to modify the &lt;code&gt;Layout.js&lt;/code&gt; file to include the &lt;code&gt;Navbar&lt;/code&gt; component so that it can be used by the entire app. We'll import the &lt;code&gt;Navbar&lt;/code&gt; component into the &lt;code&gt;Layout.js&lt;/code&gt; file and render it within the layout structure. This way, the &lt;code&gt;Navbar&lt;/code&gt; will be present across all pages wrapped within the &lt;code&gt;RootLayout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's the updated &lt;code&gt;Layout.js&lt;/code&gt; file:&lt;/p&gt;

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

// app/Layout.js
import '@styles/globals.css';
import { ClerkProvider } from '@clerk/nextjs';
import Navbar from '../components/Navbar'; // Import the Navbar component

export const metadata = {
  title: 'Clerk-Organizations',
  description: 'Clerk Role-Based Authentication Using Organizations',
};

export default function RootLayout({ children }) {
  return (
    &amp;lt;ClerkProvider&amp;gt;
      &amp;lt;html lang='en'&amp;gt;
        &amp;lt;body&amp;gt;
          &amp;lt;div className='main'&amp;gt;
            &amp;lt;div className='gradient' /&amp;gt;
          &amp;lt;/div&amp;gt;
          &amp;lt;main className='app'&amp;gt;
            &amp;lt;Navbar /&amp;gt; {/* Include the Navbar component here */}
            {children}
          &amp;lt;/main&amp;gt;
        &amp;lt;/body&amp;gt;
      &amp;lt;/html&amp;gt;
    &amp;lt;/ClerkProvider&amp;gt;
  );
}



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

&lt;/div&gt;

&lt;p&gt;With this in place, the Navbar component provides a user-friendly navigation interface for our Next.js app. It includes links for "Profile," "Dashboard," and "Admin Dashboard," enabling seamless client-side navigation to the corresponding pages when clicked.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sign in and sign up Components
&lt;/h2&gt;

&lt;p&gt;Clerk offers a selection of pre-built components that seamlessly integrate sign-in, sign-up, and other user management features into your Next.js application. To leverage these functionalities, you can utilize the &lt;code&gt;&amp;lt;SignIn /&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;SignUp /&amp;gt;&lt;/code&gt; components along with Next.js' optional catch-all route.&lt;/p&gt;

&lt;p&gt;To implement this, within the "app" folder of your project, create two new directories named "sign-up" and "sign-in." Inside each directory, place the corresponding code for the sign-up and sign-in functionalities following this structure: &lt;code&gt;sign-up/[[...sign-up]]/page.jsx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Below, find the code for the Sign In and Sign Up components using the Clerk components provided by &lt;code&gt;@clerk/nextjs&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sign In Component:
&lt;/h3&gt;

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

// app/sign-in/[[...sign-in]]/page.tsx
import { SignIn } from '@clerk/nextjs';

const SignInPage = () =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Sign In&amp;lt;/h1&amp;gt;
      &amp;lt;SignIn /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default SignInPage;



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

&lt;/div&gt;
&lt;h3&gt;
  
  
  Sign Up Component:
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// app/sign-up/[[...sign-up]]/page.tsx
import { SignUp } from '@clerk/nextjs';

const SignUpPage = () =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Sign Up&amp;lt;/h1&amp;gt;
      &amp;lt;SignUp /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default SignUpPage;



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

&lt;/div&gt;

&lt;p&gt;After adding the two pages, the updated project directory structure will look like this:&lt;/p&gt;

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

- your-nextjs-app
  - components
    - Navbar.jsx
  - app
    - Profile
      - page.jsx
    - Users
      - page.jsx
    - Admin
      - page.jsx
    - sign-up
      - [[...sign-up]]
        - page.tsx
    - sign-in
      - [[...sign-in]]
        - page.tsx
  - pages
    ... other pages if any ...



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

&lt;/div&gt;

&lt;p&gt;With the setup completed, when you visit the route &lt;code&gt;http://localhost:3000/sign-in&lt;/code&gt;, you will be able to load Clerk's login page, as demonstrated below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688682376%2Fclerk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688682376%2Fclerk.png" alt="Application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Protecting your application routes
&lt;/h2&gt;

&lt;p&gt;It's time to decide which pages are public and which require authentication now that Clerk has been installed and mounted in your application. We achieve this by declaring the public and private routes in a file called &lt;code&gt;middleware.js&lt;/code&gt; at the project's root. In our situation, we only want the home page to be viewable by the general public and the remaining portions of the page to be hidden until the user logs into the application. The code below makes it possible to achieve this:&lt;/p&gt;

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

import { authMiddleware } from '@clerk/nextjs';

export default authMiddleware({
  publicRoutes: ["/"]
});

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};



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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Hero Component
&lt;/h2&gt;

&lt;p&gt;To finalize the layout, let's beautify the homepage by adding some content to it. We'll start by creating a &lt;code&gt;Hero.jsx&lt;/code&gt; page in the &lt;code&gt;components&lt;/code&gt; folder and then embed it into the &lt;code&gt;page.jsx&lt;/code&gt; file located inside the &lt;code&gt;app&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;This component will serve as the hero section of the homepage.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// components/Hero.jsx
const Hero = () =&amp;gt; {
  return (
    &amp;lt;div className="hero"&amp;gt;
      {/* Your hero content and layout here */}
      &amp;lt;h1&amp;gt;Welcome to Our Website&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;Discover amazing things with us!&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Hero;



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

&lt;/div&gt;

&lt;p&gt;Next, go to the &lt;code&gt;page.jsx&lt;/code&gt; file inside the &lt;code&gt;app&lt;/code&gt; directory and update it to include the &lt;code&gt;Hero&lt;/code&gt; component:&lt;/p&gt;

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

// app/page.jsx
import { Hero } from "@components";

export default function Home() {
  return (
    &amp;lt;main className='overflow-hidden'&amp;gt;
      &amp;lt;Hero /&amp;gt;
      {/* Other content and components for the Home page can be added here */}
    &amp;lt;/main&amp;gt;
  );
}



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

&lt;/div&gt;

&lt;p&gt;Now, with the &lt;code&gt;Hero&lt;/code&gt; component embedded in the &lt;code&gt;Home&lt;/code&gt; page, you have a beautiful hero section displayed at the top of the homepage. You can further enhance the layout by adding additional content and components to the &lt;code&gt;Home&lt;/code&gt; page as needed. This will create an engaging and visually appealing homepage for your Next.js app.&lt;/p&gt;

&lt;p&gt;Your Final project structure should look like this upto this point : &lt;/p&gt;

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

- your-nextjs-app
  - components
    - Hero.jsx
    - Navbar.jsx
  - app
    - profile
      - page.jsx
    - users
      - page.jsx
    - admin
      - page.jsx
    - sign-up
      - [[...sign-up]]
        - page.tsx
    - sign-in
      - [[...sign-in]]
        - page.jsx
    - layout.jsx
    - page.jsx
  - styles
    - globals.css
  - node_modules
  - public
    - favicon.ico
    ... other public files ...
  - package.json
  - next.config.js



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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Navbar links Conditional Rendering
&lt;/h2&gt;

&lt;p&gt;For conditional link rendering, we will utilize Clerk's &lt;code&gt;SignedOut&lt;/code&gt;, &lt;code&gt;UserButton&lt;/code&gt;, and &lt;code&gt;SignedIn&lt;/code&gt; components. When a user is not signed in, we will display only the "Login" and "Sign Up" buttons. However, once the user is logged in, we will show the navigation links alongside Clerk's &lt;code&gt;UserButton&lt;/code&gt; component, which facilitates the sign-out functionality. This approach enables us to dynamically adjust the content displayed in the Navbar based on the user's authentication status.&lt;/p&gt;

&lt;p&gt;To achieve this functionality, on the Navbar component, import the following components from Clerk's Next.js library:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

import { SignedOut, UserButton, SignedIn } from '@clerk/nextjs';


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

&lt;/div&gt;

&lt;p&gt;These components will allow you to conditionally render content based on the user's authentication status, enabling you to show different elements for signed-in and signed-out users in the Navbar.&lt;/p&gt;

&lt;p&gt;After logging in, it becomes necessary to verify the user's role, distinguishing between "admin" and "basic_member," and accordingly display the "Profile" and "Dashboard" links only for "basic_member," while showing all links for "admin." We can obtain this information using Clerk's &lt;code&gt;useSession&lt;/code&gt; hook, which allows access to the session status. To achieve this, simply include the &lt;code&gt;useSession&lt;/code&gt; hook within the Clerk object you previously imported. By doing so, you will be able to fetch the user's role from the session data and conditionally render the appropriate links in the Navbar.&lt;/p&gt;

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

import { SignedOut, UserButton, SignedIn, useSession } from '@clerk/nextjs';


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

&lt;/div&gt;

&lt;p&gt;To simplify the role-checking process, let's create a utility function that will iterate through the session data and return the user's role. To do this, create a new folder named &lt;code&gt;utils&lt;/code&gt; at the root of the project and add a file called &lt;code&gt;userUtils.js&lt;/code&gt; inside it. In &lt;code&gt;userUtils.js&lt;/code&gt;, implement the following function:&lt;/p&gt;

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

function checkUserRole(session) {
  if (
    !session ||
    !session.user ||
    !session.user.organizationMemberships ||
    session.user.organizationMemberships.length === 0
  ) {
    return null; // Return null if the user is not a basic member
  }

  const organizationMemberships = session.user.organizationMemberships;

  // Loop through all organization memberships
  for (const membership of organizationMemberships) {
    if (membership.role) {
      return membership.role.toLowerCase(); // Return the role in lowercase if it exists
    }
  }

  return null; // Return null if no role is found in the memberships
}

export { checkUserRole };



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

&lt;/div&gt;

&lt;p&gt;This function will allow us to extract and determine the user's role from the session data, making it easier to handle role-based actions in the application.&lt;/p&gt;

&lt;p&gt;The next step is to export the &lt;code&gt;checkUserRole&lt;/code&gt; function from the &lt;code&gt;userUtils.js&lt;/code&gt; file so that it can be used in the &lt;code&gt;Navbar&lt;/code&gt; component. To achieve this, use the following import statement in the &lt;code&gt;Navbar&lt;/code&gt; component:&lt;/p&gt;

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

import { checkUserRole } from '../utils/userUtils';


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

&lt;/div&gt;

&lt;p&gt;Inside the &lt;code&gt;Navbar&lt;/code&gt; component, we can determine the user's role from the session data as follows:&lt;/p&gt;

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

const { session } = useSession();
const userRole = checkUserRole(session);


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

&lt;/div&gt;

&lt;p&gt;By utilizing the &lt;code&gt;useSession&lt;/code&gt; hook from Clerk, we retrieve the user's session data. Then, we call the &lt;code&gt;checkUserRole&lt;/code&gt; function with the &lt;code&gt;session&lt;/code&gt; parameter, which enables us to obtain the user's role. This way, we can efficiently check the user's role within the &lt;code&gt;Navbar&lt;/code&gt; component and conditionally render the appropriate links based on the role information.&lt;/p&gt;

&lt;p&gt;After the user has signed in, we can utilize the &lt;code&gt;userRole&lt;/code&gt; information to determine which links should be displayed for administrators and basic members.&lt;/p&gt;

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

&amp;lt;SignedIn&amp;gt;
  {links.map((link) =&amp;gt;
    (link.role === 'admin' &amp;amp;&amp;amp; userRole === 'admin') || !link.role ? (
      &amp;lt;Link key={link.title} href={link.url}&amp;gt;
        {/* Use a div instead of an anchor tag */}
        &amp;lt;div className='mr-5 cursor-pointer hover:text-gray-900'&amp;gt;
          {link.title}
        &amp;lt;/div&amp;gt;
      &amp;lt;/Link&amp;gt;
    ) : null
  )}
&amp;lt;/SignedIn&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;When the user is signed in, the &lt;code&gt;SignedIn&lt;/code&gt; component allows us to conditionally render the navigation links based on the user's role. The &lt;code&gt;links.map&lt;/code&gt; function iterates through the &lt;code&gt;links&lt;/code&gt; array, and for each link, it checks if the link is intended for administrators (&lt;code&gt;link.role === 'admin'&lt;/code&gt;) and if the user actually has an "admin" role (&lt;code&gt;userRole === 'admin'&lt;/code&gt;). If both conditions are met or if the link does not have a specific role assigned (&lt;code&gt;!link.role&lt;/code&gt;), the link is displayed using the &lt;code&gt;Link&lt;/code&gt; component from Next.js, enclosed within a &lt;code&gt;div&lt;/code&gt; element for proper styling. This way, we can selectively show the appropriate links based on the user's role after they have signed in.&lt;/p&gt;

&lt;p&gt;Here's how you should arrange the &lt;code&gt;SignedOut&lt;/code&gt; and &lt;code&gt;UserButton&lt;/code&gt; components:&lt;/p&gt;

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

{/* SignedOut Component */}
&amp;lt;SignedOut&amp;gt;
  &amp;lt;a href='/sign-in'&amp;gt;
    &amp;lt;button className='text-white bg-indigo-500 border-0 py-2 px-4 focus:outline-none hover:bg-indigo-600 rounded text-base mr-4'&amp;gt;
      Login
    &amp;lt;/button&amp;gt;
  &amp;lt;/a&amp;gt;
  &amp;lt;a href='/sign-up'&amp;gt;
    &amp;lt;button className='text-white bg-indigo-500 border-0 py-2 px-4 focus:outline-none hover:bg-indigo-600 rounded text-base'&amp;gt;
      Sign Up
    &amp;lt;/button&amp;gt;
  &amp;lt;/a&amp;gt;
&amp;lt;/SignedOut&amp;gt;

{/* UserButton Component */}
&amp;lt;SignedIn&amp;gt;
  &amp;lt;div className='ml-4'&amp;gt;
    &amp;lt;UserButton afterSignOutUrl='/' /&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/SignedIn&amp;gt;


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

&lt;/div&gt;

&lt;p&gt;Having completed all the necessary steps, we are now able to conditionally render the application, displaying different links based on the various scenarios we have highlighted. This allows us to customize the Navbar content depending on the user's authentication status, role, and whether they are signed in or signed out. With this implementation, the application provides a seamless and user-specific navigation experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ensuring Role-Based Access Control for the Admin    Dashboard Page
&lt;/h2&gt;

&lt;p&gt;Currently, we have successfully hidden the &lt;code&gt;Admin Dashboard&lt;/code&gt; link from basic members. However, there is still an issue to address - any user can access the &lt;code&gt;/admin&lt;/code&gt; route, even if they are not authorized to do so. This behavior is undesirable and needs to be rectified. Let's proceed to handle this situation to ensure that only users with the &lt;code&gt;admin&lt;/code&gt; role can access the &lt;code&gt;Admin Dashboard&lt;/code&gt; page.&lt;/p&gt;

&lt;p&gt;To implement this functionality, we will utilize the &lt;code&gt;useOrganizationList&lt;/code&gt; hook on the admin page. By using the &lt;code&gt;useOrganizationList&lt;/code&gt; hook, we gain access to the list of available Organizations and the OrganizationMemberships to which the user is affiliated. This information will enable us to enforce role-based access control and ensure that only authorized users can access the Admin Dashboard page.&lt;/p&gt;

&lt;p&gt;We must first import the &lt;code&gt;useOrganizationList&lt;/code&gt; hook into the admin page before we can use it. Here's how to go about it:&lt;/p&gt;

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

import { useOrganizationList } from '@clerk/nextjs';


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

&lt;/div&gt;

&lt;p&gt;After importing the &lt;code&gt;useOrganizationList&lt;/code&gt; hook, you can utilize it to access the organization data. By invoking the hook, you will receive three variables: &lt;code&gt;organizationList&lt;/code&gt;, &lt;code&gt;isLoaded&lt;/code&gt;, and &lt;code&gt;setActive&lt;/code&gt;.&lt;/p&gt;

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

const { organizationList, isLoaded, setActive } = useOrganizationList();


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

&lt;/div&gt;

&lt;p&gt;&lt;code&gt;organizationList&lt;/code&gt; will hold the list of available organizations, providing important information about each organization and its members. &lt;code&gt;isLoaded&lt;/code&gt; is a boolean value that indicates whether the organization data has been successfully loaded and is ready for use. Lastly, &lt;code&gt;setActive&lt;/code&gt; is a function that allows you to set the active organization.&lt;/p&gt;

&lt;p&gt;The subsequent step involves waiting for the organization data to load and verifying whether the user's role is not admin. We achieve this using the &lt;code&gt;useEffect&lt;/code&gt; hook:&lt;/p&gt;

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

useEffect(() =&amp;gt; {
  if (isLoaded) {
    // Find the admin organization from the loaded organization list
    const adminOrganization = organizationList.find(
      (org) =&amp;gt; org.membership.role === 'admin'
    );

    // If the user is not an admin, redirect to the homepage
    if (!adminOrganization || adminOrganization.membership.role !== 'admin') {
      router.push('/'); // Replace '/' with the homepage URL
    } else {
      // If the user is an admin, no need to wait for the organization list; render the admin page directly
      setShowLoader(false);
    }
  }
}, [isLoaded, organizationList]);


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

&lt;/div&gt;

&lt;p&gt;In this &lt;code&gt;useEffect&lt;/code&gt; block, we use the &lt;code&gt;isLoaded&lt;/code&gt; variable to ensure that we have successfully loaded the organization data. Once the data is available, we look for an organization with the role of 'admin' within the organization list. If the user does not have an admin role or there is no admin organization found, we redirect them to the homepage using the &lt;code&gt;router.push&lt;/code&gt; method. However, if the user is indeed an admin, we proceed to render the admin page directly, setting &lt;code&gt;setShowLoader&lt;/code&gt; to &lt;code&gt;false&lt;/code&gt; to indicate that the loading process is complete. This way, we enforce the role-based access control and appropriately handle navigation based on the user's role.&lt;/p&gt;

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

&lt;p&gt;With these steps, we have successfully implemented Role-Based Access Control in the Next.js App Router using Clerk Organizations. It demonstrates how seamlessly Clerk's features can be integrated into the application, making the process straightforward and efficient. This approach allows us to control user access based on their roles, providing a secure and tailored user experience. Indeed, the integration with Clerk Organizations simplifies the implementation of role-based access, making it a smooth and straightforward process.&lt;/p&gt;

&lt;p&gt;If you prefer not to create organizations through the Clerk dashboard, the Clerk team offers components that you can integrate directly into your codebase to handle organization management. For more details, you can explore the documentation at: &lt;a href="https://clerk.com/docs/organizations/overview" rel="noopener noreferrer"&gt;https://clerk.com/docs/organizations/overview&lt;/a&gt;. These components provide a convenient way to manage organizations and memberships within your application, giving you flexibility and control over the organization setup process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Refference
&lt;/h2&gt;

&lt;p&gt;For further guidance and information, refer to the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Next.js Documentation: Access the official Next.js documentation at &lt;a href="https://nextjs.org/docs" rel="noopener noreferrer"&gt;https://nextjs.org/docs&lt;/a&gt; for in-depth details about the framework.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clerk Documentation: Explore Clerk's authentication capabilities and integration guides at &lt;a href="https://clerk.com/docs" rel="noopener noreferrer"&gt;https://clerk.com/docs&lt;/a&gt; to understand its usage better.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simplifying Authentication in Next.js Applications with Clerk: Find detailed steps for setting up Clerk authentication in Next.js apps in the blog post: &lt;a href="https://dev.to/musebe/simplifying-authentication-in-nextjs-applications-with-clerk-3adh"&gt;Dev.to Link&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>clerk</category>
      <category>authentication</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Building a Todo App with Next.js 13, Clerk, and Supabase.</title>
      <dc:creator>eugene musebe</dc:creator>
      <pubDate>Wed, 19 Jul 2023 16:41:02 +0000</pubDate>
      <link>https://dev.to/musebe/building-a-todo-app-with-nextjs-13-clerk-for-authentication-and-supabase-557i</link>
      <guid>https://dev.to/musebe/building-a-todo-app-with-nextjs-13-clerk-for-authentication-and-supabase-557i</guid>
      <description>&lt;p&gt;Introduction&lt;/p&gt;

&lt;p&gt;In this guide, we will embark on a journey to build a sleek and powerful Todo application using the latest technology stack, &lt;a href="https://nextjs.org" rel="noopener noreferrer"&gt;Next.js 13&lt;/a&gt;, &lt;a href="https://clerk.com" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; for Authentication, and &lt;a href="https://supabase.com" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; as the database. With the seamless integration of Clerk and Supabase into Next.js applications, we'll discover how this combination forms a robust foundation for modern web applications, providing security, scalability, and ease of development.&lt;/p&gt;

&lt;p&gt;Throughout this blog post, we'll delve into the step-by-step process of setting up Clerk authentication in a Next.js 13 application, ensuring secure access to our Todo app. Then, we'll explore the seamless integration of Supabase, witnessing how it effortlessly handles data storage and retrieval while providing real-time updates for a smoother user experience.&lt;/p&gt;

&lt;p&gt;This is a continuation of the blogpost : &lt;a href="https://dev.to/musebe/simplifying-authentication-in-nextjs-applications-with-clerk-3adh"&gt;Simplifying Authentication in Next.js Applications with Clerk&lt;/a&gt; hence we shall be focusing on intergrating clerk with Supabase&lt;/p&gt;

&lt;p&gt;Let's dive in and discover the magic of building a minimalistic Todo app with Next.js 13, Clerk, and the Supabase database!&lt;/p&gt;

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

&lt;p&gt;Before building the Todo app, make sure you have:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Basic web development skills (HTML, CSS, JavaScript).&lt;/li&gt;
&lt;li&gt; Familiarity with Next.js basics.&lt;/li&gt;
&lt;li&gt; Node.js and npm installed.&lt;/li&gt;
&lt;li&gt; A code editor.&lt;/li&gt;
&lt;li&gt; Optional: Git for version control.&lt;/li&gt;
&lt;li&gt; A &lt;a href="https://supabase.com" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; account for the database.&lt;/li&gt;
&lt;li&gt; A &lt;a href="https://clerk.com" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; account for authentication.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;With these prerequisites, you're all set to start creating your Todo app using Next.js 13, Clerk, and Supabase. Let's begin!&lt;/p&gt;

&lt;h2&gt;
  
  
  Github Repository
&lt;/h2&gt;

&lt;p&gt;Find the starting code on the main branch : &lt;a href="https://github.com/musebe/Nextjs-Clerk" rel="noopener noreferrer"&gt;https://github.com/musebe/Nextjs-Clerk&lt;/a&gt;. For the final codebase, check out the supabase branch &lt;a href="https://github.com/musebe/Nextjs-Clerk/tree/supabase" rel="noopener noreferrer"&gt;https://github.com/musebe/Nextjs-Clerk/tree/supabase&lt;/a&gt;. Happy coding!&lt;/p&gt;

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

&lt;p&gt;To get started clone the main branch from the Github repository &lt;a href="https://github.com/musebe/Nextjs-Clerk" rel="noopener noreferrer"&gt;Simplifying Authentication in Next.js Applications with Clerk&lt;/a&gt;. The will act as the starting point for our application as its already setup with Authentication.&lt;/p&gt;

&lt;p&gt;To clone the applicarion run the following command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/musebe/Nextjs-Clerk.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Navigate to the project directory and run the following command to install all the project dependencies :&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;To start the application run the command :&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Supabase Setup
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;Supabase&lt;/a&gt; is an open-source Backend-as-a-Service (BaaS) platform that aims to simplify the development of web and mobile applications. It provides developers with a suite of tools and services to quickly build and scale applications without having to worry about server management or infrastructure setup.&lt;/p&gt;

&lt;p&gt;One of the key features of Supabase is real-time updates. It leverages PostgreSQL's capabilities to provide instant and synchronized data updates to clients, making it ideal for applications that require real-time collaboration or live data streams.&lt;/p&gt;

&lt;p&gt;To get started, follow the following steps&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Sign Up for a Supabase Account
&lt;/h3&gt;

&lt;p&gt;To begin your journey with Supabase, head over to &lt;a href="//supabase.com"&gt;supabase.com&lt;/a&gt; and click on the &lt;code&gt;Sign Up&lt;/code&gt; button located in the top right corner of the page. You can choose to sign up using your &lt;code&gt;GitHub&lt;/code&gt; or &lt;code&gt;Google&lt;/code&gt; account for a quick registration process. Alternatively, provide your email address and fill in the necessary details to create an account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Create a New Project
&lt;/h3&gt;

&lt;p&gt;Once you have successfully signed up and logged in, you will be directed to your Supabase dashboard. Here, click on the &lt;code&gt;New Project&lt;/code&gt; button to create a new project. Give your project a meaningful name and select the preferred region for data storage. Supabase offers multiple regions to ensure low-latency access to your data as highlighted below : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F1f15q4qrl0lwxmgzrvcf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F1f15q4qrl0lwxmgzrvcf.png" alt="Supabase setup" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Set Up Your Database
&lt;/h3&gt;

&lt;p&gt;After creating your project, you will land on the project overview page. From the left sidebar, select the &lt;code&gt;SQL Editor&lt;/code&gt; tab. To set up a new database, click on "Create table" template and run the following query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE TABLE todos (
  id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
  user_id VARCHAR,
  created_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, NOW()) NOT NULL,
  completed_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, NOW()) NOT NULL,
  todo VARCHAR,
  tag VARCHAR
);

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.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%2Fo3yd1hwsp8sqaen9nlrg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fo3yd1hwsp8sqaen9nlrg.png" alt="Todos Query" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Supabase query above creates a table named "todos" with the following columns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;id&lt;/code&gt; (bigint): This column is an auto-generated primary key of type &lt;code&gt;bigint&lt;/code&gt;. It will automatically assign a unique identifier to each row added to the table.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;user_id&lt;/code&gt; (varchar): This column stores the user identifier associated with the todo. It is of type &lt;code&gt;varchar&lt;/code&gt;, which means it can hold alphanumeric characters and symbols.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;created_at&lt;/code&gt; (timestamp with time zone): This column represents the timestamp when the todo was created. It has a default value set to the current time in Coordinated Universal Time (UTC). The &lt;code&gt;now()&lt;/code&gt; function retrieves the current timestamp, and the &lt;code&gt;timezone('utc'::text, ...)&lt;/code&gt; function ensures it is in UTC format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;completed_at&lt;/code&gt; (timestamp with time zone): This column represents the timestamp when the todo was marked as completed. Similar to &lt;code&gt;created_at&lt;/code&gt;, it has a default value set to the current time in UTC.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;todo&lt;/code&gt; (varchar): This column stores the actual todo item, such as a task or reminder. It is of type &lt;code&gt;varchar&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;tag&lt;/code&gt; (varchar): This column allows categorizing or labeling the todo item with a tag. It is also of type &lt;code&gt;varchar&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After running the query above click on the &lt;code&gt;table editor&lt;/code&gt; tab on the left menu and you will see a &lt;code&gt;todos&lt;/code&gt; table created with the structure below : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Finigy1o0knbi1eump3eg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Finigy1o0knbi1eump3eg.png" alt="Todos Table" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Configure RLS (Row Level Security)  for the&lt;code&gt;todos&lt;/code&gt; table
&lt;/h3&gt;

&lt;p&gt;Configuring Row Level Security (RLS) in Supabase provides an essential layer of data protection and access control for your database tables. RLS allows you to define rules that determine which rows of data a user can access based on their specific attributes or roles. This feature plays a crucial role in enhancing the security and privacy of your application's data.&lt;/p&gt;

&lt;p&gt;To create our first row level security run the following command on the &lt;code&gt;SQL Editor&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;create or replace function requesting_user_id() returns text as $$
  select nullif(current_setting('request.jwt.claims', true)::json-&amp;gt;&amp;gt;'sub', '')::text;
$$ language sql stable;

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.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%2Fvpg148tauay4m2cl30zl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fvpg148tauay4m2cl30zl.png" alt="policy_query" width="800" height="459"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above is a function named &lt;code&gt;requesting_user_id()&lt;/code&gt;. This function returns the user ID (sub claim) extracted from the JSON web token (JWT) included in the request header. &lt;/p&gt;

&lt;p&gt;Next we need to create a policy that allows only authenticated users to update their own todos. Run the following query as highlighted below :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE POLICY "Authenticated users can update their own todos"
ON public.todos FOR UPDATE
USING (
    auth.role() = 'authenticated'::text
)
WITH CHECK (
    requesting_user_id() = user_id
);

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

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.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%2F4k6g63k0r1ztxvujznib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F4k6g63k0r1ztxvujznib.png" alt="Authenticate" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This code creates a policy named "Authenticated users can update their own todos" on the &lt;code&gt;public.todos&lt;/code&gt; table. The policy allows updates to the table only if the user has the role "authenticated" and the requesting user ID matches the &lt;code&gt;user_id&lt;/code&gt; column in the table.&lt;/p&gt;

&lt;p&gt;To check if the above policies have been applied to our &lt;code&gt;todos&lt;/code&gt; database, navigate to the &lt;code&gt;Authentication&lt;/code&gt; tab and click the &lt;code&gt;policies&lt;/code&gt; button. you should be able to see this : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fgoskovdeyypr7jsxous5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fgoskovdeyypr7jsxous5.png" alt="Policies" width="800" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To finalize the database setup with Supabase, you will need to obtain the Supabase API Key and URL. These credentials are essential for connecting your application to the Supabase database and making authenticated requests to access data or perform CRUD operations.&lt;/p&gt;

&lt;p&gt;These credentials serve as your project's authentication tokens. They allow you to interact with the Supabase API securely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;API Key: The API Key acts as your secret key to authenticate requests to the Supabase API. It is a long string of characters and numbers, used to identify and authorize your application.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;URL: The URL is the endpoint through which you will make requests to the Supabase API. It typically follows the format &lt;code&gt;https://your-project-id.supabase.co&lt;/code&gt;, where &lt;code&gt;your-project-id&lt;/code&gt; is replaced with your specific Supabase project ID.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To view your keys click on the &lt;code&gt;Settings&lt;/code&gt; tab. This will take you to the project settings where all the keys are stored. Click on the &lt;code&gt;API&lt;/code&gt;  tab to revel your keys as shown below : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2F4x514kdwxt26j2du6n3x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2F4x514kdwxt26j2du6n3x.png" alt="Keys" width="800" height="295"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Copy the keys and paste them in the &lt;code&gt;.env&lt;/code&gt; file of your project as shown below :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEXT_PUBLIC_SUPABASE_URL= YOUR_SUPABASE_URL
NEXT_PUBLIC_SUPABASE_KEY=YOUR_SUPABASE_ANON_PUBLIC_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supabase requires JWTs be signed with the HS256 signing algorithm and use their signing key. Find the JWT secret key in your Supabase project under &lt;strong&gt;Settings&lt;/strong&gt; &amp;gt; &lt;strong&gt;API&lt;/strong&gt; in the &lt;strong&gt;Config&lt;/strong&gt; section. Copy the &lt;code&gt;JWT secret&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fwaaovb0yb0ms5bo99hiw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fwaaovb0yb0ms5bo99hiw.png" alt="jwt token" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To complete the integration between Supabase and the Clerk authentication service, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Access your Clerk dashboard: Log in to your Clerk account and navigate to the dashboard.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Go to JWT Templates: In the Clerk dashboard, locate the &lt;strong&gt;JWT Templates&lt;/strong&gt; page and click on it. This page allows you to configure JSON Web Token (JWT) templates for different authentication providers.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create a new template: On the &lt;strong&gt;JWT Templates&lt;/strong&gt; page, click the button to create a new template. Select "Supabase" as the authentication provider for which you want to configure the template.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set the Signing Key: In the template configuration, find the field labeled "Signing Key" and paste the "JWT secret" key that you previously copied from your Supabase project. This key is essential for securely signing and verifying the JWTs issued by Clerk.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By following these steps and configuring the JWT template in the Clerk dashboard, you have successfully integrated Supabase with Clerk's authentication service. Clerk will now be able to generate and validate JWTs using the Supabase signing key, providing secure and seamless authentication for your application as highlighted below :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Fucpge9suz9aqaqnb9vdk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Fucpge9suz9aqaqnb9vdk.png" alt="JWT" width="800" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing Supabase
&lt;/h2&gt;

&lt;p&gt;Congratulations! With the database set up and Clerk configured with Supabase, you are now ready to integrate Supabase into your Next.js project. To do so, follow these simple steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open your Next.js project: Navigate to the root directory of your Next.js project in your terminal or code editor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Install the Supabase client library: Run the following command to install the official Supabase client library for JavaScript:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install @supabase/supabase-js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will fetch and install the required &lt;code&gt;@supabase/supabase-js&lt;/code&gt; package from the npm registry and add it to your project's dependencies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Centralizing Supabase Client
&lt;/h2&gt;

&lt;p&gt;To enhance organization and reusability in your Next.js project, we can centralize the creation and configuration of the Supabase client by creating a &lt;code&gt;utils&lt;/code&gt; folder at the root of the project structure. Within this folder, we'll add a file named &lt;code&gt;supabaseClient.js&lt;/code&gt;. This approach helps maintain clean code and facilitates easier management of the Supabase client across multiple components and pages.&lt;/p&gt;

&lt;p&gt;Here's how you can achieve it:&lt;/p&gt;

&lt;p&gt;Step 1: Create the &lt;code&gt;utils&lt;/code&gt; folder&lt;/p&gt;

&lt;p&gt;In your Next.js project, navigate to the root directory and create a new folder named &lt;code&gt;utils&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Step 2: Add &lt;code&gt;supabaseClient.js&lt;/code&gt; to the &lt;code&gt;utils&lt;/code&gt; folder&lt;/p&gt;

&lt;p&gt;Within the &lt;code&gt;utils&lt;/code&gt; folder, create a new file named &lt;code&gt;supabaseClient.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Step 3: Place the Supabase Client Configuration Code&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;supabaseClient.js&lt;/code&gt; file, add the following code to create and configure the Supabase client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { createClient } from '@supabase/supabase-js';

export const supabaseClient = async (supabaseToken) =&amp;gt; {
  const supabase = createClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL,
    process.env.NEXT_PUBLIC_SUPABASE_KEY,
    {
      global: { headers: { Authorization: `Bearer ${supabaseToken}` } },
    }
  );

  return supabase;
};

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

&lt;/div&gt;



&lt;p&gt;The purpose of this code snippet is to create a Supabase client, which is a client-side library responsible for communication between the frontend application and the Supabase backend. This client enables seamless interaction with the database, making it easier to perform various operations such as querying data, managing real-time updates, and handling authentication.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;supabaseClient&lt;/code&gt; function, which is exported from this code snippet, accepts a &lt;code&gt;supabaseToken&lt;/code&gt; as an input parameter. This token is typically an authentication token obtained from Supabase, uniquely associated with a user.&lt;/p&gt;

&lt;p&gt;Inside the function, the &lt;code&gt;createClient&lt;/code&gt; function from the &lt;code&gt;@supabase/supabase-js&lt;/code&gt; library is utilized to instantiate the Supabase client. This function requires three arguments: &lt;code&gt;process.env.NEXT_PUBLIC_SUPABASE_URL&lt;/code&gt;, &lt;code&gt;process.env.NEXT_PUBLIC_SUPABASE_KEY&lt;/code&gt;, and an object containing additional configuration options.&lt;/p&gt;

&lt;p&gt;The first argument, &lt;code&gt;process.env.NEXT_PUBLIC_SUPABASE_URL&lt;/code&gt;, represents the URL of the Supabase project. It is usually stored as an environment variable and serves as the endpoint for server communication.&lt;/p&gt;

&lt;p&gt;The second argument, &lt;code&gt;process.env.NEXT_PUBLIC_SUPABASE_KEY&lt;/code&gt;, represents the public API key of the Supabase project. Like the URL, this is stored as an environment variable and provides the necessary authentication and authorization for the client.&lt;/p&gt;

&lt;p&gt;The third argument is an object that specifies further configuration options for the Supabase client. In this code snippet, it sets the &lt;code&gt;Authorization&lt;/code&gt; header for each request using the provided &lt;code&gt;supabaseToken&lt;/code&gt;. This ensures that the client is authenticated and authorized to access the relevant resources on the Supabase backend.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;supabaseClient&lt;/code&gt; function returns the configured Supabase client instance, which can then be used across the application to interact with the database and handle real-time updates. By encapsulating the client creation and configuration within this utility, it promotes code reusability and maintains a clean structure within the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Performing Requests to Fetch and Post Todos from Supabase: Creating &lt;code&gt;requests.js&lt;/code&gt; in the &lt;code&gt;utils&lt;/code&gt; Folder&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To handle fetching and posting todos to Supabase, we can create a file named &lt;code&gt;requests.js&lt;/code&gt; within the &lt;code&gt;utils&lt;/code&gt; folder. This file will contain functions that encapsulate the logic for making API requests to the Supabase database. By doing so, we can keep the API interaction centralized and easily manage todo-related requests in our Next.js project.&lt;/p&gt;

&lt;p&gt;Let's go ahead and create the &lt;code&gt;requests.js&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;Step 1: Create &lt;code&gt;requests.js&lt;/code&gt; in the &lt;code&gt;utils&lt;/code&gt; folder&lt;/p&gt;

&lt;p&gt;In your Next.js project, navigate to the &lt;code&gt;utils&lt;/code&gt; folder, which you created earlier, and create a new file named &lt;code&gt;requests.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Step 2: Implement Fetch and Post Functions&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;requests.js&lt;/code&gt; file, add the necessary functions to fetch and post todos to Supabase. Below is an example of how you can implement these functions:&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetch Todos
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// utils/requests.js
import { supabaseClient } from './supabaseClient';

// Function to fetch todos from Supabase
export const getTodos = async ({ userId, token }) =&amp;gt; {
  const supabase = await supabaseClient(token);
  const { data: todos, error } = await supabase
    .from("todos")
    .select("*")
    .eq("user_id", userId);

  if (error) {
    console.error('Error fetching todos:', error.message);
    return [];
  }

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;getTodos&lt;/code&gt; function is an asynchronous function that accepts an object with &lt;code&gt;userId&lt;/code&gt; and &lt;code&gt;token&lt;/code&gt; properties as parameters.  It first awaits the &lt;code&gt;supabaseClient&lt;/code&gt; function (imported from &lt;code&gt;'./supabaseClient'&lt;/code&gt;) passing the &lt;code&gt;token&lt;/code&gt; as an argument. This function creates and returns the Supabase client. Using the Supabase client, it performs a select query on the "todos" table, filtering the results based on the &lt;code&gt;user_id&lt;/code&gt; column that matches the &lt;code&gt;userId&lt;/code&gt; parameter.&lt;br&gt;
The result is destructured to extract the &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt; properties. If an error occurs during the fetch operation, it logs an error message to the console and returns an empty array (&lt;code&gt;[]&lt;/code&gt;).&lt;br&gt;
Otherwise, it returns the fetched &lt;code&gt;todos&lt;/code&gt; data.&lt;/p&gt;
&lt;h3&gt;
  
  
  Post Todos
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const postTodo = async ({ userId, token, e }) =&amp;gt; {
  const supabase = await supabaseClient(token);
  const { data, error } = await supabase
    .from('todos')
    .insert({
      user_id: userId,
      todo: e.target[0].value,
      tag: e.target[1].value,
    })
    .select();

  if (error) {
    console.error('Error posting todo:', error.message);
    return null;
  }

  return data;
};

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

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;postTodo&lt;/code&gt; function is also an asynchronous function that accepts an object with &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;token&lt;/code&gt;, and &lt;code&gt;e&lt;/code&gt; properties as parameters.&lt;br&gt;
It awaits the &lt;code&gt;supabaseClient&lt;/code&gt; function (imported from &lt;code&gt;'./supabaseClient'&lt;/code&gt;) passing the &lt;code&gt;token&lt;/code&gt; as an argument to create the Supabase client.&lt;br&gt;
Using the Supabase client, it performs an insert operation on the "todos" table, inserting a new row with values for &lt;code&gt;user_id&lt;/code&gt;, &lt;code&gt;todo&lt;/code&gt;, and &lt;code&gt;tag&lt;/code&gt; columns obtained from the &lt;code&gt;e&lt;/code&gt; parameter (which is expected to contain event-related information).&lt;br&gt;
The result is destructured to extract the &lt;code&gt;data&lt;/code&gt; and &lt;code&gt;error&lt;/code&gt; properties.&lt;br&gt;
If an error occurs during the insert operation, it logs an error message to the console and returns &lt;code&gt;null&lt;/code&gt;.&lt;br&gt;
Otherwise, it returns the inserted &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now that you have created the &lt;code&gt;fetchTodos&lt;/code&gt; and &lt;code&gt;postTodo&lt;/code&gt; functions in the &lt;code&gt;requests.js&lt;/code&gt; file, you can use them in your components or pages to interact with your Supabase database. Import the functions where needed and call them to fetch or post todos.&lt;/p&gt;
&lt;h2&gt;
  
  
  Post Todos Component
&lt;/h2&gt;

&lt;p&gt;To post &lt;code&gt;todos&lt;/code&gt; to Supabase, create a &lt;code&gt;create-todo&lt;/code&gt; folder inside the app directory, then add a &lt;code&gt;page.jsx&lt;/code&gt; file inside it with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';
import { useRouter } from 'next/router';
import { postTodo } from '../../utils/requests';
import { useAuth } from '@clerk/nextjs';
import Form from '@components/Form';

const CreateToDo = () =&amp;gt; {
  const router = useRouter();
  const { userId, getToken } = useAuth();

  const [submitting, setSubmitting] = useState(false);
  const [formData, setFormData] = useState({ todo: '', tag: '' });

  const createTodo = async (e) =&amp;gt; {
    e.preventDefault();
    try {
      setSubmitting(true);
      const token = await getToken({ template: 'supabase' });
      const posts = await postTodo({ e, userId, token });
      setFormData(posts);
      if (posts) {
        router.push('/');
      }
    } catch (error) {
      console.error('An error occurred:', error);
    } finally {
      setSubmitting(false);
    }
  };

  return (
    &amp;lt;Form
      type='Post'
      post={formData}
      setPost={setFormData}
      submitting={submitting}
      handleSubmit={createTodo}
    /&amp;gt;
  );
};

export default CreateToDo;

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

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;CreateToDo&lt;/code&gt; component is responsible for handling the creation of &lt;code&gt;todos&lt;/code&gt; and posting them to the Supabase backend.&lt;/p&gt;

&lt;p&gt;It imports the required dependencies, including &lt;code&gt;useState&lt;/code&gt; for managing component state, &lt;code&gt;useRouter&lt;/code&gt; from Next.js to access the router functionality, &lt;code&gt;postTodo&lt;/code&gt; from the &lt;code&gt;utils/requests&lt;/code&gt; module to send the todo data to the server, &lt;code&gt;useAuth&lt;/code&gt; from &lt;code&gt;@clerk/nextjs&lt;/code&gt; for authentication using Clerk, and &lt;code&gt;Form&lt;/code&gt; from &lt;code&gt;@components/Form&lt;/code&gt; for rendering the form.&lt;/p&gt;

&lt;p&gt;The component uses the &lt;code&gt;useState&lt;/code&gt; hook to manage the state variables &lt;code&gt;submitting&lt;/code&gt; and &lt;code&gt;formData&lt;/code&gt;. &lt;code&gt;submitting&lt;/code&gt; is used to indicate whether the form is currently being submitted, while &lt;code&gt;formData&lt;/code&gt; holds the todo and tag values from the form.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;createTodo&lt;/code&gt; function is defined to handle the form submission. It is an asynchronous function to handle the asynchronous tasks such as getting the authentication token and posting the todo data to the server.&lt;/p&gt;

&lt;p&gt;When the form is submitted (&lt;code&gt;e.preventDefault()&lt;/code&gt; is called), the function sets &lt;code&gt;submitting&lt;/code&gt; to true to indicate that the form submission is in progress.&lt;/p&gt;

&lt;p&gt;It then uses &lt;code&gt;useAuth&lt;/code&gt; to obtain the user's ID and gets the Supabase authentication token using &lt;code&gt;getToken({ template: 'supabase' })&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;postTodo&lt;/code&gt; function is called with the necessary data, including the event (&lt;code&gt;e&lt;/code&gt;), the user's ID, and the authentication token, to post the todo data to Supabase.&lt;br&gt;
The response from the server is stored in the &lt;code&gt;posts&lt;/code&gt; variable, and the state is updated with the response data using &lt;code&gt;setFormData&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the post was successful (&lt;code&gt;if (posts)&lt;/code&gt;), the user is redirected to the homepage using the Next.js router (&lt;code&gt;router.push('/')&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Any errors that occur during the process are caught in the &lt;code&gt;catch&lt;/code&gt; block and logged to the console for debugging purposes.&lt;/p&gt;

&lt;p&gt;Regardless of success or failure, &lt;code&gt;setSubmitting(false)&lt;/code&gt; is called in the &lt;code&gt;finally&lt;/code&gt; block to set &lt;code&gt;submitting&lt;/code&gt; back to false after the form submission process is completed.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;Form&lt;/code&gt; component is rendered with the appropriate props, including the &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;post&lt;/code&gt;, &lt;code&gt;setPost&lt;/code&gt;, &lt;code&gt;submitting&lt;/code&gt;, and &lt;code&gt;handleSubmit&lt;/code&gt;. These props are used to pass the necessary information and functions to the &lt;code&gt;Form&lt;/code&gt; component to display and handle the form elements.&lt;/p&gt;
&lt;h2&gt;
  
  
  Retrieve Todos Component
&lt;/h2&gt;

&lt;p&gt;To retrieve the posted todos from Supabase and create a &lt;code&gt;Feed.jsx&lt;/code&gt; component to display them, follow these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Import the necessary dependencies:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'use client';
import { useState, useEffect } from 'react';
import  {  getTodos  }  from  '../utils/requests';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Create the &lt;code&gt;Feed&lt;/code&gt; component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Feed = ({ userId, token }) =&amp;gt; {
  const [todos, setTodos] = useState([]);

  useEffect(() =&amp;gt; {
    const fetchTodos = async () =&amp;gt; {
      try {
        const todosData = await getTodos({ userId, token });
        setTodos(todosData);
      } catch (error) {
        console.error('Error fetching todos:', error.message);
        setTodos([]);
      }
    };

    fetchTodos();
  }, [userId, token]);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h2&amp;gt;Todo Feed&amp;lt;/h2&amp;gt;
      &amp;lt;ul&amp;gt;
        {todos.map((todo) =&amp;gt; (
          &amp;lt;li key={todo.id}&amp;gt;{todo.title}&amp;lt;/li&amp;gt;
        ))}
      &amp;lt;/ul&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default Feed;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;Feed&lt;/code&gt; component above, the &lt;code&gt;useState&lt;/code&gt; hook is used to create a state variable &lt;code&gt;todos&lt;/code&gt; and the &lt;code&gt;setTodos&lt;/code&gt; function to update it. The initial value of &lt;code&gt;todos&lt;/code&gt; is an empty array.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;useEffect&lt;/code&gt; hook is used to fetch the todos when the component is mounted. It calls the &lt;code&gt;fetchTodos&lt;/code&gt; function asynchronously, which is defined inside the &lt;code&gt;useEffect&lt;/code&gt; hook.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;fetchTodos&lt;/code&gt; function, the &lt;code&gt;getTodos&lt;/code&gt; function is called with the provided &lt;code&gt;userId&lt;/code&gt; and &lt;code&gt;token&lt;/code&gt;. The returned todos data is stored in the &lt;code&gt;todosData&lt;/code&gt; variable and then set as the new value of the &lt;code&gt;todos&lt;/code&gt; state using &lt;code&gt;setTodos(todosData)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If an error occurs during the API call, it is caught in the &lt;code&gt;catch&lt;/code&gt; block, logged to the console, and the &lt;code&gt;todos&lt;/code&gt; state is set to an empty array to clear any previously fetched data.&lt;/p&gt;

&lt;p&gt;The rendered JSX in the &lt;code&gt;return&lt;/code&gt; statement displays the list of todos. Each todo is mapped to a &lt;code&gt;&amp;lt;li&amp;gt;&lt;/code&gt; element with a unique &lt;code&gt;key&lt;/code&gt; attribute set to &lt;code&gt;todo.id&lt;/code&gt;, and the &lt;code&gt;todo.title&lt;/code&gt; is displayed as the content of the list item.&lt;/p&gt;

&lt;p&gt;Finally, the &lt;code&gt;Feed&lt;/code&gt; component is exported as the default export.&lt;/p&gt;

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

&lt;p&gt;In conclusion, we successfully built a sleek Todo app using Next.js 13, Clerk for Authentication, and Supabase as the database. Clerk ensured secure access, while Supabase handled data storage and real-time updates. The integration of these technologies formed a powerful foundation for modern web apps with enhanced security and user experience. Happy coding!&lt;/p&gt;

&lt;p&gt;Your final application should looki like this&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.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%2Frad47rhdidzvfuwyvrik.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.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%2Frad47rhdidzvfuwyvrik.gif" alt="Clerk-Supabase" width="600" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;For further guidance and information, refer to the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Next.js Documentation: Access the official Next.js documentation at &lt;a href="https://nextjs.org/docs" rel="noopener noreferrer"&gt;https://nextjs.org/docs&lt;/a&gt; for in-depth details about the framework.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Clerk Documentation: Explore Clerk's authentication capabilities and integration guides at &lt;a href="https://clerk.com/docs" rel="noopener noreferrer"&gt;https://clerk.com/docs&lt;/a&gt; to understand its usage better.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supabase Documentation: Learn about Supabase's real-time database features and integration options at &lt;a href="https://supabase.com/docs" rel="noopener noreferrer"&gt;https://supabase.com/docs&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simplifying Authentication in Next.js Applications with Clerk: Find detailed steps for setting up Clerk authentication in Next.js apps in the blog post: &lt;a href="https://dev.to/musebe/simplifying-authentication-in-nextjs-applications-with-clerk-3adh"&gt;Dev.to Link&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These references will aid you in building the Todo app with Next.js 13, Clerk, and Supabase effectively. Keep them handy for quick access to valuable information during your development journey.&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>clerk</category>
      <category>authentication</category>
      <category>jamstack</category>
    </item>
    <item>
      <title>Simplifying Authentication in Next.js Applications with Clerk</title>
      <dc:creator>eugene musebe</dc:creator>
      <pubDate>Fri, 07 Jul 2023 00:09:34 +0000</pubDate>
      <link>https://dev.to/musebe/simplifying-authentication-in-nextjs-applications-with-clerk-3adh</link>
      <guid>https://dev.to/musebe/simplifying-authentication-in-nextjs-applications-with-clerk-3adh</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Building secure and user-friendly authentication systems is crucial for modern web applications. As a developer, your goal is to provide a seamless experience for users while keeping their data safe. That's where &lt;a href="https://clerk.com" rel="noopener noreferrer"&gt;Clerk&lt;/a&gt; comes in. Clerk is a powerful authentication and user management platform designed to simplify authentication in Next.js and Reactjs applications, offering an exceptional developer experience and robust user security.&lt;/p&gt;

&lt;p&gt;In this step-by-step guide, we will walk you through using Clerk and Next.js to implement authentication in your web applications. Clerk provides a seamless developer experience and robust user security. Combined with the versatility and efficiency of Next.js, you can easily create secure and user-friendly authentication systems.&lt;/p&gt;

&lt;p&gt;By following the steps outlined in this guide, you'll integrate Clerk into your Next.js application and leverage its features to enhance user onboarding, simplify authentication flows, and ensure data security.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;

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

&lt;p&gt;To follow along with this tutorial, you'll need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Basic knowledge of React and Next.js.&lt;/li&gt;
&lt;li&gt; Node.js and npm (Node Package Manager) installed on your machine.&lt;/li&gt;
&lt;li&gt; A Clerk account (you can sign up for free at &lt;a href="https://www.clerk.dev/" rel="noopener noreferrer"&gt;https://www.clerk.com&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Setting Up Your Next.js Application
&lt;/h2&gt;

&lt;p&gt;First, let's create a new Next.js project by running the following commands in your terminal:&lt;/p&gt;

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

npx create-next-app my-clerk-app
cd my-clerk-app



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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Configuring a new Clerk application for Authentication
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688676392%2Fnew-setup.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688676392%2Fnew-setup.png" title="Clerk Dashboard" alt="Clerk Dashboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To begin using Clerk, the first step is to create a Clerk account. You can do this by visiting clerk.dev and signing up for a free account. After signing in, you will be prompted to create a new application within your account. This application will serve as your starting point to explore and make use of the various features and capabilities offered by Clerk as highlighted above.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688676948%2FApplication_name.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688676948%2FApplication_name.png" title="Clerk Dashboard" alt="Application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have clicked on &lt;code&gt;Add application&lt;/code&gt; after signing in, Give your application a name and select all the 'Social authentication' methods you would like your users to leverage. &lt;/p&gt;
&lt;h2&gt;
  
  
  Installing Clerk in the Next.js Application
&lt;/h2&gt;

&lt;p&gt;Clerk provides an easy-to-use Nextjs library for integrating with its authentication system. Navigate to your Next.js project's directory and run the following command to install Clerk :&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm install @clerk/nextjs


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Configuring Clerk in Your Next.js Application
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688677690%2FAPI-Keys.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688677690%2FAPI-Keys.png" title="Clerk Dashboard" alt="Api_Keys"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a &lt;code&gt;.env.local&lt;/code&gt; file in the root of your Next.js project and include your &lt;code&gt;CLERK_PUBLISHABLE_KEY&lt;/code&gt; key and &lt;code&gt;CLERK_SECRET_KEY&lt;/code&gt; as environment variables. You can obtain these values from your clerk dashboard under the &lt;code&gt;API keys&lt;/code&gt; section as highlighted above.  &lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// clerk environment variables

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY="&amp;lt;Your Publishable Key&amp;gt;"
CLERK_SECRET_KEY="&amp;lt;Your Clerk Secret Key&amp;gt;"


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Mounting The ClerkProvider
&lt;/h2&gt;

&lt;p&gt;In this step, we will mount  the  &lt;code&gt;ClerkProvider&lt;/code&gt; component to wrap your Next.js application's root layout with the ClerkProvider context. This will allow your application to access Clerk's authentication methods and user data.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// app/layout.jsx
import  {  ClerkProvider  }  from  '@clerk/nextjs';

const Layout = ({ children }) =&amp;gt; {
  return (
    &amp;lt;ClerkProvider&amp;gt;
      {/* Your layout code goes here */}
      {children}
    &amp;lt;/ClerkProvider&amp;gt;
  );
};

export default Layout;



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

&lt;/div&gt;
&lt;h2&gt;
  
  
  Safeguarding your Application Routes
&lt;/h2&gt;

&lt;p&gt;Now that Clerk has been installed and mounted in your application, it's time to decide which pages are public and which require authentication. We accomplish this by placing a &lt;code&gt;middleware.js&lt;/code&gt; file at the root of the project structure and declaring the public and private routes. In our case, we only want the home page to be public and the rest of the page to be inaccessible until the user logs into the application. This is possible with the following code:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// Protects access from all the other pages except the home page

import { authMiddleware } from '@clerk/nextjs';

export default authMiddleware({
  publicRoutes: ["/"]
});

export const config = {
  matcher: ['/((?!.*\\..*|_next).*)', '/', '/(api|trpc)(.*)'],
};


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  SignIn and SignUp Components
&lt;/h2&gt;

&lt;p&gt;Clerk provides a selection of ready-made components that allow you to integrate sign-in, sign-up, and other user management features into your Next.js application. To utilize these features, you can use the &lt;code&gt;&amp;lt;SignIn /&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;SignUp /&amp;gt;&lt;/code&gt; components alongside Next.js' optional catch-all route.&lt;/p&gt;

&lt;p&gt;To implement this, within the "app" folder of your project, create two new directories named "sign-up" and "sign-in". Inside each directory, insert the corresponding code for the sign-up and sign-in functionalities.&lt;/p&gt;
&lt;h3&gt;
  
  
  Signin
&lt;/h3&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

// app/sign-in/pages.js

import { SignIn } from "@clerk/nextjs";

const signIn = () =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;SignIn /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default signIn;



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

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

// app/sign-up/pages.js

import { SignUp } from "@clerk/nextjs";

const signUp = () =&amp;gt; {
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;SignUp /&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

export default signUp;


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

&lt;/div&gt;

&lt;p&gt;With this in place, When you visit the route &lt;code&gt;http://localhost:3000/sign-in&lt;/code&gt; you should be able to load Clerks login page as illustrated below :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688682376%2Fclerk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688682376%2Fclerk.png" alt="Application"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up SignedIn, SignedOut and User Profile
&lt;/h2&gt;

&lt;p&gt;Clerk offers us a set of components that serve specific purposes in managing user authentication within our application. These components include "SignedIn," "SignedOut," and "RedirectToSignIn." By utilizing these components, we can conveniently wrap other components with the necessary authentication functionality. This means that we can easily control the behavior of our application based on whether a user is signed in or signed out. Additionally, we have the ability to trigger a redirection to the sign-in page whenever required. These components greatly enhance our ability to handle user authentication seamlessly within our application.&lt;/p&gt;

&lt;p&gt;To finalize the application we need to show the &lt;code&gt;SignInButton&lt;/code&gt;, &lt;code&gt;UserButton&lt;/code&gt; and &lt;code&gt;SignedOut&lt;/code&gt;  on the applications  &lt;code&gt;Navbar&lt;/code&gt; component. Navigate to your applications component and Imports various components and hooks from the '@clerk/nextjs' library as highlited below : &lt;/p&gt;

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

import  {SignedIn, SignedOut,SignInButton,UserButton,}  from  '@clerk/nextjs';


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

&lt;/div&gt;

&lt;p&gt;To understand how each component highlighted above works visit &lt;a href="https://clerk.com/docs/nextjs/get-started-with-nextjs" rel="noopener noreferrer"&gt;Clerks documentation&lt;/a&gt;  for further reading.&lt;/p&gt;

&lt;p&gt;After importing the above components on the navbar component, wrap &lt;code&gt;UserButton&lt;/code&gt; component with the &lt;code&gt;SignedIn&lt;/code&gt; component. This indicates that the &lt;code&gt;UserButton&lt;/code&gt; should only be rendered when a user is signed in.&lt;/p&gt;

&lt;p&gt;The SignedOut component, Wraps the the &lt;code&gt;SignInButton&lt;/code&gt; component with the &lt;code&gt;SignedOut&lt;/code&gt; component. This indicates that the &lt;code&gt;SignInButton&lt;/code&gt; should only be rendered when a user is signed out as illustrated in the codeblock below : &lt;/p&gt;

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

const Navbar = () =&amp;gt; {
  return (
    &amp;lt;nav&amp;gt;
      &amp;lt;SignedIn&amp;gt;
        &amp;lt;UserButton /&amp;gt;
      &amp;lt;/SignedIn&amp;gt;
      &amp;lt;SignedOut&amp;gt;
        &amp;lt;SignInButton mode='modal'&amp;gt;
          &amp;lt;button className='rounded border border-gray-400 px-3 py-0.5'&amp;gt;
            Sign in
          &amp;lt;/button&amp;gt;
        &amp;lt;/SignInButton&amp;gt;
      &amp;lt;/SignedOut&amp;gt;
    &amp;lt;/nav&amp;gt;
  );
};

export default Navbar;



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

&lt;/div&gt;

&lt;p&gt;With this in place you should be able to have a fully authenticated application as highlighted below : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688687004%2Ffinal.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fhackit-africa%2Fimage%2Fupload%2Fv1688687004%2Ffinal.gif" alt="Final Application"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;In conclusion, Clerk is the ideal choice for authentication and identity management in Next.js and React applications, thanks to its effortless integration. Clerk's dedicated libraries for Next.js and React, along with its well-documented APIs, make the integration process straightforward and time-saving. Developers can swiftly set up authentication features like login, registration, and user management, leveraging Clerk's user-friendly components and powerful API. Moreover, Clerk seamlessly integrates with various application stacks, ensuring compatibility without significant modifications.&lt;/p&gt;

&lt;p&gt;By opting for Clerk, developers can focus on building core application features instead of investing resources in complex authentication systems. Clerk's robust security measures, including multi-factor authentication and passwordless login, enhance application security without additional implementation complexities. With its easy integration, Clerk enables developers to create seamless and secure authentication experiences in Next.js and React applications, ensuring efficient functionality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Codebase
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Github Repository : &lt;a href="https://github.com/musebe/Nextjs-Clerk" rel="noopener noreferrer"&gt;https://github.com/musebe/Nextjs-Clerk&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Live Demo : &lt;a href="https://nextjs-clerk-nine.vercel.app/" rel="noopener noreferrer"&gt;https://nextjs-clerk-nine.vercel.app/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>authentication</category>
      <category>clerk</category>
      <category>nextjs</category>
      <category>authorization</category>
    </item>
    <item>
      <title>Find a Face in a Crowd With AI</title>
      <dc:creator>eugene musebe</dc:creator>
      <pubDate>Fri, 22 Mar 2019 12:18:20 +0000</pubDate>
      <link>https://dev.to/musebe/find-a-face-in-a-crowd-with-ai-4pd4</link>
      <guid>https://dev.to/musebe/find-a-face-in-a-crowd-with-ai-4pd4</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fthf8yekp1xlefar1bdg4.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fthf8yekp1xlefar1bdg4.gif" alt="Alt text of image"&gt;&lt;/a&gt;&lt;br&gt;
As technology continues its dominance in our everyday life, facial recognition is becoming more and more common, lending security to systems and gadgets in various sectors, such as health care, payments, criminal identification, and advertising. As a prominent feature of what are called biometric identification systems, facial recognition examines the physical features of people to uniquely distinguish one person from the others. Specifically, this capability takes in data, often an image from an unknown person, analyzes the data, and compares the image with the ones in a database of known people’s faces. The process takes three steps: detection, faceprint creation, and verification or identification.&lt;/p&gt;

&lt;p&gt;After verification, the system stores away a faceprint, much like a fingerprint, that contains a set of characteristics, such as the relative locations of the facial features: eyes, eyebrows, nose. When assembled, they uniquely identify a person’s face.&lt;/p&gt;

&lt;p&gt;This post describes how to manage and optimize  images with &lt;a href="https://twitter.com/smashingmag/status/1107677212218703880" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt; after manipulating and uploading them to the Cloudinary storage. To learn how to create, read, and delete images, see the article &lt;a href="https://dev.to/musebe/get-on-board-with-the-media-express-5h1k"&gt;&lt;em&gt;Get On Board With the Media Express&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Process
&lt;/h2&gt;

&lt;p&gt;Follow the procedures in this section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing the Relevant Software for Face.js
&lt;/h3&gt;

&lt;p&gt;First, install on your machine the software on which Face.js depends for facial recognition.&lt;/p&gt;

&lt;p&gt;For Linux and iOS, install the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;cmake:&lt;/strong&gt; Type the command &lt;code&gt;sudo apt-get install cmake&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;** libx11 (XQuartz on OSX) for the dlib GUI:** Type the command &lt;code&gt;sudo apt-get install libpng-dev&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;libpng for reading images:&lt;/strong&gt; Type the command &lt;code&gt;sudo apt-get install libpng-dev&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Installing and Configuring Cloudinary
&lt;/h3&gt;

&lt;p&gt;For the purpose of reading images from its storage, Cloudinary offers an outstanding Node.js integration library through npm. Install Cloudinary by typing this command:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;npm install cloudinary&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add the Node.js classes to your code. Type:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const cloudinary = require(‘cloudinary’)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To enable Cloudinary to work with your account, configure Cloudinary with your cloud name, API key, and API secret, like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cloudinary.config({ &lt;br&gt;
  cloud_name: 'sample', &lt;br&gt;
  api_key: '874837483274837', &lt;br&gt;
  api_secret: 'a676b67565c6767a6767d6767f676fe1' &lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up the APIs
&lt;/h3&gt;

&lt;p&gt;To retrieve all your trained images from the Cloudinary server, leverage  Cloudinary’s search API. Send the images to the front end with &lt;code&gt;socket.emit()&lt;/code&gt;, as follows:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cloudinary.v2.search&lt;br&gt;
    .expression('folder=face_recognition')&lt;br&gt;
    .execute().then(result=&amp;gt;{&lt;br&gt;
    socket.emit("images", result.resources);&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, set up the process of receiving images on the front end with &lt;code&gt;socket.on()&lt;/code&gt;: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;//Wait to receive images&lt;br&gt;
socket.on("images", function(images) {&lt;br&gt;
  for(image of images){&lt;br&gt;
   //Add images to HTML DOM&lt;br&gt;
  }&lt;br&gt;
  //Add event listener&lt;br&gt;
  let domImgs = document.querySelectorAll("#imgCont img")&lt;br&gt;
  for(var i = 0; i &amp;lt; domImgs.length; i++) {&lt;br&gt;
    domImgs[i].addEventListener('click', function(event){&lt;br&gt;
        clickedSrc = event.target.src&lt;br&gt;
        UploadToNodeServer(event.target.src)&lt;br&gt;
    }, false);&lt;br&gt;
  }&lt;br&gt;
  }&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The code above specifies that, on an image click, Cloudinary saves the image source in a global variable, triggering the &lt;code&gt;UploadToNodeServer&lt;/code&gt; function. See below.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;function UploadToNodeServer(imgSrc) {&lt;br&gt;
    socket.emit("imageUpload", {&lt;br&gt;
    image: false,&lt;br&gt;
    src: imgSrc,&lt;br&gt;
    });&lt;br&gt;
  }&lt;br&gt;
  $("#upldbtn").addClass("disabled");&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;UploadToNodeServer&lt;/code&gt; function sends the image source to the node’s back end, as below: &lt;/p&gt;

&lt;p&gt;&lt;code&gt;socket.on("imageUpload", function(info) {&lt;br&gt;
    if(!info.image){&lt;br&gt;
        let base64Data;&lt;br&gt;
        download(info.src, './tmp/uploads/out.png', function(){&lt;br&gt;
            if (info.format === "png")&lt;br&gt;
                console.log("Download success")&lt;br&gt;
                socket.emit("DownloadSuccess", "true"); &lt;br&gt;
//return success&lt;br&gt;
            });&lt;br&gt;
        }&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Afterwards, download the image and send it back to the front end:&lt;/p&gt;

&lt;p&gt;`//Function for downloading images&lt;/p&gt;

&lt;p&gt;const download = function(uri, filename, callback){&lt;br&gt;
    request.head(uri, function(err, res, body){&lt;br&gt;
    console.log('content-type:', res.headers['content-type']);&lt;br&gt;
    console.log('content-length:', res.headers['content-length']);&lt;br&gt;
    request(uri).pipe(fs.createWriteStream(filename)).on('close', callback);&lt;br&gt;
    });&lt;br&gt;
  }`&lt;/p&gt;

&lt;p&gt;A click of the Recognize button triggers an AJAX call to the Recognize route, which recognizes the images through the &lt;code&gt;FaceRecognizer&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;Finally, send the response in a new browser window. See the code below.&lt;/p&gt;

&lt;p&gt;`router.get('/recognize',function(req,res){&lt;br&gt;
  const recognizer = fr.FaceRecognizer();&lt;br&gt;
  /*&lt;br&gt;
  Load Our Previously Saved Train Data&lt;br&gt;
  &lt;em&gt;/&lt;br&gt;
  const modelState = require('../model.json');&lt;br&gt;
  recognizer.load(modelState);&lt;br&gt;
  /&lt;/em&gt;&lt;br&gt;
  Detect face from image&lt;br&gt;
  */&lt;br&gt;
  const image = fr.loadImage('./tmp/uploads/out.png');&lt;br&gt;
  const detector = fr.FaceDetector();&lt;br&gt;
  const targetSize = 150;&lt;br&gt;
  const faceImage = detector.detectFaces(image, targetSize);&lt;/p&gt;

&lt;p&gt;/*&lt;br&gt;
  Draw rectangle on face&lt;br&gt;
  and write a prediction for each face&lt;br&gt;
  */&lt;br&gt;
  const faceRects  = detector.locateFaces(image).map(mmodRect =&amp;gt; mmodRect.rect);&lt;br&gt;
  const faces = detector.getFacesFromLocations(image, faceRects, 150);&lt;/p&gt;

&lt;p&gt;if(faceRects.length){&lt;br&gt;
    const win= new fr.ImageWindow();&lt;br&gt;
    win.setImage(image);&lt;br&gt;
    faceRects.forEach((rect,i)=&amp;gt;{&lt;br&gt;
    win.addOverlay(rect);&lt;br&gt;
    const predict = recognizer.predict Best(faces[i],0.69);&lt;br&gt;
    win.addOverlay(rect, &lt;code&gt;${predict.className} (${predict.distance})&lt;/code&gt;);&lt;br&gt;
  });&lt;br&gt;
    // fr.hitEnterToContinue();&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;/*&lt;br&gt;
  Send the output for a face to an HTML page&lt;br&gt;
  */&lt;br&gt;
  if(faceImage.length){&lt;br&gt;
  const predictions=recognizer.predict(faceImage[0]);&lt;br&gt;
  res.send(predictions);&lt;br&gt;
  }&lt;br&gt;
  else{&lt;br&gt;
    res.status(400).json({msg:'Could Not Detect Face, Please try another &lt;br&gt;
  picture'});&lt;br&gt;
  }&lt;br&gt;
});`&lt;/p&gt;

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

&lt;p&gt;Presently, major tech companies, such as Apple, are keenly interested in and adopting the facial-recognition technology. AI startups, too, are becoming unicorns. Without a doubt, facial recognition will play a more and more prominent role in society in the near future. Concerns about privacy notwithstanding, facial recognition makes our streets, homes, banks, and shops safer—and more efficient,  too.&lt;/p&gt;

&lt;p&gt;For details of the facial-recognition project described in this post, see the &lt;a href="https://github.com/musebe/Face-Recognition" rel="noopener noreferrer"&gt;GitHub code&lt;/a&gt;. Contributions and suggestions are welcome.&lt;/p&gt;

</description>
      <category>node</category>
      <category>cloudinary</category>
      <category>facejs</category>
    </item>
    <item>
      <title>Get On Board With the Media Express</title>
      <dc:creator>eugene musebe</dc:creator>
      <pubDate>Tue, 12 Mar 2019 20:08:20 +0000</pubDate>
      <link>https://dev.to/musebe/get-on-board-with-the-media-express-5h1k</link>
      <guid>https://dev.to/musebe/get-on-board-with-the-media-express-5h1k</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fk18xm2azna0k21llj24g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fk18xm2azna0k21llj24g.png" alt="Alt Image Uploads $ Retrievals"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In today’s online world, the delivery speed of your eCommerce web and mobile apps is a paramount factor in user experience. If your customers become frustrated by a lengthy load time for your website, they might stop visiting it, putting your online presence at risk. The fact is, people judge your brand by how well they can interact with your web and mobile apps before contacting you in person.&lt;/p&gt;

&lt;p&gt;For web developers, managing digital assets, such as videos, photos, music, and other multimedia, is a must-do. Poor handling of that task might lead to slow performance of your apps, causing a dismal user experience.&lt;/p&gt;

&lt;p&gt;No worries,&lt;a href="https://cloudinary.com/" rel="noopener noreferrer"&gt;Cloudinary&lt;/a&gt; is here to the rescue.&lt;/p&gt;

&lt;p&gt;Cloudinary is a cloud-based platform for managing images and videos, enabling businesses and developers to focus on their specialties. In fact, management of digital assets is Cloudinary’s core business.&lt;/p&gt;

&lt;p&gt;This article steps you through the process of developing a simple, web-based app that creates, reads, and deletes media from the Cloudinary servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing NPM
&lt;/h2&gt;

&lt;p&gt;To start, download the most stable release of the Node.js binaries from &lt;a&gt;&lt;code&gt;https://nodejs.org&lt;/code&gt;&lt;/a&gt;.Afterwards, install them on your machine by following the procedure on the page that pertains to your platform.&lt;/p&gt;

&lt;p&gt;To confirm the installation, type these two commands:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;node -v&lt;/code&gt;&lt;br&gt;
&lt;code&gt;npm -v&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The output displays the version numbers of your Node.js and the Node Package Manager (NPM), a tool for installing, uninstalling, and maintaining package modules for apps.&lt;/p&gt;
&lt;h2&gt;
  
  
  Initializing a New App
&lt;/h2&gt;

&lt;p&gt;A basic Node app contains a &lt;code&gt;.js&lt;/code&gt; file and a &lt;code&gt;package.json&lt;/code&gt; file, which does the following :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specifies the packages on which your project depends,&lt;/li&gt;
&lt;li&gt;Lists the versions of a package that your project can use according to the 
&lt;a&gt;&lt;code&gt;semantic versioning&lt;/code&gt;&lt;/a&gt;rules.&lt;/li&gt;
&lt;li&gt;Makes your build reproducible, hence easier to share with other developers.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To generate a &lt;code&gt;package.json&lt;/code&gt; file for your app, navigate to your project folder in a terminal or, for Windows users, in Git Bash, and type the following command:&lt;/p&gt;

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

&lt;p&gt;Running the above command without the flag &lt;code&gt;-y&lt;/code&gt; generates questions that prompt for answers from you, which would clearly describe the app and its dependencies.&lt;/p&gt;
&lt;h2&gt;
  
  
  Installing the Required Dependencies
&lt;/h2&gt;

&lt;p&gt;Run this command to install the required dependencies:&lt;br&gt;
&lt;code&gt;npm install express body-parser multer express-handlebars moment dotenv cloudinary --save&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Below are the dependencies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;express&lt;/code&gt;&lt;/strong&gt;: A web-app framework for Node.js.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;body-parser&lt;/code&gt;&lt;/strong&gt;: A middleware that handles post requests in &lt;code&gt;express&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;multer&lt;/code&gt;&lt;/strong&gt;: The Node.js middleware for handling multipart &lt;code&gt;FormData&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;express-handlebars&lt;/code&gt;&lt;/strong&gt;: A Handlebars view-engine for &lt;code&gt;express&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;moment&lt;/code&gt;&lt;/strong&gt;: A lightweight JavaScript date-library for parsing, validating, manipulating, and formatting dates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;dotenv&lt;/code&gt;&lt;/strong&gt;: A module that loads environment variables from a &lt;code&gt;.env&lt;/code&gt; file into the &lt;code&gt;process.env&lt;/code&gt; property.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;code&gt;cloudinary&lt;/code&gt;&lt;/strong&gt;: A Node.js wrapper that enables you to communicate with the Cloudinary servers.&lt;br&gt;
Once the dependency packages are in place, edit the &lt;code&gt;package.json&lt;/code&gt; file to read like this:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fj8lfpp11wvvyh7b3dl26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fj8lfpp11wvvyh7b3dl26.png" alt="Alt package.json"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As specified in the file, the entry point to your app is the &lt;code&gt;server.js&lt;/code&gt; file. That is where you will document most of the logic on which the app depends.&lt;/p&gt;
&lt;h2&gt;
  
  
  Starting the Server
&lt;/h2&gt;

&lt;p&gt;Next, start the server by adding the following code to the &lt;code&gt;server.js&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const express = require("express");&lt;br&gt;
const app = express();&lt;br&gt;
app.get("/", (req, res) =&amp;gt; res.send("Hello Cloudy"));&lt;br&gt;
const PORT = process.env.PORT || 5000;&lt;br&gt;
app.listen(PORT, () =&amp;gt; {&lt;br&gt;
 console.log(&lt;/code&gt;Server running on ${PORT}&lt;code&gt;);&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Aftwards, start your app by running this command:&lt;br&gt;
&lt;code&gt;node server.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now go to &lt;code&gt;localhost:5000&lt;/code&gt; on your browser to verify that the string &lt;code&gt;Hello Cloudy&lt;/code&gt; is displayed.&lt;/p&gt;
&lt;h2&gt;
  
  
  Building the Project Structure
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;express-handlebars&lt;/code&gt; is your default templating engine on the front end. To make use of it, do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Register the templating engine’s packages by adding the following code to your &lt;code&gt;server.js&lt;/code&gt; file:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;const exphbs = require('express-handlebars');&lt;br&gt;
app.engine('handlebars', exphbs({defaultLayout: 'main'}));&lt;br&gt;
app.set('view engine', 'handlebars');&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;2.Enclose all the front-end files in a folder called &lt;code&gt;views&lt;/code&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the &lt;code&gt;views&lt;/code&gt; folder, create another folder and name it &lt;code&gt;layouts&lt;/code&gt;, in which the &lt;code&gt;main.handlebars&lt;/code&gt; file, which contains your app’s front-end structure, resides.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your app’s project structure now looks like this:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8pdm8kkg6bht1fqx6uw0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8pdm8kkg6bht1fqx6uw0.png" alt="Alt file_structure"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Adding Content to the &lt;code&gt;main.js&lt;/code&gt; and &lt;code&gt;index.handlebars&lt;/code&gt; Files
&lt;/h2&gt;

&lt;p&gt;Add the following code to the &lt;code&gt;main.js&lt;/code&gt; file:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;With the Moustache symbol &lt;code&gt;{{body}}&lt;/code&gt;, you can seamlessly invoke other pages into the main body.&lt;/p&gt;

&lt;p&gt;Next, go to the root of the &lt;code&gt;views&lt;/code&gt; folder, create an &lt;code&gt;index.handlebars&lt;/code&gt; file, and then add a media-upload form with the following code to the file:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Afterwards, run the app on &lt;code&gt;localhost:5000&lt;/code&gt; on the browser and verify that the form below is displayed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwe5qdu9xcq0z4thzsq8d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fwe5qdu9xcq0z4thzsq8d.png" alt="Alt frontend"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Multer
&lt;/h2&gt;

&lt;p&gt;Recall that you installed Multer earlier. That’s a Node.js middleware for uploading or handling multipart &lt;code&gt;FormData&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To configure Multer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the root of your app, create a folder called &lt;code&gt;handlers&lt;/code&gt; for storing the configurations for Multer and other packages.&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;handlers&lt;/code&gt; folder, create a file called &lt;code&gt;multer.js&lt;/code&gt; with this configuration code:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;const multer = require("multer");module.exports = multer({&lt;br&gt;
 storage: multer.diskStorage({}),&lt;br&gt;
 fileFilter: (req, file, cb) =&amp;gt; {&lt;br&gt;
   if (!file.mimetype.match(/jpe|jpeg|png|gif$i/)) {&lt;br&gt;
     cb(new Error("File is not supported"), false);&lt;br&gt;
     return;&lt;br&gt;
   }cb(null, true);&lt;br&gt;
 }&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Next, export &lt;code&gt;multer.js&lt;/code&gt; to the main &lt;code&gt;server.js&lt;/code&gt; file by adding this codeline to &lt;code&gt;server.js&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const upload = require("./handlers/multer");&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then edit the upload route to read like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.post("/uploads", upload.single("image"), (req, res) =&amp;gt; {res.send(req.file);});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The above steps ensure that when you upload a media file, you can capture the content of the request on the &lt;code&gt;/uploads&lt;/code&gt; route, as shown here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9uitoap73hq0xtb731vr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F9uitoap73hq0xtb731vr.gif" alt="Alt frontend"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Uploading Media to Cloudinary
&lt;/h2&gt;

&lt;p&gt;The project is now ready for file uploads to Cloudinary. Perform the steps below.&lt;/p&gt;
&lt;h3&gt;
  
  
  Initializing the Cloudinary SDK
&lt;/h3&gt;

&lt;p&gt;First, initialize the Cloudinary SDK into the project by adding this codeline to the main &lt;code&gt;server.js&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const cloudinary = require("cloudinary");&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Storing and Securing Cloudinary API Keys
&lt;/h3&gt;

&lt;p&gt;To use Cloudinary, you must store its API key, cloud name, and cloud secret in your app. Those keys identify the app or user who’s accessing the Cloudinary servers.&lt;br&gt;
Secure the keys with the &lt;code&gt;dotenv&lt;/code&gt; package. Even though you can store and use keys without packages, the packages are of great help in managing the keys.&lt;/p&gt;

&lt;p&gt;To prepare &lt;code&gt;dotenv&lt;/code&gt; for use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add these two lines to your &lt;code&gt;server.js&lt;/code&gt; file:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;require("dotenv").config();&lt;br&gt;
require("./handlers/cloudinary");&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The second codeline above calls for a &lt;code&gt;cloudinary.js&lt;/code&gt; file in the &lt;code&gt;handlers&lt;/code&gt; folder.&lt;br&gt;
2.Create a &lt;code&gt;cloudinary.js&lt;/code&gt; file  in the &lt;code&gt;handlers&lt;/code&gt; folder with the following content:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const cloudinary = require("cloudinary");&lt;br&gt;
cloudinary.config({&lt;br&gt;
 cloud_name: process.env.CLOUD_NAME,&lt;br&gt;
 api_key: process.env.API_ID,&lt;br&gt;
 api_secret: process.env.API_SECRET&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;With this file, the app can locate your server’s access keys that are stored in the &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;3.Go to the root of the app and create the &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;If your &lt;code&gt;.env&lt;/code&gt; file contains confidential values, such as keys, secrets, and passwords, place it in the &lt;code&gt;.gitignore&lt;/code&gt; folder to prevent it from being committed it to the GitHub repository.&lt;/p&gt;

&lt;p&gt;Afterwards, declare your credentials in the &lt;code&gt;.env&lt;/code&gt; file by adding the following code to it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CLOUD_NAME= your_cloud_name&lt;br&gt;
API_ID= id&lt;br&gt;
API_SECRET= secret&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To get the values for those three credentials, first &lt;a href="https://cloudinary.com/users/register/free" rel="noopener noreferrer"&gt;register&lt;/a&gt; for a Cloudinary account. Once you are logged in, you’ll see the credential values on your Dashboard. Here’s an example:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjgwz57ui5mlmlfdj9jud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjgwz57ui5mlmlfdj9jud.png" alt="Alt dashboard"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Configuring the &lt;code&gt;/Uploads&lt;/code&gt; Route
&lt;/h3&gt;

&lt;p&gt;For details on how to perform create, read, update, and delete (CRUD) operations to and from the Cloudinary servers, see the related documentation.&lt;/p&gt;

&lt;p&gt;To enable file uploads, configure the &lt;code&gt;post “/uploads”&lt;/code&gt; route, like this:&lt;/p&gt;

&lt;p&gt;`app.post("/uploads", upload.single("image"), async (req, res) =&amp;gt; {&lt;br&gt;
const result = await cloudinary.v2.uploader.upload(req.file.path);&lt;br&gt;
res.send(result);&lt;/p&gt;

&lt;p&gt;});`&lt;/p&gt;

&lt;p&gt;With that configuration, Cloudinary would store the media files that you submit and return to you an object that spells out the properties of those files. See the example below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftke6fw9w6edgcr4rogj5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ftke6fw9w6edgcr4rogj5.gif" alt="Alt upload"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Setting Up the Cloudinary Upload Widget
&lt;/h3&gt;

&lt;p&gt;In case you worry that uploading media to the Cloudinary servers might take up an inordinate amount of time, worry no more. Cloudinary’s -upload widget renders file uploads a fast process.  For details of the widget, see the related documentation.&lt;/p&gt;

&lt;p&gt;Follow these steps to set up the upload widget: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add a button to your form with the value of the ID (&lt;code&gt;id&lt;/code&gt;) specified as 
&lt;code&gt;upload_widget_opener&lt;/code&gt;, like this:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;input value="Upload with Cloudinary Widget" id="upload_widget_opener" &lt;br&gt;
   class="btn btn-primary btn-block"&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Add this script to the &lt;code&gt;main.handlebars&lt;/code&gt; file to load the widget:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;script src="//widget.cloudinary.com/global/all.js" type="text/javascript"&amp;gt; &lt;br&gt;
   &amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up a handler to listen to a click event of the button element on the web page and then call the widget's &lt;code&gt;open&lt;/code&gt; method to display the initialized widget. Below is the sample code.&lt;/li&gt;
&lt;/ol&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Finally, change your upload presets from signed to unsigned. To do so, choose Settings &amp;gt; Upload Tab &amp;gt; Upload Presets and make the change in the dialog box that is displayed.&lt;/p&gt;

&lt;p&gt;You can now upload media with Cloudinary’s upload widget.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fhsdxhkbcjx8qe2nyshwn.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fhsdxhkbcjx8qe2nyshwn.gif" alt="Alt Image Uploads $ Retrievals"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Retrieving Stored Media From Cloudinary in JSON Format
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;server.js&lt;/code&gt; file, define a &lt;code&gt;GET “/api/files”&lt;/code&gt; endpoint to call all the files you have stored in Cloudinary. Add the following code:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.get("/api/files", async (req, res) =&amp;gt; {&lt;br&gt;
const images = await cloudinary.v2.api.resources({&lt;br&gt;
type: "upload",&lt;br&gt;
prefix: "image"&lt;br&gt;
});&lt;br&gt;
return res.json(images);&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Afterwards, go to localhost:5000/api/ files on your browser for a display of all your stored files in Cloudinary.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn4jozknlhgyhiit677vh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fn4jozknlhgyhiit677vh.png" alt="Alt Api"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Displaying Your Stored Files on the Front End
&lt;/h2&gt;

&lt;p&gt;To display your stored files on the front end, send a GET request to the Cloudinary storage, which will then return an object with all the stored data for conversion into a format that suits the app. For this app, target the &lt;code&gt;secure_url&lt;/code&gt; and &lt;code&gt;created_at&lt;/code&gt; fields. &lt;/p&gt;

&lt;p&gt;Create another endpoint in your &lt;code&gt;server.js&lt;/code&gt; file with the following format:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.get("/files", async (req, res) =&amp;gt; {&lt;br&gt;
 const images = await cloudinary.v2.api.resources({&lt;br&gt;
   type: "upload",&lt;br&gt;
   prefix: "image"&lt;br&gt;
 });&lt;br&gt;
 // Check if files&lt;br&gt;
 if (!images || images.length === 0) {&lt;br&gt;
   return res.status(404).json({&lt;br&gt;
     err: "No files exist"&lt;br&gt;
   });&lt;br&gt;
 }&lt;br&gt;
// Files exist&lt;br&gt;
 res.render("files", {&lt;br&gt;
   images: images&lt;br&gt;
 });&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can now render all the media on the &lt;code&gt;/files&lt;/code&gt; route on the browser. However, for that to happen, you must first create the endpoint in the &lt;code&gt;views&lt;/code&gt; folder and add logic to it to loop and format the responses you receive.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;views&lt;/code&gt; folder, create a &lt;code&gt;files.handlebars&lt;/code&gt; file with the following code:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;Recall that you’re targeting the &lt;code&gt;url&lt;/code&gt; and &lt;code&gt;created_at&lt;/code&gt; endpoints from the server. The code above displays all your media by means of bootstrap cards after looping through the media with the Handlebars’ looping technique.&lt;/p&gt;

&lt;p&gt;You’ll now see the following response when you access the route:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpqhw3uh8kv97ai9y4n73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fpqhw3uh8kv97ai9y4n73.png" alt="Alt Api"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Deleting Files
&lt;/h2&gt;

&lt;p&gt;You can easily delete a media file  by passing its ID (&lt;code&gt;id&lt;/code&gt;) in a request, as shown in this example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;app.delete("/files", (req, res) =&amp;gt; {&lt;br&gt;
let id = req.body.id;&lt;br&gt;
cloudinary.v2.api.delete_resources([id], function(error, result) {console.log(result);});&lt;br&gt;
});&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By setting cloudinary.v2.api.delete_resource(), you can capture the ID of the selected media file and delete that file from Cloudinary.&lt;/p&gt;

&lt;p&gt;Earlier, on the bootstrap card, you added a button to initiate the delete operation when clicked. Complete that setup by adding the following script under the bootstrap card on the &lt;code&gt;files.handlebars&lt;/code&gt; route:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;br&gt;
deleteImage = () =&amp;gt; {&lt;br&gt;
const imageClickedID = event.target.id&lt;br&gt;
fetch(&lt;/code&gt;/files&lt;code&gt;, {&lt;br&gt;
method: 'DELETE',&lt;br&gt;
headers: { 'Content-Type': 'application/json' },&lt;br&gt;
body: JSON.stringify({ id: imageClickedID })&lt;br&gt;
})&lt;br&gt;
.then(location.reload())&lt;br&gt;
.catch(err =&amp;gt; console.log(err))&lt;br&gt;
}&lt;br&gt;
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There! Now you can delete the selected file from Cloudinary by clicking the Delete button.&lt;/p&gt;

&lt;h2&gt;
  
  
  Formatting the Date With Moment.Js
&lt;/h2&gt;

&lt;p&gt;The only remaining task is to set up the date and time in a readable format. Do that with a package called &lt;code&gt;moment&lt;/code&gt;, a lightweight JavaScript date-library for parsing, validating, manipulating, and formatting dates.&lt;/p&gt;

&lt;p&gt;You’ve already pulled the package to the project. Now do the following:&lt;br&gt;
Initialize &lt;code&gt;moment&lt;/code&gt; into the project with this codeline:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;const moment = require("moment");&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Call the &lt;code&gt;moment&lt;/code&gt; variable for the date-format values by navigating to the line in which you declared your default layout and adding a helper` function:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;helpers: {&lt;br&gt;
renderDateFormat: function(time) {&lt;br&gt;
return moment(time).format("MMMM Do YYYY");}&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;files.handlebar&lt;/code&gt; file and add &lt;code&gt;renderDateFormat&lt;/code&gt; within  the Handlebars&lt;code&gt; &lt;/code&gt;created_at` helper. Your helper then reads like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{{renderDateFormat created_at}}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Your app is now all set,  resembling the one hosted on Heroku.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking Out the References
&lt;/h2&gt;

&lt;p&gt;Managing digital media with Express, Multer, and Cloudinary is a painless, seamless, and simple process. In particular, Cloudinary’s robust features greatly accelerate software development that involves digital media. The &lt;a href="https://cloudinary.com/documentation" rel="noopener noreferrer"&gt;Cloudinary documentation&lt;/a&gt; contains all the details.&lt;br&gt;
Additionally, feel free to clone and modify the &lt;a href="https://github.com/musebe/Cloudy_Crud" rel="noopener noreferrer"&gt;source code on GitHub&lt;/a&gt;. Have fun!&lt;/p&gt;

</description>
      <category>express</category>
      <category>multer</category>
      <category>cloudinary</category>
    </item>
  </channel>
</rss>
