<?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>Forem: Emily Johnson</title>
    <description>The latest articles on Forem by Emily Johnson (@yeagoo).</description>
    <link>https://forem.com/yeagoo</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%2F3637604%2Fcf556c47-9c94-4b65-a5e5-58d3ef3a3a84.png</url>
      <title>Forem: Emily Johnson</title>
      <link>https://forem.com/yeagoo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/yeagoo"/>
    <language>en</language>
    <item>
      <title>Cloudflare R2 Hands-On Guide: Set Up Free 10GB Storage, Zero-Egress Object Storage, and S3-Compatible API Keys</title>
      <dc:creator>Emily Johnson</dc:creator>
      <pubDate>Tue, 09 Dec 2025 16:08:25 +0000</pubDate>
      <link>https://forem.com/yeagoo/cloudflare-r2-hands-on-guide-set-up-free-10gb-storage-zero-egress-object-storage-and-325n</link>
      <guid>https://forem.com/yeagoo/cloudflare-r2-hands-on-guide-set-up-free-10gb-storage-zero-egress-object-storage-and-325n</guid>
      <description>&lt;p&gt;In a modern full-stack (or &lt;em&gt;vibe coding&lt;/em&gt;) stack, even though Supabase ships with Storage and Vercel offers free Blob quotas, many developers (including &lt;a href="https://hicyou.com/" rel="noopener noreferrer"&gt;HiCyou&lt;/a&gt;) still prefer &lt;strong&gt;Cloudflare R2&lt;/strong&gt; as the primary storage layer for SaaS projects.&lt;/p&gt;

&lt;p&gt;The main reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;R2 is &lt;strong&gt;fully compatible with the S3 API&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Most importantly, it offers &lt;strong&gt;zero egress fees&lt;/strong&gt;. That means no matter how many times users download images or files from your app, you don’t get hit with surprise bandwidth bills. (There &lt;em&gt;are&lt;/em&gt; request charges, but they’re very low in practice.) This is huge for SaaS scalability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For early-stage indie founders, R2’s free tier is extremely generous: &lt;strong&gt;10GB of free storage, free egress, and plenty of free requests&lt;/strong&gt;, which is ideal for launching projects at basically zero infrastructure cost.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Creating an R2 bucket&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Generating S3-compatible API credentials&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuring a custom domain for public access&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 1: Create Your R2 Bucket
&lt;/h2&gt;

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

&lt;p&gt;Before you begin, make sure you have a Cloudflare account.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to the &lt;strong&gt;&lt;a href="https://dash.cloudflare.com/" rel="noopener noreferrer"&gt;Cloudflare Dashboard&lt;/a&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;In the sidebar, find and click &lt;strong&gt;R2&lt;/strong&gt;.

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Note: If this is your first time using R2, Cloudflare may ask you to add a payment method. R2 still offers a very generous free tier (10GB storage + millions of requests per month), but a credit card or PayPal is usually required to activate the service.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;“Create bucket”&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Configure the Bucket
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bucket Name:&lt;/strong&gt; Enter a unique name (for example, &lt;code&gt;hicyou-assets&lt;/code&gt; or &lt;code&gt;my-saas-uploads&lt;/code&gt;).

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Tip: Only lowercase letters, numbers, and hyphens are allowed.&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Location:&lt;/strong&gt; You can leave this as &lt;code&gt;Automatic&lt;/code&gt;. Cloudflare’s global network will handle edge routing and optimization for you.&lt;/li&gt;

&lt;li&gt;Click &lt;strong&gt;“Create Bucket”&lt;/strong&gt;.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;You now have an R2 bucket. At this point, it’s still &lt;strong&gt;private&lt;/strong&gt; – your code and your users can’t access it yet.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Generate API Keys (S3 Credentials)
&lt;/h2&gt;

&lt;p&gt;To let your application (Node.js, Python, Go, etc.) upload and read files, you need credentials. Since R2 is S3-compatible, you’ll need an &lt;strong&gt;Access Key ID&lt;/strong&gt; and &lt;strong&gt;Secret Access Key&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt; Don’t look for these inside the bucket itself. They’re configured in the &lt;strong&gt;R2 account-level settings&lt;/strong&gt;, not under a specific bucket.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;ol&gt;
&lt;li&gt;Go back to the &lt;strong&gt;R2 Overview&lt;/strong&gt; page.&lt;/li&gt;
&lt;li&gt;On the right sidebar, under &lt;strong&gt;“Account Details”&lt;/strong&gt;, click the &lt;code&gt;{} Manage&lt;/code&gt; button.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;“Create User API Token”&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Permission Wizard
&lt;/h3&gt;

&lt;p&gt;To make sure your app can read and write objects correctly, configure the token like this:&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Token Name:&lt;/strong&gt; Use a descriptive name (for example, &lt;code&gt;Production App Read/Write&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Permissions:&lt;/strong&gt; Select &lt;strong&gt;Object Read &amp;amp; Write&lt;/strong&gt;.

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Security tip:&lt;/em&gt; For app credentials, avoid using full &lt;strong&gt;Admin&lt;/strong&gt; permissions. &lt;strong&gt;Object Read &amp;amp; Write&lt;/strong&gt; is safer and typically all you need.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Specific Bucket(s):&lt;/strong&gt; Choose &lt;strong&gt;“Apply to specific buckets only”&lt;/strong&gt; and select the bucket you just created (for example, &lt;code&gt;hicyou-assets&lt;/code&gt;).&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;TTL:&lt;/strong&gt; Choose &lt;strong&gt;“Forever”&lt;/strong&gt; (unless you already have a key rotation policy in place).&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Click &lt;strong&gt;“Create User API Token”&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fs.w.org%2Fimages%2Fcore%2Femoji%2F17.0.2%2Fsvg%2F26a0.svg" alt="⚠️" width="36" height="36"&gt; Important: Save Your Keys Immediately
&lt;/h3&gt;

&lt;p&gt;Cloudflare will only show you the &lt;strong&gt;Secret Key once&lt;/strong&gt;. If you close the page, you won’t be able to view it again.&lt;/p&gt;

&lt;p&gt;Copy and store the following values in your &lt;code&gt;.env&lt;/code&gt; file or password manager:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Access Key ID&lt;/strong&gt; (e.g. &lt;code&gt;f82b...&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Secret Access Key&lt;/strong&gt; (e.g. &lt;code&gt;8d9a...&lt;/code&gt; – a long random string)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Endpoint&lt;/strong&gt; – your S3-compatible endpoint, typically something like:https://.r2.cloudflarestorage.com&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Developer tip:&lt;/strong&gt; When configuring an S3 client (AWS SDK, MinIO, etc.), the &lt;strong&gt;Endpoint&lt;/strong&gt; usually does &lt;strong&gt;not&lt;/strong&gt; include the bucket name. The client will add the bucket to the URL automatically when making requests.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 3: Enable Public Access (Custom Domain)
&lt;/h2&gt;

&lt;p&gt;By default, objects in R2 are private. If you want users to view images (avatars, blog cover images, etc.) directly in their browser, you need to enable some form of public access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practice: Use Your Own Custom Domain
&lt;/h3&gt;

&lt;p&gt;Avoid using the default &lt;code&gt;*.r2.dev&lt;/code&gt; domain in production – it has strict rate limits. Instead, bind a domain you control.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Open your &lt;strong&gt;Bucket&lt;/strong&gt; and go to the &lt;strong&gt;Settings&lt;/strong&gt; tab.&lt;/li&gt;
&lt;li&gt;Scroll down to &lt;strong&gt;Public Access&lt;/strong&gt; → &lt;strong&gt;Custom Domains&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;“Connect Domain”&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Enter a subdomain such as &lt;code&gt;cdn.hicyou.com&lt;/code&gt; or &lt;code&gt;assets.myapp.com&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Cloudflare will automatically create and configure the necessary DNS records for you.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now, if you upload a file named &lt;code&gt;logo.png&lt;/code&gt;, users can access it via:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://assets.hicyou.com/logo.png
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 4: Configure CORS (For Direct Uploads from the Frontend)
&lt;/h2&gt;

&lt;p&gt;If you want your frontend (React, Next.js, Vue, etc.) to &lt;strong&gt;upload directly to R2&lt;/strong&gt; instead of proxying through your backend, you must configure &lt;strong&gt;CORS (Cross-Origin Resource Sharing)&lt;/strong&gt; for your bucket.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In your &lt;strong&gt;Bucket Settings&lt;/strong&gt; page.&lt;/li&gt;
&lt;li&gt;Scroll down to &lt;strong&gt;CORS Policy&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Add JSON similar to the following to allow both local development and your production domains:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "AllowedOrigins": [
      "http://localhost:3000",
      "https://hicyou.com",
      "https://www.hicyou.com"
    ],
    "AllowedMethods": [
      "GET",
      "PUT",
      "POST",
      "DELETE",
      "HEAD"
    ],
    "AllowedHeaders": [
      "*"
    ],
    "ExposeHeaders": [],
    "MaxAgeSeconds": 3000
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Combined with the previous Supabase guide, you now have two core pieces of infrastructure ready for your SaaS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Postgres&lt;/strong&gt; (via Supabase) for your database&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cloudflare R2&lt;/strong&gt; for object storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both are battle-tested, highly cost-effective options for indie devs and small teams.&lt;/p&gt;

&lt;p&gt;You’re welcome to use &lt;a href="https://github.com/hicyoucom/hicyou" rel="noopener noreferrer"&gt;https://github.com/hicyoucom/hicyou&lt;/a&gt; to spin up your own AI-powered link directory site.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo:&lt;/strong&gt; &lt;a href="https://hicyou.com/" rel="noopener noreferrer"&gt;https://hicyou.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://startupfa.me/s/hi-cyou" rel="noopener noreferrer"&gt;https://startupfa.me/s/hi-cyou&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cloudflarechallenge</category>
      <category>webdev</category>
      <category>cloud</category>
      <category>programming</category>
    </item>
    <item>
      <title>A Practical Guide to Supabase: Setting up a Database, Auth, and Integrating Resend</title>
      <dc:creator>Emily Johnson</dc:creator>
      <pubDate>Mon, 08 Dec 2025 16:19:21 +0000</pubDate>
      <link>https://forem.com/yeagoo/a-practical-guide-to-supabase-setting-up-a-database-auth-and-integrating-resend-obe</link>
      <guid>https://forem.com/yeagoo/a-practical-guide-to-supabase-setting-up-a-database-auth-and-integrating-resend-obe</guid>
      <description>&lt;p&gt;In modern full-stack development and &lt;em&gt;vibe coding&lt;/em&gt; workflows, &lt;strong&gt;Supabase&lt;/strong&gt; is no longer just “the open-source Firebase alternative” – it’s become a full development platform. You get a production-grade Postgres database plus powerful Auth, auto-generated APIs, and real-time subscriptions.&lt;/p&gt;

&lt;p&gt;That’s why &lt;a href="https://hicyou.com/" rel="noopener noreferrer"&gt;HiCyou&lt;/a&gt; uses Supabase as both its database and Auth solution.&lt;/p&gt;

&lt;p&gt;One common pain point, though, is handling &lt;strong&gt;email confirmation for user sign-ups&lt;/strong&gt;. Supabase’s built-in email service is great for quick tests, but it has a low sending limit and often lands in the spam folder.&lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Registering and creating a Supabase project&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enabling and configuring Auth&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integrating Resend&lt;/strong&gt; (one of the most popular email services for developers today) so your verification emails actually reach inboxes reliably.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 1: Create Your Supabase Database
&lt;/h2&gt;

&lt;p&gt;First, you’ll need a Supabase organization.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;supabase.com&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Sign in with GitHub or register with email.&lt;/li&gt;
&lt;li&gt;Create an organization and choose a plan. For a new project, the &lt;strong&gt;Free Plan&lt;/strong&gt; is usually more than enough. When you eventually need to upgrade, it typically means your product is doing pretty well.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;Next, create a project:&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Fill in project details:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; Give your project a name (for example, &lt;code&gt;My SaaS App&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Database Password:&lt;/strong&gt; &lt;strong&gt;Write this down somewhere safe.&lt;/strong&gt; This is your main database password and you won’t be able to view it again later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Region:&lt;/strong&gt; Pick a region close to your users (for example, if your users are in Asia, &lt;code&gt;Singapore&lt;/code&gt; or &lt;code&gt;Tokyo&lt;/code&gt; is usually a good choice).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Create new project"&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step three is to understand how to connect to your database:&lt;/p&gt;

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

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

&lt;ol&gt;
&lt;li&gt;Click the &lt;strong&gt;&lt;code&gt;Connect&lt;/code&gt;&lt;/strong&gt; button at the top.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Method&lt;/strong&gt;, select &lt;strong&gt;&lt;code&gt;Transaction pooler&lt;/code&gt;&lt;/strong&gt;. This option works well across both IPv4 and IPv6 environments and is generally more compatible with various servers and local dev setups.&lt;/li&gt;
&lt;li&gt;Copy the connection string, and remember to replace &lt;code&gt;[YOUR-PASSWORD]&lt;/code&gt; with the database password you just set.&lt;/li&gt;
&lt;/ol&gt;

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




&lt;h2&gt;
  
  
  Step 2: Configure Auth (Authentication)
&lt;/h2&gt;

&lt;p&gt;Building a proper user system – especially the login flow – is harder than it looks. Implementing basic signup and login is easy; what’s difficult is making the system &lt;strong&gt;secure, reliable, and resistant to abusive mass registrations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Supabase Auth gives you a solid infrastructure for this. If you build on top of it, you can pretty quickly get to a login system that’s “about 9/10” in terms of security without reinventing everything yourself.&lt;/p&gt;

&lt;p&gt;Once your project is created, you’ll land in the Dashboard. Supabase enables Auth by default, but we’ll double-check the settings.&lt;/p&gt;

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

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

&lt;ol&gt;
&lt;li&gt;In the left sidebar, click &lt;strong&gt;Authentication&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Sign In / Providers&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;You’ll see that &lt;strong&gt;Email&lt;/strong&gt; is &lt;code&gt;Enabled&lt;/code&gt; by default.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default email behavior:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;If you don’t configure a custom SMTP server, Supabase will send emails from &lt;code&gt;noreply@mail.app.supabase.io&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The catch:&lt;/strong&gt; This default sender is convenient, but it has strict hourly sending limits and a high chance of landing in Gmail/Outlook spam folders. That’s exactly why we want to integrate &lt;strong&gt;Resend&lt;/strong&gt; instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Enable Google, GitHub, etc. Login
&lt;/h3&gt;

&lt;p&gt;GitHub and Google are two of the most common login options for developers, and enabling them already covers a large portion of users’ expectations.&lt;/p&gt;

&lt;p&gt;Click the corresponding provider icon – we’ll use GitHub as an example here:&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;Click the &lt;strong&gt;GitHub Enabled&lt;/strong&gt; toggle/button, then copy the &lt;strong&gt;Callback URL&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Go to &lt;a href="https://github.com/settings/apps/new" rel="noopener noreferrer"&gt;https://github.com/settings/apps/new&lt;/a&gt; and create a new GitHub App.&lt;/li&gt;
&lt;/ol&gt;

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

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

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Register application&lt;/strong&gt; to create the OAuth app.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Generate a new client secret&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

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

&lt;ol&gt;
&lt;li&gt;Copy the &lt;strong&gt;Client ID&lt;/strong&gt; and &lt;strong&gt;Client secret&lt;/strong&gt; back into the GitHub provider settings in Supabase Auth and save.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 3: Integrate Resend Email Service (Key Step)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Resend&lt;/strong&gt; is currently one of the best email sending services for developers: simple API, great DX, and excellent deliverability. Supabase’s own docs also recommend using it to take over email sending.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 Set Things Up in Resend
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://resend.com/" rel="noopener noreferrer"&gt;resend.com&lt;/a&gt; and sign up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a domain:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Add a domain you own (for example, &lt;code&gt;myapp.com&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Important:&lt;/strong&gt; Resend will show you several DNS records (DKIM, SPF, DMARC). Go to your DNS provider (Cloudflare, GoDaddy, Namecheap, etc.) and add these as TXT records.&lt;/li&gt;
&lt;li&gt;Wait for verification to pass (typically anywhere from a few minutes to a few hours).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Get an API Key:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;In the Resend dashboard, go to &lt;strong&gt;API Keys&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Create API Key&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose permission &lt;strong&gt;"Sending access"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copy the key that starts with &lt;code&gt;re_&lt;/code&gt;&lt;/strong&gt; and keep it safe.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3.2 Configure Supabase to Use Resend
&lt;/h3&gt;

&lt;p&gt;Back in the Supabase Dashboard:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Project Settings&lt;/strong&gt; (gear icon in the lower left).&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;Authentication&lt;/strong&gt; -&amp;gt; &lt;strong&gt;SMTP Settings&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Toggle &lt;strong&gt;Enable Custom SMTP&lt;/strong&gt; to ON.&lt;/li&gt;
&lt;li&gt;Fill in the fields as follows:&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Field&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Value&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sender Email&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;noreply@yourdomain.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Must&lt;/strong&gt; be an email on the domain you verified&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Sender Name&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;My App Team&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Display name shown to users in their email client&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Host&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;smtp.resend.com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Resend’s SMTP server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Port Number&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;465&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;SSL port&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Username&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;resend&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;This is fixed – always use &lt;code&gt;resend&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Password&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;re_12345...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Paste the API Key you generated in Resend&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;Click &lt;strong&gt;Save&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 4: Customize Email Templates (Optional)
&lt;/h2&gt;

&lt;p&gt;Now that the email pipeline is wired up, you can tweak the actual email content.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go back to &lt;strong&gt;Authentication&lt;/strong&gt; -&amp;gt; &lt;strong&gt;Email Templates&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Edit templates like &lt;strong&gt;"Confirm Your Signup"&lt;/strong&gt; or &lt;strong&gt;"Reset Password"&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Templates support HTML. Just make sure you keep variables like &lt;code&gt;{{ .ConfirmationURL }}&lt;/code&gt; – this is the link users click to confirm their account.&lt;/li&gt;
&lt;/ol&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;You’re welcome to use &lt;a href="https://github.com/hicyoucom/hicyou" rel="noopener noreferrer"&gt;https://github.com/hicyoucom/hicyou&lt;/a&gt; to spin up your own AI-powered link directory site.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Demo:&lt;/strong&gt; &lt;a href="https://hicyou.com/" rel="noopener noreferrer"&gt;https://hicyou.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;via: &lt;a href="https://blog.hicyou.com/en/supabase-setup/" rel="noopener noreferrer"&gt;https://blog.hicyou.com/en/supabase-setup/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>supabase</category>
      <category>database</category>
      <category>postgres</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
