<?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: xiaoguang_</title>
    <description>The latest articles on Forem by xiaoguang_ (@xiaoguang_).</description>
    <link>https://forem.com/xiaoguang_</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%2F1064278%2Fc55a4ec2-b28f-4988-836e-894c6892c2c7.jpg</url>
      <title>Forem: xiaoguang_</title>
      <link>https://forem.com/xiaoguang_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/xiaoguang_"/>
    <language>en</language>
    <item>
      <title>The AI That Makes You Feel Stupid—but In a Good Way</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Tue, 07 Apr 2026 10:15:21 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/the-ai-that-makes-you-feel-stupid-but-in-a-good-way-3mj8</link>
      <guid>https://forem.com/xiaoguang_/the-ai-that-makes-you-feel-stupid-but-in-a-good-way-3mj8</guid>
      <description>&lt;p&gt;You’ve seen it. Every dev forum, Twitter thread, and Discord server is full of panic about &lt;span&gt;AI&lt;/span&gt;. “&lt;span&gt;GPT will take my job!&lt;/span&gt;” “&lt;span&gt;AI is coding better than me!&lt;/span&gt;”&lt;/p&gt;

&lt;p&gt;Here’s the thing: most developers are thinking about &lt;span&gt;AI&lt;/span&gt; the wrong way. They imagine some future robot sitting at their desk, typing flawless code while they sip coffee. But that’s not what’s happening. &lt;span&gt;AI isn’t a replacement&lt;/span&gt;; it’s a mirror. It shows you what you already do—and sometimes, how sloppy you’ve been.&lt;/p&gt;

&lt;p&gt;For example, I once watched a junior dev spend three hours writing a function to validate emails. Then they asked &lt;span&gt;GPT&lt;/span&gt; to do the same thing. &lt;span&gt;GPT wrote it in five seconds—and made it slightly better.&lt;/span&gt; The panic moment? Totally understandable. But here’s the insight: the junior dev &lt;span&gt;learned more in that panic than in any tutorial.&lt;/span&gt; They saw the gap between “&lt;span&gt;good enough&lt;/span&gt;” and “&lt;span&gt;actually elegant&lt;/span&gt;.”&lt;/p&gt;

&lt;p&gt;&lt;span&gt;AI is basically a magnifying glass.&lt;/span&gt; It amplifies the difference between average and excellent. It doesn’t replace humans who understand context, who can decide which path is worth taking, who know what “&lt;span&gt;good enough&lt;/span&gt;” really means.&lt;/p&gt;

&lt;p&gt;Here’s the memorable part: worrying about &lt;span&gt;AI replacing you&lt;/span&gt; is like worrying that a calculator will make arithmetic teachers obsolete. You’ll never be obsolete if you know why you’re doing what you do.&lt;/p&gt;

&lt;p&gt;Practical takeaway: don’t try to out-AI the AI. Use it. Let it show you where your blind spots are. &lt;span&gt;Learn faster, code smarter&lt;/span&gt;, and spend more time on the things &lt;span&gt;AI can’t touch&lt;/span&gt;: judgment, empathy, and creativity.&lt;/p&gt;

&lt;p&gt;&lt;span&gt;AI isn’t your enemy.&lt;/span&gt; It’s your fastest way to becoming the developer everyone else fears will actually replace the lazy ones.&lt;/p&gt;




&lt;p&gt;Read with color: &lt;a href="https://kimkorngmao.com/notes/the-ai-that-makes-you-feel-stupid-but-in-a-good-way" rel="noopener noreferrer"&gt;https://kimkorngmao.com/notes/the-ai-that-makes-you-feel-stupid-but-in-a-good-way&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>discuss</category>
      <category>programming</category>
    </item>
    <item>
      <title>My Honest Take on AI Coding Tools After Months of Heavy Use</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Wed, 01 Apr 2026 10:16:32 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/my-honest-take-on-ai-coding-tools-after-months-of-heavy-use-1a1k</link>
      <guid>https://forem.com/xiaoguang_/my-honest-take-on-ai-coding-tools-after-months-of-heavy-use-1a1k</guid>
      <description>&lt;p&gt;I started using AI tools daily last year. Not as a gimmick. Not to skip thinking. Just as part of my normal workflow.&lt;/p&gt;

&lt;p&gt;At first I was skeptical. I worried the code would feel off, or I’d lose the muscle of solving problems myself.  &lt;/p&gt;

&lt;p&gt;Turns out the opposite happened.&lt;/p&gt;

&lt;p&gt;The tools forced me to get clearer. You can’t paste a vague idea and expect magic. You have to explain the goal, the constraints, the edge cases. That exercise sharpened how I think about problems before I even write a line.&lt;/p&gt;

&lt;p&gt;Most days now look like this:&lt;br&gt;&lt;br&gt;
I sketch the logic in plain English.&lt;br&gt;&lt;br&gt;
I ask the AI to turn it into code.&lt;br&gt;&lt;br&gt;
I read every line.&lt;br&gt;&lt;br&gt;
I change what doesn’t fit my style or the project’s needs.&lt;/p&gt;

&lt;p&gt;The AI writes fast. I still own the decisions.&lt;/p&gt;

&lt;p&gt;What surprised me most was how much time I suddenly had for the parts that actually matter: architecture, user experience, performance trade-offs, and talking to the team. The boring boilerplate disappeared. The interesting problems stayed.&lt;/p&gt;

&lt;p&gt;I also caught myself becoming a better reviewer. When the AI suggests something clever, I pause and ask why it works. When it suggests something lazy, I explain the better path. That back-and-forth improved my own judgment faster than any side project ever did.&lt;/p&gt;

&lt;p&gt;None of this means I stopped learning fundamentals. Data structures, system design, debugging under pressure—those skills matter even more now. The AI handles syntax. I handle consequences.&lt;/p&gt;

&lt;p&gt;Here’s the part I keep coming back to: the developers who will do well aren’t the ones who type the fastest. They’re the ones who know when to accept the suggestion, when to reject it, and when to step away from the tool entirely and think.&lt;/p&gt;

&lt;p&gt;AI is a very good pair programmer.&lt;br&gt;&lt;br&gt;
It is not the architect.&lt;br&gt;&lt;br&gt;
It is not the product owner.&lt;br&gt;&lt;br&gt;
And it definitely isn’t you.&lt;/p&gt;

&lt;p&gt;I’m curious where you stand.&lt;/p&gt;

&lt;p&gt;Have you integrated AI tools into your daily work yet?&lt;br&gt;&lt;br&gt;
What changed for you—good or bad?&lt;br&gt;&lt;br&gt;
What’s one rule you follow to stay in control?&lt;/p&gt;

&lt;p&gt;Drop your experience in the comments. I read every one.&lt;/p&gt;




&lt;p&gt;Read on my site: &lt;a href="https://kimkorngmao.com/notes/my-honest-take-on-ai-coding-tools-after-months-of-heavy-use" rel="noopener noreferrer"&gt;https://kimkorngmao.com/notes/my-honest-take-on-ai-coding-tools-after-months-of-heavy-use&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Why I Still Keep a Personal Website</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Tue, 31 Mar 2026 03:55:28 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/why-i-still-keep-a-personal-website-5hj1</link>
      <guid>https://forem.com/xiaoguang_/why-i-still-keep-a-personal-website-5hj1</guid>
      <description>&lt;p&gt;I didn’t build my &lt;a href="https://kimkorngmao.com" rel="noopener noreferrer"&gt;personal website&lt;/a&gt; to impress anyone.&lt;/p&gt;

&lt;p&gt;At least, not anymore.&lt;/p&gt;

&lt;p&gt;At first, I treated it like a portfolio website.&lt;br&gt;
Something to showcase work. Something to look “complete.”&lt;/p&gt;

&lt;p&gt;But over time, that idea started to feel limiting.&lt;/p&gt;

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

&lt;p&gt;Most portfolio websites try to present a finished version of someone.&lt;/p&gt;

&lt;p&gt;Clean. Polished. Final.&lt;/p&gt;

&lt;p&gt;But that’s not how real work feels.&lt;/p&gt;

&lt;p&gt;Things change. Skills improve. Interests shift.&lt;/p&gt;

&lt;p&gt;So I stopped thinking of my site as a portfolio.&lt;/p&gt;

&lt;p&gt;I started treating it more like a working space.&lt;/p&gt;

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

&lt;p&gt;Now it’s closer to a notebook.&lt;/p&gt;

&lt;p&gt;A place where I can write things down.&lt;br&gt;
Small ideas. Observations. Experiments.&lt;/p&gt;

&lt;p&gt;Nothing too formal.&lt;/p&gt;

&lt;p&gt;Just enough to capture how I think at the moment.&lt;/p&gt;

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

&lt;p&gt;This changed how I approach writing.&lt;/p&gt;

&lt;p&gt;I don’t wait for a “good” idea anymore.&lt;/p&gt;

&lt;p&gt;I just write when something feels worth noting.&lt;/p&gt;

&lt;p&gt;Short posts help with that.&lt;/p&gt;

&lt;p&gt;They’re easier to start. Easier to finish.&lt;br&gt;
And easier to come back to later.&lt;/p&gt;

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

&lt;p&gt;Interestingly, this also works well for search.&lt;/p&gt;

&lt;p&gt;Not because I’m trying to rank for keywords like &lt;em&gt;personal website&lt;/em&gt; or &lt;em&gt;portfolio website&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But because I’m writing in a way people actually search.&lt;/p&gt;

&lt;p&gt;Simple phrases. Clear thoughts. No over-explaining.&lt;/p&gt;

&lt;p&gt;That seems to matter more than anything else.&lt;/p&gt;

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

&lt;p&gt;I’ve also noticed something else.&lt;/p&gt;

&lt;p&gt;A site that keeps growing feels different from one that stays the same.&lt;/p&gt;

&lt;p&gt;Even small updates make it feel alive.&lt;/p&gt;

&lt;p&gt;And that makes me want to keep working on it.&lt;/p&gt;

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

&lt;p&gt;If you’re building your own personal website, it doesn’t need to be perfect.&lt;/p&gt;

&lt;p&gt;You don’t need a full portfolio on day one.&lt;/p&gt;

&lt;p&gt;You can start with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one page&lt;/li&gt;
&lt;li&gt;a few notes&lt;/li&gt;
&lt;li&gt;a simple layout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s enough.&lt;/p&gt;

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

&lt;p&gt;Over time, it becomes something else.&lt;/p&gt;

&lt;p&gt;Not just a portfolio website.&lt;br&gt;
Something more personal.&lt;/p&gt;

&lt;p&gt;Something that reflects how you think.&lt;/p&gt;

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

&lt;p&gt;That’s the part I didn’t expect.&lt;/p&gt;

&lt;p&gt;And probably the reason I’m still maintaining it.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>sideprojects</category>
      <category>portfolio</category>
    </item>
    <item>
      <title>Connect Telegram Notifications in Laravel App Quickly</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Mon, 23 Mar 2026 09:38:21 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/connect-telegram-notifications-in-laravel-app-quickly-2c20</link>
      <guid>https://forem.com/xiaoguang_/connect-telegram-notifications-in-laravel-app-quickly-2c20</guid>
      <description>&lt;p&gt;Integrating Telegram notifications into a Laravel app is a solid move. It’s faster than email and less intrusive than SMS.&lt;/p&gt;

&lt;p&gt;Here is a streamlined way to wire it up.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Database and Bot Setup
&lt;/h3&gt;

&lt;p&gt;First, you need a place to store the handshake between your app and Telegram. Add a &lt;code&gt;telegram_id&lt;/code&gt; column to your &lt;code&gt;users&lt;/code&gt; table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Blueprint&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
    &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'telegram_id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;nullable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;unique&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;//&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, talk to &lt;a href="https://t.me/botfather" rel="noopener noreferrer"&gt;@BotFather&lt;/a&gt; on Telegram. Create a new bot, grab your API Token, and add it to your &lt;code&gt;.env&lt;/code&gt; file. You’ll need this token for every request your backend makes.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The Frontend "Connect" Button
&lt;/h3&gt;

&lt;p&gt;To link a user, you need them to start a conversation with your bot while carrying their local User ID as a parameter. Using JavaScript to handle the redirect keeps the UI clean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"connectTelegram"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Connect Telegram&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;script&amp;gt;&lt;/span&gt;
&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connectTelegram&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&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="o"&gt;=&amp;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;userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;{{ auth()-&amp;gt;id() }}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; 
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;botUsername&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YourBotUsername&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`tg://resolve?domain=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;botUsername&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;start=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the user clicks this, Telegram opens and sends a &lt;code&gt;/start {userId}&lt;/code&gt; message to your bot.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Small note:&lt;/strong&gt; When the user sends &lt;code&gt;/start&lt;/code&gt;, the extra parameter isn’t visible on their end. They’ll just see a normal &lt;code&gt;/start&lt;/code&gt; message in their chat.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Handling the Webhook
&lt;/h3&gt;

&lt;p&gt;You need a controller to listen for Telegram’s ping. When the user hits "Start," Telegram sends a POST request to your app.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handleWebhook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Request&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$request&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nv"&gt;$chatId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'from'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="nv"&gt;$text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'text'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Telegram sends the start param as "/start 123"&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;preg_replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/\D/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$userId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;explode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;' '&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$text&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="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'telegram_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$chatId&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;response&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'status'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'success'&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;Don't forget to exclude this route from CSRF protection in your &lt;code&gt;VerifyCsrfToken&lt;/code&gt; middleware.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Connecting your bot to a webhook:&lt;/strong&gt;&lt;br&gt;
You can set your bot’s webhook by opening this URL in your browser (replace &lt;code&gt;&amp;lt;YOUR_BOT_TOKEN&amp;gt;&lt;/code&gt; and your webhook endpoint accordingly):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;https://api.telegram.org/bot&amp;lt;YOUR_BOT_TOKEN&amp;gt;/setWebhook?url=your_webhook_endpoint&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;example: &lt;a href="https://api.telegram.org/bot123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ/setWebhook?url=https://kimkorngmao.com/telegram/webhook" rel="noopener noreferrer"&gt;https://api.telegram.org/bot123456789:ABCdefGhIJKlmNoPQRsTUVwxyZ/setWebhook?url=https://kimkorngmao.com/telegram/webhook&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once opened, Telegram will push all messages to your Laravel controller automatically.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  4. Sending the Notification
&lt;/h3&gt;

&lt;p&gt;Laravel’s Notification system makes the actual delivery feel native to the framework. While you can use a community package, a simple &lt;code&gt;Http&lt;/code&gt; call often suffices for basic alerts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;sendTelegramNotification&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$userId&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="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;telegram_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Http&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://api.telegram.org/bot"&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'TELEGRAM_BOT_TOKEN'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;"/sendMessage"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'chat_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;telegram_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'text'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'parse_mode'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'HTML'&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A few thoughts
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;start={id}&lt;/code&gt; parameter is the "deep linking" magic of Telegram. It bypasses the need for users to type codes manually.&lt;/p&gt;

&lt;p&gt;Just ensure your webhook URL is secured via HTTPS, or Telegram won't talk to it. It’s a simple system, but once it’s running, the engagement rates usually beat email by a mile.&lt;/p&gt;




&lt;p&gt;Read original: &lt;a href="https://kimkorngmao.com/notes/connect-telegram-notifications-in-laravel-app-quickly" rel="noopener noreferrer"&gt;https://kimkorngmao.com/notes/connect-telegram-notifications-in-laravel-app-quickly&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>laravel</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Laravel 13 Highlights</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Mon, 23 Mar 2026 04:04:52 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/laravel-13-highlights-4i16</link>
      <guid>https://forem.com/xiaoguang_/laravel-13-highlights-4i16</guid>
      <description>&lt;p&gt;Laravel 13 dropped last week. The biggest takeaway is that it’s a "zero breaking changes" release for most. It’s mostly about modernizing the syntax and embracing AI.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. PHP 8.3 is the New Floor
&lt;/h2&gt;

&lt;p&gt;Laravel 13 officially requires &lt;strong&gt;PHP 8.3&lt;/strong&gt;.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support for PHP 8.1 and 8.2 is gone.
&lt;/li&gt;
&lt;li&gt;This lets the framework use typed constants and &lt;code&gt;json_validate()&lt;/code&gt; internally.
&lt;/li&gt;
&lt;li&gt;You get a small performance boost just by upgrading the runtime.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Attributes Everywhere
&lt;/h2&gt;

&lt;p&gt;The biggest visual change is moving away from class properties to &lt;strong&gt;PHP Attributes&lt;/strong&gt;. It's optional, but it makes models and jobs look much cleaner.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Old Way:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$fillable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'name'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'email'&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;&lt;strong&gt;New Way (Laravel 13):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="na"&gt;#[Table('users')]&lt;/span&gt;
&lt;span class="na"&gt;#[Fillable(['name', 'email'])]&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Model&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. The First-Party AI SDK
&lt;/h2&gt;

&lt;p&gt;Laravel now has a native AI SDK (&lt;code&gt;laravel/ai&lt;/code&gt;). No more wrestling with multiple community packages to talk to OpenAI, Anthropic, or Gemini.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Provider Agnostic:&lt;/strong&gt; Swap between OpenAI, Anthropic, and Gemini in &lt;code&gt;config/ai.php&lt;/code&gt; without changing your app logic.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unified API:&lt;/strong&gt; One syntax for text, images, and audio.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Text Generation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Ai\Facades\Ai&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Ai&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Explain quantum computing to a five year old'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Image Generation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Ai\Image&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nv"&gt;$image&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Image&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;of&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'A futuristic city in the style of Van Gogh'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;landscape&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nv"&gt;$image&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cities/future.png'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Creating an Agent:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Agents are classes that wrap instructions (system prompts) and tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Ai\Agents&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Ai\Contracts\Agent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Laravel\Ai\Promptable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SupportAgent&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Promptable&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s1"&gt;'You are a helpful customer support assistant for our SaaS.'&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="c1"&gt;// Usage:&lt;/span&gt;
&lt;span class="nv"&gt;$reply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;SupportAgent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'How do I reset my password?'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Cache Management
&lt;/h2&gt;

&lt;p&gt;A small but smart addition. You can now &lt;strong&gt;extend a cache item’s life without fetching the data first&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Old Way (Manual Refresh):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'session_data'&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="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'session_data'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;addMinutes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30&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;&lt;strong&gt;New Way (Laravel 13):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nc"&gt;Cache&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;touch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'session_data'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1800&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 1800 seconds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Just "touch" the key. It resets the expiration timer directly in the cache store (Redis/Memcached) without pulling the data into PHP memory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5. JSON:API Resources (New in v13)
&lt;/h2&gt;

&lt;p&gt;Laravel 13 introduces a dedicated &lt;strong&gt;JsonApiResource&lt;/strong&gt; for strict spec compliance. It handles IDs, Types, and nesting automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:resource PostResource &lt;span class="nt"&gt;--json-api&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It uses a declarative style instead of the old &lt;code&gt;toArray()&lt;/code&gt; manual nesting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Comparison:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Old Way (Manual)&lt;/th&gt;
&lt;th&gt;New Way (v13 Native)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Structure&lt;/td&gt;
&lt;td&gt;Manually define data, id, type.&lt;/td&gt;
&lt;td&gt;Handled automatically.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attributes&lt;/td&gt;
&lt;td&gt;Mixed inside a single array.&lt;/td&gt;
&lt;td&gt;Clean &lt;code&gt;$attributes&lt;/code&gt; property.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Relations&lt;/td&gt;
&lt;td&gt;Manual &lt;code&gt;whenLoaded&lt;/code&gt; checks.&lt;/td&gt;
&lt;td&gt;Clean &lt;code&gt;$relationships&lt;/code&gt; property.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Example Code (v13):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Http\Resources\JsonApi\JsonApiResource&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PostResource&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JsonApiResource&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$attributes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'title'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'content'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$relationships&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'author'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'comments'&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;blockquote&gt;
&lt;p&gt;You can also use &lt;code&gt;toResource()&lt;/code&gt; directly on a model now, and Laravel will find the correct resource class for you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  My Take
&lt;/h2&gt;

&lt;p&gt;If you’re on Laravel 12, don’t stress. The upgrade is mostly a &lt;strong&gt;dependency bump&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;"Attribute" syntax&lt;/strong&gt; is the future—it’s more IDE-friendly and keeps configuration right where the logic is.&lt;/p&gt;

&lt;p&gt;If you're starting a new project, go with 13 immediately to get that &lt;strong&gt;AI SDK&lt;/strong&gt; and &lt;strong&gt;PHP 8.3 speed&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>news</category>
      <category>php</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Supabase Quick Docs</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Mon, 16 Mar 2026 06:10:36 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/supabase-quick-docs-2dmj</link>
      <guid>https://forem.com/xiaoguang_/supabase-quick-docs-2dmj</guid>
      <description>&lt;p&gt;I keep a small note when learning a new tool.&lt;/p&gt;

&lt;p&gt;Not a full guide. Not polished documentation.&lt;/p&gt;

&lt;p&gt;Just the &lt;strong&gt;syntax I actually use&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;After a few projects with Supabase, I noticed the same pattern. I kept opening the docs, searching for the same things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to insert a row&lt;/li&gt;
&lt;li&gt;How to query data&lt;/li&gt;
&lt;li&gt;How to update something&lt;/li&gt;
&lt;li&gt;How to call an RPC&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I wrote a small “quick syntax sheet”.&lt;/p&gt;

&lt;p&gt;This is the version I wish I had when starting.&lt;/p&gt;




&lt;p&gt;Supabase is simple once you learn the core pattern.&lt;/p&gt;

&lt;p&gt;Almost everything follows this shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supabase
  .from("table")
  .operation(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you remember that, the rest becomes predictable.&lt;/p&gt;

&lt;h1&gt;
  
  
  Setup
&lt;/h1&gt;

&lt;p&gt;Create a client first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&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;createClient&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;@supabase/supabase-js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createClient&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;NEXT_PUBLIC_SUPABASE_URL&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;NEXT_PUBLIC_SUPABASE_ANON_KEY&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it.&lt;/p&gt;

&lt;p&gt;Now every database call starts with &lt;code&gt;supabase&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Select (Read Data)
&lt;/h1&gt;

&lt;p&gt;The most common query.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&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="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll probably write this line hundreds of times.&lt;/p&gt;

&lt;h3&gt;
  
  
  Select specific columns
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.select("id, title, created_at")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id, title&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;h3&gt;
  
  
  Filter rows
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.eq(column, value)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author_id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other common filters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.eq()   equal
.neq()  not equal
.gt()   greater than
.lt()   less than
.like() pattern match
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Get one row
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.single()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;single&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Insert (Create Data)
&lt;/h1&gt;

&lt;p&gt;Insert is straightforward.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&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="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;My post&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello world&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;Multiple rows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Post 1&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; },&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Post 2&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; }&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Return inserted data
&lt;/h3&gt;

&lt;p&gt;Add &lt;code&gt;.select()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; })&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful when you need the new &lt;code&gt;id&lt;/code&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Update
&lt;/h1&gt;

&lt;p&gt;Update rows with a filter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&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="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;Updated title&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt; })&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Without a filter, it updates &lt;strong&gt;every row&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s a mistake most people make once.&lt;/p&gt;

&lt;h1&gt;
  
  
  Delete
&lt;/h1&gt;

&lt;p&gt;Delete also requires a filter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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;delete&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;postId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again, no filter means deleting everything.&lt;/p&gt;

&lt;h1&gt;
  
  
  Ordering
&lt;/h1&gt;

&lt;p&gt;Sort results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ascending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;order&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ascending&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Limit
&lt;/h1&gt;

&lt;p&gt;Limit rows returned.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;limit&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;limit&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Pagination
&lt;/h1&gt;

&lt;p&gt;Use &lt;code&gt;.range()&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;range&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="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;range&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="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This returns rows &lt;strong&gt;0–9&lt;/strong&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Joins
&lt;/h1&gt;

&lt;p&gt;Supabase uses PostgREST syntax.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;posts&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="nf"&gt;select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*, profiles(username)&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;This joins the &lt;code&gt;profiles&lt;/code&gt; table.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;post
  └ profile.username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Auth (Quick Syntax)
&lt;/h1&gt;

&lt;p&gt;Get the current user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sign in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signInWithPassword&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;password&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sign up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signUp&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;password&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sign out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;signOut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Storage
&lt;/h1&gt;

&lt;p&gt;Upload a file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;avatars&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="nf"&gt;upload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Get public URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;supabase&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;avatars&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="nf"&gt;getPublicUrl&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user.png&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;h1&gt;
  
  
  RPC (Calling Database Functions)
&lt;/h1&gt;

&lt;p&gt;If you define a Postgres function, call it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;supabase&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rpc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get_popular_posts&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;With parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rpc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;get_posts_by_user&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;user_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  The Pattern Behind Everything
&lt;/h1&gt;

&lt;p&gt;After using Supabase for a while, you notice something simple.&lt;/p&gt;

&lt;p&gt;Almost every query follows the same structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;supabase
  .from(table)
  .action()
  .filter()
  .modifier()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.from().select()
.from().insert()
.from().update()
.from().delete()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once that clicks, the API feels predictable.&lt;/p&gt;

&lt;h1&gt;
  
  
  What I Actually Remember
&lt;/h1&gt;

&lt;p&gt;When working quickly, I don’t remember the whole API.&lt;/p&gt;

&lt;p&gt;I remember a few patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.from("table")&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.select("*")&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.insert({})&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.update({}).eq()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.delete().eq()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.order()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.limit()&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Everything else can be looked up.&lt;/p&gt;

&lt;h1&gt;
  
  
  A Small Lesson About Tools
&lt;/h1&gt;

&lt;p&gt;Most tools feel complex at first.&lt;/p&gt;

&lt;p&gt;But good tools have a &lt;strong&gt;small core idea&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For Supabase, it’s this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pick a table.
Choose an operation.
Add filters.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s most of the API.&lt;/p&gt;

&lt;p&gt;Once you see the pattern, the documentation becomes easier to navigate.&lt;/p&gt;




&lt;p&gt;Read on my site: &lt;a href="https://kimkorngmao.com/notes/supabase-quick-docs" rel="noopener noreferrer"&gt;https://kimkorngmao.com/notes/supabase-quick-docs&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>database</category>
      <category>javascript</category>
      <category>productivity</category>
    </item>
    <item>
      <title>A Roadmap to Becoming a Web Developer</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Fri, 13 Mar 2026 10:00:43 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/a-roadmap-to-becoming-a-web-developer-41ka</link>
      <guid>https://forem.com/xiaoguang_/a-roadmap-to-becoming-a-web-developer-41ka</guid>
      <description>&lt;p&gt;If you want to become a web developer, the internet has never made it easier.&lt;/p&gt;

&lt;p&gt;You don’t need a computer science degree.&lt;br&gt;
You don’t need permission.&lt;br&gt;
You just need curiosity and time.&lt;/p&gt;

&lt;p&gt;Here’s a roadmap I recommend.&lt;/p&gt;
&lt;h2&gt;
  
  
  1. Learn the Foundations
&lt;/h2&gt;

&lt;p&gt;Start with the basics of the web.&lt;/p&gt;

&lt;p&gt;Everything else builds on this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Core technologies&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTML — structure&lt;/li&gt;
&lt;li&gt;CSS — layout and styling&lt;/li&gt;
&lt;li&gt;JavaScript — behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your first goal is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build a static website from scratch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Not a tutorial.&lt;br&gt;
Your own idea.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;personal portfolio&lt;/li&gt;
&lt;li&gt;blog&lt;/li&gt;
&lt;li&gt;photo gallery&lt;/li&gt;
&lt;li&gt;simple landing page&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  2. Learn How the Web Actually Works
&lt;/h2&gt;

&lt;p&gt;Many beginners skip this step.&lt;/p&gt;

&lt;p&gt;Don’t.&lt;/p&gt;

&lt;p&gt;Understanding the web makes everything easier later.&lt;/p&gt;

&lt;p&gt;Things worth learning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How browsers render pages&lt;/li&gt;
&lt;li&gt;What happens when you visit a URL&lt;/li&gt;
&lt;li&gt;HTTP requests and responses&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;JSON&lt;/li&gt;
&lt;li&gt;how servers work&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t need deep theory.&lt;/p&gt;

&lt;p&gt;Just enough to understand the system.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Pick a Modern Stack
&lt;/h2&gt;

&lt;p&gt;Once you know the basics, choose a stack and go deeper.&lt;/p&gt;

&lt;p&gt;For frontend development, a common path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;Next.js&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Tailwind CSS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don’t worry about choosing the “best” stack.&lt;/p&gt;

&lt;p&gt;Any modern framework will work.&lt;/p&gt;

&lt;p&gt;The important thing is &lt;strong&gt;building real projects&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Build Projects (Lots of Them)
&lt;/h2&gt;

&lt;p&gt;Projects teach you things tutorials never will.&lt;/p&gt;

&lt;p&gt;Ideas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blog CMS&lt;/li&gt;
&lt;li&gt;video player website&lt;/li&gt;
&lt;li&gt;note-taking app&lt;/li&gt;
&lt;li&gt;AI chatbot&lt;/li&gt;
&lt;li&gt;online game&lt;/li&gt;
&lt;li&gt;dashboard&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every project will reveal something new:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;deployment&lt;/li&gt;
&lt;li&gt;performance&lt;/li&gt;
&lt;li&gt;bugs you didn’t expect&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how developers actually learn.&lt;/p&gt;
&lt;h2&gt;
  
  
  5. Learn the Backend
&lt;/h2&gt;

&lt;p&gt;At some point you’ll want dynamic data.&lt;/p&gt;

&lt;p&gt;Now learn backend fundamentals.&lt;/p&gt;

&lt;p&gt;Useful topics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;databases (Postgres, MySQL)&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;server frameworks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Popular tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js&lt;/li&gt;
&lt;li&gt;Express&lt;/li&gt;
&lt;li&gt;Supabase&lt;/li&gt;
&lt;li&gt;Firebase&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you reach this point, you can build &lt;strong&gt;full-stack apps&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  6. Deploy Your Work
&lt;/h2&gt;

&lt;p&gt;If your projects live only on your laptop, nobody sees them.&lt;/p&gt;

&lt;p&gt;Deployment is part of the skill.&lt;/p&gt;

&lt;p&gt;Learn how to deploy to platforms like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vercel&lt;/li&gt;
&lt;li&gt;Netlify&lt;/li&gt;
&lt;li&gt;Cloudflare&lt;/li&gt;
&lt;li&gt;Docker servers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shipping projects forces you to learn:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;environment variables&lt;/li&gt;
&lt;li&gt;build processes&lt;/li&gt;
&lt;li&gt;performance&lt;/li&gt;
&lt;li&gt;monitoring&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  7. Write and Share
&lt;/h2&gt;

&lt;p&gt;One underrated skill for developers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;communication.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Write about what you learn.&lt;/p&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blog posts&lt;/li&gt;
&lt;li&gt;GitHub READMEs&lt;/li&gt;
&lt;li&gt;tutorials&lt;/li&gt;
&lt;li&gt;dev notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Clear writing improves clear thinking.&lt;/p&gt;

&lt;p&gt;And it helps others learn too.&lt;/p&gt;
&lt;h2&gt;
  
  
  8. Keep Building
&lt;/h2&gt;

&lt;p&gt;There is no finish line.&lt;/p&gt;

&lt;p&gt;The web changes constantly.&lt;/p&gt;

&lt;p&gt;Your goal isn’t to “learn everything”.&lt;/p&gt;

&lt;p&gt;Your goal is to &lt;strong&gt;stay curious and keep shipping&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A simple loop works well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;learn → build → ship → share → repeat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do this for a few years and you’ll be amazed how far you go.&lt;/p&gt;




&lt;p&gt;Read on my site: &lt;a href="https://kimkorngmao.com/notes/a-roadmap-to-becoming-a-web-developer" rel="noopener noreferrer"&gt;https://kimkorngmao.com/notes/a-roadmap-to-becoming-a-web-developer&lt;/a&gt;&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>career</category>
      <category>codenewbie</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Developer in the Age of AI</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Fri, 06 Mar 2026 10:03:31 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/developer-in-the-age-of-ai-53dl</link>
      <guid>https://forem.com/xiaoguang_/developer-in-the-age-of-ai-53dl</guid>
      <description>&lt;p&gt;Software development is changing quickly.&lt;/p&gt;

&lt;p&gt;For decades, writing software meant typing every line of code yourself. You opened an editor, read documentation, searched forums, and slowly assembled working systems one function at a time.&lt;/p&gt;

&lt;p&gt;Today, the workflow looks very different.&lt;/p&gt;

&lt;p&gt;You describe the problem.&lt;br&gt;
An AI suggests the solution.&lt;br&gt;
You guide the system toward the outcome you want.&lt;/p&gt;

&lt;p&gt;This doesn’t remove the developer from the process. Instead, it changes the role.&lt;/p&gt;

&lt;p&gt;Developers are becoming &lt;strong&gt;architects of intent&lt;/strong&gt; rather than producers of syntax.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real skill: knowing what to build
&lt;/h2&gt;

&lt;p&gt;AI can write code. But it cannot decide &lt;em&gt;what is worth building&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That decision still belongs to humans.&lt;/p&gt;

&lt;p&gt;The most valuable engineers are not the ones who type the fastest. They are the ones who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Identify meaningful problems&lt;/li&gt;
&lt;li&gt;Design simple solutions&lt;/li&gt;
&lt;li&gt;Understand tradeoffs&lt;/li&gt;
&lt;li&gt;Ship things people actually use&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI accelerates execution. It does not replace judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Speed changes how we learn
&lt;/h2&gt;

&lt;p&gt;When building becomes faster, experimentation increases.&lt;/p&gt;

&lt;p&gt;You can try five ideas in the time it used to take to build one.&lt;/p&gt;

&lt;p&gt;This leads to a new pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build quickly&lt;/li&gt;
&lt;li&gt;Learn what works&lt;/li&gt;
&lt;li&gt;Throw away what doesn’t&lt;/li&gt;
&lt;li&gt;Repeat&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Iteration becomes the main advantage.&lt;/p&gt;

&lt;p&gt;The teams that learn the fastest will win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Small teams, bigger outcomes
&lt;/h2&gt;

&lt;p&gt;Tools that multiply developer productivity change team dynamics.&lt;/p&gt;

&lt;p&gt;Historically, large engineering organizations were necessary to build complex products.&lt;/p&gt;

&lt;p&gt;Now, a small group with strong judgment and modern tooling can move incredibly fast.&lt;/p&gt;

&lt;p&gt;Less coordination.&lt;br&gt;
Less overhead.&lt;br&gt;
More focus on the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bottleneck moves
&lt;/h2&gt;

&lt;p&gt;As AI removes friction from coding, new bottlenecks appear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product thinking&lt;/li&gt;
&lt;li&gt;Clear communication&lt;/li&gt;
&lt;li&gt;Good taste in design&lt;/li&gt;
&lt;li&gt;Understanding user problems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In other words: &lt;strong&gt;human skills matter more, not less.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Clear thinking leads to clear prompts.&lt;br&gt;
Clear prompts lead to better systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  The future developer
&lt;/h2&gt;

&lt;p&gt;The future developer will likely spend less time writing code and more time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Designing systems&lt;/li&gt;
&lt;li&gt;Reviewing AI-generated solutions&lt;/li&gt;
&lt;li&gt;Teaching models through feedback&lt;/li&gt;
&lt;li&gt;Communicating ideas clearly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Coding becomes a conversation.&lt;/p&gt;

&lt;p&gt;Not just between humans and machines, but between ideas and execution.&lt;/p&gt;

&lt;p&gt;The tools will keep improving.&lt;/p&gt;

&lt;p&gt;But the core job remains the same:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand problems deeply, then build something useful.&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Read on my site: &lt;a href="https://www.kimkorngmao.com/notes/developer-in-the-age-of-ai" rel="noopener noreferrer"&gt;https://www.kimkorngmao.com/notes/developer-in-the-age-of-ai&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>programming</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Write Code Like You’ll Maintain It</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Fri, 06 Mar 2026 01:58:06 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/write-code-like-youll-maintain-it-3lp7</link>
      <guid>https://forem.com/xiaoguang_/write-code-like-youll-maintain-it-3lp7</guid>
      <description>&lt;p&gt;Most of us write code for the moment.&lt;/p&gt;

&lt;p&gt;We’re trying to fix a bug. Ship a feature. Hit a deadline.&lt;/p&gt;

&lt;p&gt;Maintenance feels like a future problem. But here’s the truth: future you is the one who pays for today’s shortcuts.&lt;/p&gt;

&lt;p&gt;I’ve learned this the hard way.&lt;/p&gt;

&lt;h2&gt;
  
  
  The code isn’t done when it works
&lt;/h2&gt;

&lt;p&gt;Getting something to run is only step one.&lt;/p&gt;

&lt;p&gt;You know that feeling when the feature finally works and you think, “Good enough”? That’s usually the point where the real work should start.&lt;/p&gt;

&lt;p&gt;Ask yourself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Would I understand this in six months?&lt;/li&gt;
&lt;li&gt;Would a new teammate understand this in six minutes?&lt;/li&gt;
&lt;li&gt;Is the naming obvious?&lt;/li&gt;
&lt;li&gt;Is the logic doing one thing or five?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the answer makes you hesitate, it’s not done.&lt;/p&gt;

&lt;p&gt;Working code is not the goal. Clear code is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Name things like you mean it
&lt;/h2&gt;

&lt;p&gt;Bad names are expensive.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;data&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;, &lt;code&gt;temp&lt;/code&gt;, &lt;code&gt;handleStuff&lt;/code&gt; — these are signs you were in a rush.&lt;/p&gt;

&lt;p&gt;Naming forces you to think. When you struggle to name something, it usually means the idea isn’t clear yet.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;calculatePrice&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Calculate what price? With tax? With discount? For which user?&lt;/p&gt;

&lt;p&gt;A better name might be:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nf"&gt;calculateDiscountedPriceWithTax&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Longer? Yes. Clearer? Also yes.&lt;/p&gt;

&lt;p&gt;Clarity beats cleverness every time.&lt;/p&gt;
&lt;h2&gt;
  
  
  Fewer abstractions, not more
&lt;/h2&gt;

&lt;p&gt;Early in my career, I loved abstractions.&lt;/p&gt;

&lt;p&gt;Custom hooks for everything. Utility layers. Reusable patterns for cases that only happened once.&lt;/p&gt;

&lt;p&gt;It felt smart.&lt;/p&gt;

&lt;p&gt;But too many abstractions hide intent. They make simple code harder to follow.&lt;/p&gt;

&lt;p&gt;If something is only used in one place, it probably belongs in that place.&lt;/p&gt;

&lt;p&gt;Duplication is not always bad. Confusing indirection is worse.&lt;/p&gt;

&lt;p&gt;You can always extract later. It’s much harder to simplify over-engineered code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Comments are not a rescue plan
&lt;/h2&gt;

&lt;p&gt;If your code needs a paragraph to explain it, something is wrong.&lt;/p&gt;

&lt;p&gt;This:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// This function loops through the array and checks if the user is active&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;…should not be necessary.&lt;/p&gt;

&lt;p&gt;Your code should already say that.&lt;/p&gt;

&lt;p&gt;Comments are useful when they explain &lt;em&gt;why&lt;/em&gt;, not &lt;em&gt;what&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// We intentionally skip caching here because user permissions change often.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That helps future you. It explains context. That’s what comments are for.&lt;/p&gt;
&lt;h2&gt;
  
  
  Write smaller functions
&lt;/h2&gt;

&lt;p&gt;Large functions hide bugs.&lt;/p&gt;

&lt;p&gt;When a function does too much, you stop reasoning about it. You just hope it works.&lt;/p&gt;

&lt;p&gt;A simple rule I follow: if I have to scroll a lot to see the whole function, it’s probably doing too much.&lt;/p&gt;

&lt;p&gt;Break it into smaller pieces. Each function should do one clear thing.&lt;/p&gt;

&lt;p&gt;This makes testing easier. It also makes reading easier.&lt;/p&gt;

&lt;p&gt;And reading code is most of the job.&lt;/p&gt;
&lt;h2&gt;
  
  
  Think about the next person
&lt;/h2&gt;

&lt;p&gt;Code is a form of communication.&lt;/p&gt;

&lt;p&gt;You are not writing for the compiler. You are writing for other humans.&lt;/p&gt;

&lt;p&gt;Even if you work alone, the “other human” is future you.&lt;/p&gt;

&lt;p&gt;Be kind to that person.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid clever tricks unless they truly simplify.&lt;/li&gt;
&lt;li&gt;Prefer boring solutions.&lt;/li&gt;
&lt;li&gt;Stick to common patterns in your ecosystem.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Boring code is underrated. It is predictable. Predictable code is easy to trust.&lt;/p&gt;

&lt;p&gt;Actually, I don’t think clever code is cool anymore. I think understandable code is cool.&lt;/p&gt;
&lt;h2&gt;
  
  
  Tests are a gift to yourself
&lt;/h2&gt;

&lt;p&gt;Tests are not just for catching bugs.&lt;/p&gt;

&lt;p&gt;They document behavior.&lt;/p&gt;

&lt;p&gt;When you come back to a piece of code and don’t remember what it’s supposed to do, the tests tell you.&lt;/p&gt;

&lt;p&gt;Even a few basic tests help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does it handle empty input?&lt;/li&gt;
&lt;li&gt;Does it handle invalid input?&lt;/li&gt;
&lt;li&gt;Does it return the expected shape?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You don’t need perfect coverage. You need confidence.&lt;/p&gt;

&lt;p&gt;That’s enough.&lt;/p&gt;
&lt;h2&gt;
  
  
  Slow down a little
&lt;/h2&gt;

&lt;p&gt;Rushing feels productive.&lt;/p&gt;

&lt;p&gt;But debugging unclear code later is slow. Very slow.&lt;/p&gt;

&lt;p&gt;Spending an extra 10 minutes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Renaming variables&lt;/li&gt;
&lt;li&gt;Removing dead code&lt;/li&gt;
&lt;li&gt;Simplifying a condition&lt;/li&gt;
&lt;li&gt;Splitting a function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…usually saves hours down the line.&lt;/p&gt;

&lt;p&gt;It’s not glamorous. But it works.&lt;/p&gt;
&lt;h2&gt;
  
  
  The real goal
&lt;/h2&gt;

&lt;p&gt;When I look back at old projects, I rarely think, “Wow, that was fast.”&lt;/p&gt;

&lt;p&gt;I think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why is this so hard to follow?&lt;/li&gt;
&lt;li&gt;Why did I make this so complicated?&lt;/li&gt;
&lt;li&gt;What was I even thinking here?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good code ages well.&lt;/p&gt;

&lt;p&gt;It reads simply. It feels obvious. It doesn’t try to impress anyone.&lt;/p&gt;

&lt;p&gt;That’s the kind of code I try to write now.&lt;/p&gt;

&lt;p&gt;Not perfect. Just clear.&lt;/p&gt;

&lt;p&gt;And honestly, that’s enough.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.kimkorngmao.com/notes/write-code-like-youll-maintain-it" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.kimkorngmao.com%2Fnotes%2Fimages%2F1772787958410-write-code-like-youll-maintain-it.png" height="534" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.kimkorngmao.com/notes/write-code-like-youll-maintain-it" rel="noopener noreferrer" class="c-link"&gt;
            Write Code Like You’ll Maintain It - Kimkorng Mao
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Clear code today saves you from confusion tomorrow.
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kimkorngmao.com%2Ffavicon%2Ffavicon.ico" width="48" height="48"&gt;
          kimkorngmao.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>codequality</category>
      <category>coding</category>
      <category>programming</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Stop Trying to Scale Everything</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Fri, 06 Mar 2026 01:52:02 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/stop-trying-to-scale-everything-2iam</link>
      <guid>https://forem.com/xiaoguang_/stop-trying-to-scale-everything-2iam</guid>
      <description>&lt;p&gt;A few years ago, I thought everything needed to scale.&lt;/p&gt;

&lt;p&gt;Every side project had to become a startup.&lt;br&gt;
Every blog post had to become a content engine.&lt;br&gt;
Every tool had to turn into a platform.&lt;/p&gt;

&lt;p&gt;If something showed early traction, I immediately asked: “How do I grow this?”&lt;/p&gt;

&lt;p&gt;That question isn’t wrong. But it can quietly ruin good work.&lt;/p&gt;
&lt;h2&gt;
  
  
  Not Everything Needs to Be Big
&lt;/h2&gt;

&lt;p&gt;We live in a world that rewards scale.&lt;/p&gt;

&lt;p&gt;Venture capital rewards it. Social media rewards it. Even advice online pushes it. If you’re not growing, you’re “leaving opportunity on the table.”&lt;/p&gt;

&lt;p&gt;But small things have power.&lt;/p&gt;

&lt;p&gt;A small tool can solve a very specific problem really well.&lt;br&gt;
A small blog can reach exactly the right people.&lt;br&gt;
A small product can fund your lifestyle without owning your life.&lt;/p&gt;

&lt;p&gt;Actually, most of the internet runs on small things.&lt;/p&gt;

&lt;p&gt;When you try to scale too early, you change the nature of what you’re building. You start optimizing for growth instead of usefulness. You think about funnels instead of features. You worry about onboarding flows before you even know if the product matters.&lt;/p&gt;

&lt;p&gt;And that shift changes your decisions.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Cost of Optimization
&lt;/h2&gt;

&lt;p&gt;Optimization sounds smart. It feels responsible.&lt;/p&gt;

&lt;p&gt;But optimization adds complexity.&lt;/p&gt;

&lt;p&gt;You add analytics. You add growth experiments. You add email capture. You add dashboards. You add settings pages for features only two people asked for.&lt;/p&gt;

&lt;p&gt;Suddenly, your simple idea becomes heavy.&lt;/p&gt;

&lt;p&gt;I’ve done this. I’ve added systems before proving the core idea worked. I’ve hired help before understanding the problem deeply. I’ve scaled infrastructure before scaling demand.&lt;/p&gt;

&lt;p&gt;It rarely ends well.&lt;/p&gt;

&lt;p&gt;You don’t just add code. You add maintenance. You add mental overhead. You add pressure.&lt;/p&gt;

&lt;p&gt;And pressure makes you build for numbers instead of people.&lt;/p&gt;
&lt;h2&gt;
  
  
  Build Something That Feels Complete at 1x
&lt;/h2&gt;

&lt;p&gt;Instead of asking “How can this reach 1 million users?” try asking:&lt;/p&gt;

&lt;p&gt;“Is this great for the first 10?”&lt;/p&gt;

&lt;p&gt;When you build for 10 people, you pay attention. You answer emails. You watch how they use it. You fix the rough edges.&lt;/p&gt;

&lt;p&gt;You build something tight.&lt;/p&gt;

&lt;p&gt;If it grows after that, great. Growth built on top of something solid is different from growth used as a strategy to find solidity.&lt;/p&gt;

&lt;p&gt;There’s a difference between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building something small that grows.&lt;/li&gt;
&lt;li&gt;Building something to grow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That difference matters.&lt;/p&gt;
&lt;h2&gt;
  
  
  Some Projects Should Stay Small
&lt;/h2&gt;

&lt;p&gt;This is the part people don’t say out loud.&lt;/p&gt;

&lt;p&gt;Some projects are better small.&lt;/p&gt;

&lt;p&gt;A niche newsletter.&lt;br&gt;
A focused SaaS tool.&lt;br&gt;
A personal blog.&lt;br&gt;
A paid community with 200 members.&lt;/p&gt;

&lt;p&gt;If it supports your goals, pays your bills, and feels sustainable, why force it into something bigger?&lt;/p&gt;

&lt;p&gt;Scale increases surface area. More users means more support. More complexity. More expectations.&lt;/p&gt;

&lt;p&gt;Sometimes you don’t want a company. You want freedom.&lt;/p&gt;

&lt;p&gt;And freedom doesn’t always scale.&lt;/p&gt;
&lt;h2&gt;
  
  
  Growth Is a Tool, Not the Goal
&lt;/h2&gt;

&lt;p&gt;Growth is useful when it supports something meaningful. It’s dangerous when it becomes the meaning.&lt;/p&gt;

&lt;p&gt;It’s okay to build something that stays simple.&lt;br&gt;
It’s okay to serve a small group deeply.&lt;br&gt;
It’s okay to stop at “enough.”&lt;/p&gt;

&lt;p&gt;Actually, “enough” is underrated.&lt;/p&gt;

&lt;p&gt;The internet makes it easy to compare. There’s always someone bigger, faster, louder. But you don’t see their tradeoffs. You don’t see the stress or the loss of control.&lt;/p&gt;

&lt;p&gt;You only see the numbers.&lt;/p&gt;
&lt;h2&gt;
  
  
  What I Do Now
&lt;/h2&gt;

&lt;p&gt;Now, when I start something new, I ask a different question:&lt;/p&gt;

&lt;p&gt;“If this never gets big, would I still be proud of it?”&lt;/p&gt;

&lt;p&gt;If the answer is no, I rethink it.&lt;/p&gt;

&lt;p&gt;Because if you only enjoy the outcome at scale, you won’t enjoy the process. And most of your time is spent in the process.&lt;/p&gt;

&lt;p&gt;Build things that feel good at 1x.&lt;/p&gt;

&lt;p&gt;Let them grow if they earn it.&lt;/p&gt;

&lt;p&gt;And if they don’t, that’s fine too.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.kimkorngmao.com/notes/stop-trying-to-scale-everything" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fassets.kimkorngmao.com%2Fnotes%2Fimages%2F1775013189492-1r7pygpp52n.gif" height="304" class="m-0" width="540"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.kimkorngmao.com/notes/stop-trying-to-scale-everything" rel="noopener noreferrer" class="c-link"&gt;
            Stop Trying to Scale Everything - Kimkorng Mao
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Build Small First, Let Growth Happen Naturally Later
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.kimkorngmao.com%2Ffavicon%2Ffavicon.ico" width="48" height="48"&gt;
          kimkorngmao.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


</description>
      <category>discuss</category>
      <category>productivity</category>
      <category>sideprojects</category>
      <category>startup</category>
    </item>
    <item>
      <title>Human in the Loop</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Wed, 06 Aug 2025 09:54:35 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/human-in-the-loop-1d21</link>
      <guid>https://forem.com/xiaoguang_/human-in-the-loop-1d21</guid>
      <description>&lt;p&gt;I used to think writing code was the whole job. Type the right syntax, hit compile, ship it. Then AI Code Agent showed up. Suddenly half my keystrokes were suggestions. At first it felt like cheating. Then it felt normal. Now it’s the only way I work.&lt;/p&gt;

&lt;p&gt;The shift is simple. Instead of telling the computer how to do something, I tell it what I want. The “how” is handled by an AI that’s read more code than I ever will. My job is to stay in the loop. I guide, correct, and decide when the result is good enough. I’m no longer a typist. I’m a filter.&lt;/p&gt;

&lt;p&gt;This changes the skills that matter. Memorizing syntax is less useful. Spotting subtle bugs is more useful. Explaining intent in plain words is now a core skill. The AI can write a for loop, but it can’t tell me if the loop solves the real problem. Only I can do that.&lt;/p&gt;

&lt;p&gt;There’s a trap here. If I stop paying attention, the code still looks fine. It just quietly drifts from what I actually need. The loop only works if the human stays human. That means asking “why” before asking “how.” It means pushing back when the answer feels off.&lt;/p&gt;

&lt;p&gt;I’ve started treating the AI like a junior teammate who codes fast but misses context. I review every line. I ask questions. Sometimes I reject the whole thing and start over. The process is slower than pure autopilot, but the result is better. And I still learn something new each time.&lt;/p&gt;

&lt;p&gt;This isn’t the end of programming. It’s a new layer. We still need architecture, testing, security, taste. We just get to spend less time on boilerplate and more time on decisions that matter. The loop keeps us honest. As long as we stay in it, the tools serve us, not the other way around.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>A Simple Guide to Bash Commands for New Developers</title>
      <dc:creator>xiaoguang_</dc:creator>
      <pubDate>Wed, 23 Jul 2025 02:45:44 +0000</pubDate>
      <link>https://forem.com/xiaoguang_/a-simple-guide-to-bash-commands-for-new-developers-314a</link>
      <guid>https://forem.com/xiaoguang_/a-simple-guide-to-bash-commands-for-new-developers-314a</guid>
      <description>&lt;p&gt;Original post: &lt;a href="https://www.kimkorngmao.com/notes/simple-guide-bash-commands-for-new-developers" rel="noopener noreferrer"&gt;https://www.kimkorngmao.com/notes/simple-guide-bash-commands-for-new-developers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you are a new developer, you probably use a nice GUI (Graphical User Interface) to code. It's easy. But when you start doing real work—like backend systems, deployment, or CI/CD—you will need to use the &lt;strong&gt;Terminal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Using the terminal and &lt;strong&gt;Bash commands&lt;/strong&gt; is a skill you must have.&lt;/p&gt;

&lt;p&gt;This article is for new developers who are not used to the command line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Commands You Should Know
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Basics &amp;amp; File Management&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;pwd&lt;/code&gt;, &lt;code&gt;ls&lt;/code&gt;, &lt;code&gt;cd&lt;/code&gt;, &lt;code&gt;touch&lt;/code&gt;, &lt;code&gt;mkdir&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;cat&lt;/code&gt;, &lt;code&gt;less&lt;/code&gt;, &lt;code&gt;head&lt;/code&gt;, &lt;code&gt;tail&lt;/code&gt;, &lt;code&gt;echo&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Searching &amp;amp; Editing&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;grep&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;, &lt;code&gt;nano&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Managing Git&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;git clone&lt;/code&gt;, &lt;code&gt;git status&lt;/code&gt;, &lt;code&gt;git log&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Processing Text&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;awk&lt;/code&gt;, &lt;code&gt;sed&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Calling APIs &amp;amp; Basic Networking&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;ping&lt;/code&gt;, &lt;code&gt;wget&lt;/code&gt;, &lt;code&gt;netstat&lt;/code&gt;, &lt;code&gt;lsof&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1 Basics and File Management
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;pwd&lt;/code&gt; – Where am I?
&lt;/h4&gt;

&lt;p&gt;This command shows you the path of the folder you are in right now.&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;pwd&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It will display something like this:&lt;br&gt;
&lt;code&gt;/Users/yourname/projects/myapp&lt;/code&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;code&gt;ls&lt;/code&gt; – What's in here?
&lt;/h4&gt;

&lt;p&gt;This lists all the files and folders in your current directory.&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;ls&lt;/span&gt;          &lt;span class="c"&gt;# A short list of files and folders.&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lah&lt;/span&gt;     &lt;span class="c"&gt;# A detailed list of all files.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;-l&lt;/code&gt; gives you more details (like size and date).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;-a&lt;/code&gt; shows all files, even hidden ones (those starting with a dot &lt;code&gt;.&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;-h&lt;/code&gt; makes file sizes easy to read (like KB or MB).&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;cd&lt;/code&gt; – Change folder
&lt;/h4&gt;

&lt;p&gt;Use this to move between folders.&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;cd &lt;/span&gt;bash_cmd_learn      &lt;span class="c"&gt;# Go into the 'bash_cmd_learn' folder.&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; ..       &lt;span class="c"&gt;# Go back up to the parent folder.&lt;/span&gt;
&lt;span class="nb"&gt;cd&lt;/span&gt; -        &lt;span class="c"&gt;# Go back to the last folder you were in.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;touch&lt;/code&gt; – Create an empty file
&lt;/h4&gt;

&lt;p&gt;This creates a new, empty file.&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;rean.txt   &lt;span class="c"&gt;# Creates a new file named rean.txt.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the file already exists, this command just updates its timestamp.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;mkdir&lt;/code&gt; – Make a new folder
&lt;/h4&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;logs          &lt;span class="c"&gt;# Creates a new folder named 'logs'.&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; data/db    &lt;span class="c"&gt;# Creates 'data' folder and then 'db' folder inside it.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-p&lt;/code&gt; option is useful. It creates the parent folder if it's not there.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;rm&lt;/code&gt; – Remove a file or folder
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm &lt;/span&gt;rean.txt      &lt;span class="c"&gt;# Deletes the file rean.txt.&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; logs/        &lt;span class="c"&gt;# Deletes the 'logs' folder and everything inside it.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;-r&lt;/code&gt; means recursive, so it deletes the whole folder.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;-f&lt;/code&gt; means force, so it doesn't ask you for confirmation.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Be very careful with &lt;code&gt;rm -rf&lt;/code&gt;.&lt;/strong&gt; It deletes everything forever and does not ask you. There is no undo.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;cat&lt;/code&gt; – Read a whole file
&lt;/h4&gt;

&lt;p&gt;This command prints the entire content of a file to the screen. Good for small files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;less&lt;/code&gt; – Read a file page by page
&lt;/h4&gt;

&lt;p&gt;If a file is very long, use &lt;code&gt;less&lt;/code&gt;. It lets you scroll up and down.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;less 2000_log_file.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Press &lt;code&gt;q&lt;/code&gt; to exit.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;head&lt;/code&gt; and &lt;code&gt;tail&lt;/code&gt; – See the start or end of a file
&lt;/h4&gt;

&lt;p&gt;Sometimes you only need to see the first few lines or the last few lines.&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;head &lt;/span&gt;app.js        &lt;span class="c"&gt;# Shows the first 10 lines.&lt;/span&gt;
&lt;span class="nb"&gt;tail &lt;/span&gt;app.js        &lt;span class="c"&gt;# Shows the last 10 lines.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;echo&lt;/code&gt; – Print text
&lt;/h4&gt;

&lt;p&gt;This command prints text or the value of a variable.&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"Hello, Developer"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;          &lt;span class="c"&gt;# Shows the path to your home directory.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use it to write text to a file.&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;echo&lt;/span&gt; &lt;span class="s2"&gt;"PORT=8080"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; .env     &lt;span class="c"&gt;# Creates a file named .env with this text.&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"DEBUG=true"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .env    &lt;span class="c"&gt;# Adds a new line to the end of .env.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;&amp;gt;&lt;/code&gt; overwrites the file.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;&amp;gt;&amp;gt;&lt;/code&gt; adds to the end of the file.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  2. Searching &amp;amp; Editing
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;grep&lt;/code&gt; – Find text inside files
&lt;/h4&gt;

&lt;p&gt;This is one of the most useful commands. It searches for a pattern of text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Search for any usage of async functions in JS files.&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"async function"&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.js

&lt;span class="c"&gt;# Search for all lines that import modules (ES6 style).&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"^import"&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;find&lt;/code&gt; – Find files or folders
&lt;/h4&gt;

&lt;p&gt;Use this to find files by name, type, or size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Find all JavaScript files in the src/ directory and its subdirectories.&lt;/span&gt;
find ./src &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.js"&lt;/span&gt;

&lt;span class="c"&gt;# Find all test files that end with .test.js.&lt;/span&gt;
find &lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; f &lt;span class="nt"&gt;-name&lt;/span&gt; &lt;span class="s2"&gt;"*.test.js"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;nano&lt;/code&gt; – The simple editor
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;nano&lt;/code&gt; is a very easy-to-use editor for beginners allow you edit the files in the terminal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;nano index.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This opens &lt;code&gt;config.yaml&lt;/code&gt; for you to edit.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Press &lt;code&gt;Ctrl + O&lt;/code&gt; to save your changes.&lt;/li&gt;
&lt;li&gt;  Press &lt;code&gt;Ctrl + X&lt;/code&gt; to exit.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3. Basic Git Commands
&lt;/h3&gt;

&lt;p&gt;You will use Git every day. Here are the most common commands.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;code&gt;git status&lt;/code&gt; - See what files have changed.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;git add &amp;lt;file&amp;gt;&lt;/code&gt; - Prepare a file to be saved.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;git commit -m "Your message"&lt;/code&gt; - Save your changes with a message.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;git log --oneline&lt;/code&gt; - See a short history of all your saves.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;git pull&lt;/code&gt; - Get the latest changes from the server.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;git push&lt;/code&gt; - Send your saved changes to the server.&lt;/li&gt;
&lt;li&gt;  &lt;code&gt;git clone &amp;lt;url&amp;gt;&lt;/code&gt; - Copy a project from a server to your computer.&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  4. Processing Text
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;awk&lt;/code&gt; – Get a specific column of text
&lt;/h4&gt;

&lt;p&gt;Imagine you have a log file where data is separated by spaces. &lt;code&gt;awk&lt;/code&gt; can pull out just the columns you want.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# From a Node.js server log, print the first column (the timestamp).&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $1}'&lt;/span&gt; server.log

&lt;span class="c"&gt;# Print the IP address if it's the third column.&lt;/span&gt;
&lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $3}'&lt;/span&gt; server.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;sed&lt;/code&gt; – Find and replace text
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;sed&lt;/code&gt; is for finding and replacing text in a stream or file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Replace 'development' with 'production' in a .env file.&lt;/span&gt;
&lt;span class="c"&gt;# This only prints the result; it doesn't change the file.&lt;/span&gt;
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s1"&gt;'s/development/production/g'&lt;/span&gt; .env

&lt;span class="c"&gt;# To update the file in-place, use the -i flag.&lt;/span&gt;
&lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; &lt;span class="s1"&gt;'s/development/production/g'&lt;/span&gt; .env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;jq&lt;/code&gt; – Work with JSON
&lt;/h4&gt;

&lt;p&gt;If you work with APIs or config files like &lt;code&gt;package.json&lt;/code&gt;, &lt;code&gt;jq&lt;/code&gt; is a powerful tool for handling JSON.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Pretty-print package.json&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;package.json | jq &lt;span class="s1"&gt;'.'&lt;/span&gt;

&lt;span class="c"&gt;# Get the value of the "name" field in package.json&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;package.json | jq &lt;span class="s1"&gt;'.name'&lt;/span&gt;

&lt;span class="c"&gt;# Get all dependency names from package.json&lt;/span&gt;
&lt;span class="nb"&gt;cat &lt;/span&gt;package.json | jq &lt;span class="s1"&gt;'.dependencies | keys[]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  5. Network Commands You Should Know
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;ping&lt;/code&gt; – Is the server online?
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;ping&lt;/code&gt; to check if you can reach a server.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ping google.com

&lt;span class="c"&gt;# Ping 4 times and then stop.&lt;/span&gt;
ping &lt;span class="nt"&gt;-c&lt;/span&gt; 4 google.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it works, you’ll see replies with response times (e.g., &lt;code&gt;64 bytes from ... time=23.4 ms&lt;/code&gt;). If it’s not , you’ll get errors like &lt;code&gt;Request timed out&lt;/code&gt; or &lt;code&gt;Destination Host Unreachable&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;code&gt;curl&lt;/code&gt; – Talk to APIs
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;curl&lt;/code&gt; is a great tool for testing APIs from the command line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Send a GET request to a health check endpoint.&lt;/span&gt;
curl http://localhost:8080/health

&lt;span class="c"&gt;# Send a POST request with JSON data.&lt;/span&gt;
curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8080/users &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"name": "new dev"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;wget&lt;/code&gt; – Download files
&lt;/h4&gt;

&lt;p&gt;Use &lt;code&gt;wget&lt;/code&gt; to download a file from a URL.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;wget https://example.com/some-file.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;code&gt;lsof&lt;/code&gt; and &lt;code&gt;netstat&lt;/code&gt; – What's using that port?
&lt;/h4&gt;

&lt;p&gt;If you get an error like "port already in use," these commands can help.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Show me what program is using port 8080.&lt;/span&gt;
lsof &lt;span class="nt"&gt;-i&lt;/span&gt; :8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will show you the command and PID using the port. You can then use &lt;code&gt;kill&lt;/code&gt; to stop it if you need to.&lt;/p&gt;




&lt;p&gt;You don't need to remember all these commands at once. The best way to learn is to start using them for your real projects.&lt;/p&gt;

&lt;p&gt;Start with simple things: moving between folders, editing a config file, checking logs, or running your app.&lt;/p&gt;

&lt;p&gt;Once you are comfortable, you will see that the command line is a powerful tool. You can build your own scripts for testing, deploying, and monitoring your work. And that is a very important skill for a developer.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>bash</category>
    </item>
  </channel>
</rss>
