<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Tejaswa Hinduja</title>
    <description>The latest articles on DEV Community by Tejaswa Hinduja (@tejaswahinduja).</description>
    <link>https://dev.to/tejaswahinduja</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%2F2671628%2F1b9d960e-e3e4-4007-9250-7ff06772535c.jpg</url>
      <title>DEV Community: Tejaswa Hinduja</title>
      <link>https://dev.to/tejaswahinduja</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tejaswahinduja"/>
    <language>en</language>
    <item>
      <title>How to Build an agent using coral</title>
      <dc:creator>Tejaswa Hinduja</dc:creator>
      <pubDate>Sun, 31 May 2026 17:24:41 +0000</pubDate>
      <link>https://dev.to/tejaswahinduja/how-to-build-an-agent-using-coral-17lf</link>
      <guid>https://dev.to/tejaswahinduja/how-to-build-an-agent-using-coral-17lf</guid>
      <description>&lt;h1&gt;
  
  
  How I Built an AI Agent That Queries GitHub, Calendar, and Sleep Data With One SQL Interface
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;A practical guide to Coral — the local-first SQL runtime that gives your agents a single query layer over any API&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I spent the better part of a week building an agent that could answer questions like "why am I not productive lately?" The idea was simple: pull data from GitHub, Google Calendar, and sleep tracking, cross-reference everything, and get an AI answer.&lt;/p&gt;

&lt;p&gt;The hard part turned out to be the data plumbing. Every source has its own auth, its own pagination, its own quirks. By the time I had GitHub and Calendar talking to the same script, I had written more glue code than actual agent logic.&lt;/p&gt;

&lt;p&gt;Then I found Coral.&lt;/p&gt;

&lt;p&gt;This post walks through what Coral is, why it matters for agent development, and how to build a working AI agent with it from scratch.&lt;/p&gt;




&lt;h2&gt;
  
  
  The problem with how agents access data today
&lt;/h2&gt;

&lt;p&gt;Most agent workflows look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent → Tool A → API A
Agent → Tool B → API B
Agent → Tool C → API C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each tool call is isolated. The agent has to reason about three separate schemas, handle three different auth flows, and then try to mentally join the results. This creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Too many LLM round-trips&lt;/strong&gt; — each tool call is its own context window exchange&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repeated glue code&lt;/strong&gt; — pagination, retry logic, rate limiting, per source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Poor cross-source reasoning&lt;/strong&gt; — the LLM sees results one at a time, not as a unified dataset&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High token costs&lt;/strong&gt; — raw API responses are verbose JSON, not trimmed result sets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The benchmark from the Coral team actually quantified this: across 82 real-world tasks, Claude was &lt;strong&gt;20% more accurate&lt;/strong&gt; and &lt;strong&gt;2x more cost efficient&lt;/strong&gt; using Coral versus direct provider MCPs. For complex multi-hop queries (the kind coding agents actually do), accuracy jumped &lt;strong&gt;31%&lt;/strong&gt; and cost dropped &lt;strong&gt;3.4x&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The reason is architectural. Coral gives agents &lt;strong&gt;one SQL interface&lt;/strong&gt; over everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Coral?
&lt;/h2&gt;

&lt;p&gt;Coral is a &lt;strong&gt;local-first SQL runtime&lt;/strong&gt; that sits between your agent and your data sources. You write SQL, Coral translates it into API calls (handling auth, pagination, and retries), and returns clean tabular rows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Your Agent → SQL → Coral → GitHub API
                         → Google Calendar API  
                         → Local JSONL files
                   ↓
              One result set
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key properties:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Local-first.&lt;/strong&gt; Everything runs on your machine. Credentials are stored locally and never leave. Coral is a read layer — it makes API calls on your behalf but doesn't send your data anywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sources as SQL schemas.&lt;/strong&gt; When you connect GitHub, it appears as a &lt;code&gt;github&lt;/code&gt; schema. You query &lt;code&gt;github.commits&lt;/code&gt;, &lt;code&gt;github.issues&lt;/code&gt;, &lt;code&gt;github.pulls&lt;/code&gt; just like database tables. Same pattern for every source.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Joins across sources.&lt;/strong&gt; Because every source looks like a SQL table, you can &lt;code&gt;JOIN&lt;/code&gt; across them. Coral executes the join locally after fetching each side. That single query replaces three separate tool calls and the LLM reasoning needed to combine them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MCP server built-in.&lt;/strong&gt; Coral ships with an MCP server so you can wire it directly into Claude Code, Cursor, or any MCP-compatible agent with one command.&lt;/p&gt;




&lt;h2&gt;
  
  
  Installing Coral
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;macOS:&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;brew &lt;span class="nb"&gt;install &lt;/span&gt;withcoral/tap/coral
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Linux:&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;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://withcoral.com/install.sh | sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows (10/11 x86_64):&lt;/strong&gt;&lt;br&gt;
Download &lt;code&gt;coral-x86_64-pc-windows-msvc.zip&lt;/code&gt; from the &lt;a href="https://github.com/withcoral/coral/releases" rel="noopener noreferrer"&gt;latest GitHub release&lt;/a&gt;, extract it, and add &lt;code&gt;coral.exe&lt;/code&gt; to your PATH.&lt;/p&gt;

&lt;p&gt;Verify the install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;coral &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Connecting your first source
&lt;/h2&gt;

&lt;p&gt;Coral ships with bundled sources for GitHub, Google Calendar, Linear, Sentry, Datadog, Stripe, Slack, and more. See everything available:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;coral &lt;span class="nb"&gt;source &lt;/span&gt;discover
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's connect GitHub. You'll need a &lt;a href="https://github.com/settings/tokens" rel="noopener noreferrer"&gt;Personal Access Token&lt;/a&gt; with &lt;code&gt;repo&lt;/code&gt; and &lt;code&gt;read:user&lt;/code&gt; scopes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;coral &lt;span class="nb"&gt;source &lt;/span&gt;add &lt;span class="nt"&gt;--interactive&lt;/span&gt; github
&lt;span class="c"&gt;# Coral will prompt: Enter your GitHub PAT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once connected, verify it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;coral sql &lt;span class="s2"&gt;"SELECT schema_name, table_name FROM coral.tables WHERE schema_name = 'github'"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see rows for &lt;code&gt;github.commits&lt;/code&gt;, &lt;code&gt;github.issues&lt;/code&gt;, &lt;code&gt;github.pulls&lt;/code&gt;, &lt;code&gt;github.user&lt;/code&gt;, and others.&lt;/p&gt;

&lt;p&gt;Try a real query:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;coral sql &lt;span class="s2"&gt;"
  SELECT CAST(commit__author__date AS DATE) AS date, COUNT(*) AS commits
  FROM github.commits
  WHERE owner = 'your-username'
    AND commit__author__date &amp;gt;= NOW() - INTERVAL '7 days'
  GROUP BY 1
  ORDER BY 1 DESC
"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Coral flattens nested JSON with &lt;code&gt;__&lt;/code&gt; as the separator.&lt;/strong&gt; So &lt;code&gt;commit.author.date&lt;/code&gt; in the GitHub API response becomes &lt;code&gt;commit__author__date&lt;/code&gt; in your SQL. Run &lt;code&gt;SELECT column_name FROM coral.columns WHERE schema_name = 'github' AND table_name = 'commits'&lt;/code&gt; to inspect the exact column names for any table.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Building the agent
&lt;/h2&gt;

&lt;p&gt;We'll build a Node.js agent that answers natural language questions about your GitHub activity. Ask it "what have I been shipping this week?" and it queries your real commit data and returns an AI-generated summary.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project setup
&lt;/h3&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;my-coral-agent &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;my-coral-agent
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; @google/genai dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GEMINI_API_KEY=your_key_here
GITHUB_USERNAME=your_github_username
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The agent — &lt;code&gt;agent.ts&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;The full agent is around 80 lines. Here's how it works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Query Coral for real data&lt;/strong&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;execFileSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;coralQuery&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;execFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;coral&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--format&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf-8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ignore&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;  &lt;span class="c1"&gt;// suppress Coral's stderr&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We call Coral's CLI and ask for JSON output. &lt;code&gt;execFileSync&lt;/code&gt; blocks until Coral finishes — Coral handles all the GitHub API calls, pagination, and auth internally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Gather the data&lt;/strong&gt;&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getGithubActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Commits per day&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;coralQuery&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;repos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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="s2"&gt;`
    SELECT
      CAST(commit__author__date AS DATE)   AS date,
      ARRAY_AGG(DISTINCT repo)             AS repos,
      COUNT(*)                             AS count
    FROM github.commits
    WHERE owner = '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'
      AND commit__author__date &amp;gt;= NOW() - INTERVAL '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; days'
    GROUP BY 1
    ORDER BY 1 DESC
  `&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Open PRs&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;prs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;coralQuery&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="s2"&gt;`
    SELECT title, state, created_at
    FROM github.pulls
    WHERE owner = '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'
      AND created_at &amp;gt;= NOW() - INTERVAL '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;days&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; days'
    ORDER BY created_at DESC
    LIMIT 20
  `&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;commits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prs&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;Step 3: Ask Gemini&lt;/strong&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GoogleGenAI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@google/genai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&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;ai&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;GoogleGenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;apiKey&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;GEMINI_API_KEY&lt;/span&gt;&lt;span class="o"&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;response&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;ai&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;models&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generateContent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gemini-2.5-flash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;systemInstruction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`You are a developer productivity assistant. 
        You have access to real GitHub data. Be direct and specific. 
        Reference actual repos and dates from the data.`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`
      Developer question: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"

      GitHub data (last 7 days):
      &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;

      Answer the question using this data.
    `&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="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Wire it together&lt;/strong&gt;&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dotenv&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="nx"&gt;dotenv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt; &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Usage: npx tsx agent.ts "what have I been working on?"&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;username&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_USERNAME&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Querying GitHub via Coral...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="kd"&gt;let&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;object&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getGithubActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;username&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Coral query failed:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Analyzing...&lt;/span&gt;&lt;span class="se"&gt;\n&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;answer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;question&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;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx tsx agent.ts &lt;span class="s2"&gt;"what have I been shipping this week?"&lt;/span&gt;
npx tsx agent.ts &lt;span class="s2"&gt;"which repo am I spending the most time on?"&lt;/span&gt;
npx tsx agent.ts &lt;span class="s2"&gt;"have I been less active than usual?"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent queries your live GitHub data, hands it to Gemini, and returns a natural language answer grounded in actual commit history.&lt;/p&gt;




&lt;h2&gt;
  
  
  Going further: cross-source queries
&lt;/h2&gt;

&lt;p&gt;The real power of Coral is joins across sources. Add a second source:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;coral &lt;span class="nb"&gt;source &lt;/span&gt;add &lt;span class="nt"&gt;--interactive&lt;/span&gt; google_calendar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can ask questions that span both:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="c1"&gt;-- Commits on days with heavy meeting load&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt;
  &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit__author__date&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;date&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;DISTINCT&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sha&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;commits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;DISTINCT&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;                 &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;meetings&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commits&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;google_calendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;events&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;
  &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit__author__date&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;CAST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;start_date_time&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="nb"&gt;DATE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'your-username'&lt;/span&gt;
  &lt;span class="k"&gt;AND&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;commit__author__date&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;INTERVAL&lt;/span&gt; &lt;span class="s1"&gt;'30 days'&lt;/span&gt;
&lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a query that would normally require two separate API calls, result storage, and manual joining in your agent code. With Coral, it's one SQL statement.&lt;/p&gt;




&lt;h2&gt;
  
  
  Using Coral over MCP
&lt;/h2&gt;

&lt;p&gt;If you're using Claude Code, Cursor, or any MCP-compatible agent, you can expose Coral as an MCP server — no custom code required:&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;# Claude Code&lt;/span&gt;
claude mcp add &lt;span class="nt"&gt;--scope&lt;/span&gt; user coral &lt;span class="nt"&gt;--&lt;/span&gt; coral mcp-stdio
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this, your agent can query all connected sources directly using natural language. Ask it to "show me open GitHub issues assigned to me" and it will write the SQL and run it through Coral automatically.&lt;/p&gt;

&lt;p&gt;You can also install Coral's skills to teach your agent the discovery-first workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx skills add withcoral/skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives your agent knowledge of &lt;code&gt;coral.tables&lt;/code&gt;, &lt;code&gt;coral.columns&lt;/code&gt;, and the metadata tables it needs to explore schemas before writing queries.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I actually built
&lt;/h2&gt;

&lt;p&gt;The agent I described at the start — the one that cross-references GitHub, Calendar, and sleep data to answer "why am I not productive?" — uses exactly this pattern.&lt;/p&gt;

&lt;p&gt;The behavioral metrics engine computes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sleep decline vs baseline&lt;/li&gt;
&lt;li&gt;Late-night coding session frequency
&lt;/li&gt;
&lt;li&gt;Meeting load increase as a percentage over your own baseline&lt;/li&gt;
&lt;li&gt;Context switching (repos per day, live from GitHub commits)&lt;/li&gt;
&lt;li&gt;Interruption count trends&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of it feeds into Gemini as a structured prompt. The result looks like this in the terminal:&lt;br&gt;
&lt;/p&gt;

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

  ▘▀▀▀▀▀▀▀▀▀▀▀▝
  ▌  75/100    ▐
  ▌    HIGH    ▐
  ▗▄▄▄███████▄▖

  ────────────────────────────────────────────────

  TL;DR
  ────────────────────────────────────────
  Sleep dropped 38% while meetings tripled — you're
  compensating with late-night coding and it's not working.

  KEY FINDINGS
  ────────────────────────────────────────
  ◆ Average sleep fell from 8.1h to 5.0h over 30 days
  ◆ Meetings increased from 1.5/day to 5.2/day (+180%)
  ◆ 6 late-night coding sessions in the last 7 days vs 0 in baseline
  ◆ Context switching across 4 repos/day vs 1 repo/day baseline
  ◆ Productivity score: 36/100 (down from 79 baseline)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full source is on GitHub. The key file is &lt;a href="//src/coral/sources/github.ts"&gt;src/coral/sources/github.ts&lt;/a&gt; which shows exactly how to wrap Coral queries in a TypeScript function and handle the column naming conventions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Coral is one of those tools that removes a whole category of boilerplate. Instead of writing per-source auth, pagination, and retry logic, you write SQL. Instead of your agent reasoning about three separate tool outputs, it reasons about one result set.&lt;/p&gt;

&lt;p&gt;The setup is:&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;# 1. Install&lt;/span&gt;
brew &lt;span class="nb"&gt;install &lt;/span&gt;withcoral/tap/coral   &lt;span class="c"&gt;# or curl on Linux, zip on Windows&lt;/span&gt;

&lt;span class="c"&gt;# 2. Connect a source  &lt;/span&gt;
coral &lt;span class="nb"&gt;source &lt;/span&gt;add &lt;span class="nt"&gt;--interactive&lt;/span&gt; github

&lt;span class="c"&gt;# 3. Query&lt;/span&gt;
coral sql &lt;span class="s2"&gt;"SELECT repo, COUNT(*) FROM github.commits WHERE owner = 'you' GROUP BY 1"&lt;/span&gt;

&lt;span class="c"&gt;# 4. Use in your agent&lt;/span&gt;
execFileSync&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'coral'&lt;/span&gt;, &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'sql'&lt;/span&gt;, &lt;span class="s1"&gt;'--format'&lt;/span&gt;, &lt;span class="s1"&gt;'json'&lt;/span&gt;, query]&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's really it. The complexity sits inside Coral, and your agent code stays clean.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you build something with Coral, I'd like to see it. The xetroc source is at &lt;a href="https://github.com" rel="noopener noreferrer"&gt;github.com/TejaswaHinduja/xetroc&lt;/a&gt; if you want a reference implementation to work from.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>sql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Solana Token Launchpad (with metadata) -2</title>
      <dc:creator>Tejaswa Hinduja</dc:creator>
      <pubDate>Fri, 06 Mar 2026 15:26:50 +0000</pubDate>
      <link>https://dev.to/tejaswahinduja/solana-token-launchpad-with-metadata-2-46o1</link>
      <guid>https://dev.to/tejaswahinduja/solana-token-launchpad-with-metadata-2-46o1</guid>
      <description>&lt;p&gt;I hope you are coming from the previous &lt;a href="https://dev.to/tejaswahinduja/how-to-build-a-solana-token-launchpad-with-metadata-37cp"&gt;blog &lt;/a&gt;&lt;br&gt;
So we created tokens using the token-22 program which  supports extensions (Metadata Pointer Extension) stored directly in the mint account.&lt;/p&gt;

&lt;p&gt;Token-2022 can store basic metadata on-chain:-name,symbol,uri,etc.&lt;br&gt;
The uri is a link to off-chain metadata json &lt;br&gt;
{&lt;br&gt;
  "name": "My Token",&lt;br&gt;
  "symbol": "MT",&lt;br&gt;
  "description": "Example token",&lt;br&gt;
  "image": "arweave://...",&lt;br&gt;
  "attributes": [...]&lt;br&gt;
}&lt;br&gt;
There are a few ways to store this json, the easiest i found is through irys(arweave).Lets get started with that, install these first @irys/web-upload-solana , @irys/web-upload &lt;br&gt;
Lets first set up the a irys uploader &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv3q0cemfrawru1eusoh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv3q0cemfrawru1eusoh.png" alt=" " width="800" height="285"&gt;&lt;/a&gt;&lt;br&gt;
and fund the irys account so that they give us some storage to upload our data&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6tzsfb67z7gw3mt3mhm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe6tzsfb67z7gw3mt3mhm.png" alt=" " width="696" height="526"&gt;&lt;/a&gt;&lt;br&gt;
Now do you remember in the last blog we built a form for the user to enter some metadata for the token, now we need to upload that metadata and convert it into a metaplex std json &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fjviatrkuoa5u6kd92j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4fjviatrkuoa5u6kd92j.png" alt=" " width="800" height="567"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbd49f8g63ngkwbwxifc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbd49f8g63ngkwbwxifc.png" alt=" " width="731" height="383"&gt;&lt;/a&gt;&lt;br&gt;
What this function does is it takes the input from the form and converts it into a json(metaplex std) and then gives it to irys which then returns a uri.&lt;br&gt;
Now we store this uri in our metadata object and use it while creating the mint account&lt;br&gt;
&lt;code&gt;createInitializeInstruction({&lt;br&gt;
                    programId: TOKEN_2022_PROGRAM_ID,&lt;br&gt;
                    mint: mintKeypair.publicKey,&lt;br&gt;
                    metadata: mintKeypair.publicKey,&lt;br&gt;
                    name: metadata.name,&lt;br&gt;
                    symbol: metadata.symbol,&lt;br&gt;
                    uri: metadata.uri,&lt;br&gt;
                    mintAuthority: wallet.publicKey,&lt;br&gt;
                    updateAuthority: wallet.publicKey,&lt;br&gt;
}),&lt;/code&gt;&lt;br&gt;
And we are done, few things i would like to add, I am storing only the json ideally you want to store everything on areweave or ipfs including the image.&lt;br&gt;
Also how do wallets discover the metadata and show token image:-&lt;br&gt;
When a wallet detects a token in your account, it first reads the mint account from the token program From this it learns about mint address,extensions and some other stuff.If the mint uses the TokenMetadata extension, the wallet reads:name,symbol,uri.&lt;/p&gt;

&lt;p&gt;If you found the blog helpful give it a like and follow, also connect on socials:-&lt;br&gt;
Twitter:-&lt;a href="https://x.com/Tej_Codes" rel="noopener noreferrer"&gt;https://x.com/Tej_Codes&lt;/a&gt;&lt;br&gt;
LinkedIn:-&lt;a href="https://linkedin.com/in/TejaswaHinduja" rel="noopener noreferrer"&gt;https://linkedin.com/in/TejaswaHinduja&lt;/a&gt;&lt;/p&gt;

</description>
      <category>web3</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>solana</category>
    </item>
    <item>
      <title>How to build a solana token launchpad (with metadata)</title>
      <dc:creator>Tejaswa Hinduja</dc:creator>
      <pubDate>Tue, 10 Feb 2026 12:25:23 +0000</pubDate>
      <link>https://dev.to/tejaswahinduja/how-to-build-a-solana-token-launchpad-with-metadata-37cp</link>
      <guid>https://dev.to/tejaswahinduja/how-to-build-a-solana-token-launchpad-with-metadata-37cp</guid>
      <description>&lt;p&gt;This blog is relevant for anybody who is just getting started in web3 just like me and is wondering what is all this token stuff.&lt;br&gt;
First just install all the dependencies, I am using nextjs,typescript,yarn(npm wasnt working idk why)&lt;br&gt;
&lt;code&gt;@solana/spl-token","@solana/spl-token-metadata","@solana/wallet-adapter-base","@solana/wallet-adapter-react","@solana/wallet-adapter-react-ui","@solana/wallet-adapter-wallets","@solana/web3.js"&lt;/code&gt;&lt;br&gt;
So we are building a solana token launchpad using the token22 program.&lt;br&gt;
To make tokens first we need a mint account,&lt;br&gt;
We need few things to make a Mint account:-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A keypair&lt;/li&gt;
&lt;li&gt;The user's public key&lt;/li&gt;
&lt;li&gt;Rent value&lt;/li&gt;
&lt;li&gt;space&lt;/li&gt;
&lt;li&gt;programId(which is token22)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sccbbao3n97szo7o92y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sccbbao3n97szo7o92y.png" alt=" " width="549" height="252"&gt;&lt;/a&gt;&lt;br&gt;
Now lets get to the token creation part,Obviously the token needs to have a name and a symbol and some other metadata so lets get that sorted.&lt;br&gt;
Create a form &lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgz2x9pzhv69lf2ppsth3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgz2x9pzhv69lf2ppsth3.png" alt=" " width="677" height="270"&gt;&lt;/a&gt;&lt;br&gt;
and find the space,rent which would be required&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8njr432kmo74jc466qf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj8njr432kmo74jc466qf.png" alt=" " width="800" height="313"&gt;&lt;/a&gt;&lt;br&gt;
Next step is to add the instructions for setting up the metadata and the mint&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7mdljnyh57t5njncyq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi7mdljnyh57t5njncyq1.png" alt=" " width="568" height="482"&gt;&lt;/a&gt;&lt;br&gt;
Now we need to add the users public key to the transaction and also the recent blockhash(unlike eth where programs can get verfied after a few days, in solana it doesnt work like that) and we partially sign the transaction since we do not have the users private key and only have the mint account keypair, the wallet then asks the user to sign the transaction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefdi3dgnt5rau6shnxkd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fefdi3dgnt5rau6shnxkd.png" alt=" " width="754" height="134"&gt;&lt;/a&gt;&lt;br&gt;
and then finally wrap the function inside the wallet provider,&lt;br&gt;
Most of the things are done in the next blog ill share about how to store the metadata.&lt;br&gt;
and Obviously I am talking about devnet here and not real prod&lt;/p&gt;

&lt;p&gt;If you liked the blog&lt;br&gt;
Connect on socials:-&lt;br&gt;
Twitter:-&lt;a href="https://x.com/Tej_Codes" rel="noopener noreferrer"&gt;https://x.com/Tej_Codes&lt;/a&gt;&lt;br&gt;
LinkedIn:-&lt;a href="https://linkedin.com/in/TejaswaHinduja" rel="noopener noreferrer"&gt;https://linkedin.com/in/TejaswaHinduja&lt;/a&gt;&lt;/p&gt;

</description>
      <category>solana</category>
      <category>web3</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>What is CORS?</title>
      <dc:creator>Tejaswa Hinduja</dc:creator>
      <pubDate>Tue, 20 Jan 2026 15:38:08 +0000</pubDate>
      <link>https://dev.to/tejaswahinduja/what-is-cors-340l</link>
      <guid>https://dev.to/tejaswahinduja/what-is-cors-340l</guid>
      <description>&lt;p&gt;So while building full stack projects , I came across this annoying thing called cors, whenever I tried to send a request from my frontend to the backend it never went through and it was pretty frustrating.So here's my attempt to explain it to someone who is just starting out building projects.&lt;/p&gt;

&lt;p&gt;In almost all of the full stack projects you would come across there are two things interacting with each other,the client and the server,For example&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4aoa4slfqdxesiwaul2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj4aoa4slfqdxesiwaul2.png" alt=" " width="800" height="467"&gt;&lt;/a&gt;&lt;br&gt;
Now lets say you have two tabs open in a browser,&lt;br&gt;
1.&lt;a href="https://www.tejaswahinduja.me" rel="noopener noreferrer"&gt;tejaswahinduja.me&lt;/a&gt;&lt;br&gt;
2.Instagram.com&lt;br&gt;
both of the sites would have their own servers&lt;br&gt;
and you are logged into instagram and you now visit tejaswahinduja.me,Lets say I have added some js code on my client side like &lt;strong&gt;fetch(instagram/user/inbox/chats)&lt;/strong&gt; this will send a request to the instagram's server and since you are &lt;strong&gt;already logged in&lt;/strong&gt; your cookies exist, through which the instagram's server can validate that you are logged in and it would return the response,You can now figure out whats wrong here right, tejaswahinduja.me shouldn't be able to access your insta account.To prevent this,The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/Security/Defenses/Same-origin_policy" rel="noopener noreferrer"&gt;same-origin-policy&lt;/a&gt; is a critical security mechanism that restricts how a script loaded from a origin interact with other origins.But now you cannot interact with your frontend and backend since they are two different origins.&lt;br&gt;
**Now how does CORS(cross origin resource sharing) helps in solving this?&lt;br&gt;
First lets see ,What is a origin?A origin is nothing but a tuple of:-scheme(http/https)+host+port for eg:&lt;a href="https://tejaswahinduja.me" rel="noopener noreferrer"&gt;https://tejaswahinduja.me&lt;/a&gt; and &lt;a href="https://www.tejaswahinduja.me" rel="noopener noreferrer"&gt;https://www.tejaswahinduja.me&lt;/a&gt; are two different origins.&lt;br&gt;
CORS is an HTTP-header based mechanism that allows a server to indicate any origins other than its own from which a browser should permit loading resources.In short the backend can decide which client to trust and who not to.How this works it lets the server decide which origins to permit, check the below image.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5a9ea2bx94p3vy315dnb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5a9ea2bx94p3vy315dnb.png" alt=" " width="478" height="345"&gt;&lt;/a&gt;&lt;br&gt;
The server sends a Access-Control-Allow-Origin in the response headers which tells the broswer if the client is allowed or not.By default the cookies are not sent to the server so credentials:include is used to send the cookies to the server.&lt;br&gt;
Well this works perfectly fine when making standard http requests like get and post.&lt;br&gt;
But if the client makes a non-standard http requests like put,delete,etc the browser then first sends a "preflight" request which just checks if the origin is allowed or not.If the origin is not allowed then a CORS error occurs.&lt;br&gt;
That’s CORS in action strict, sometimes frustrating, but essential for web security.&lt;/p&gt;

&lt;p&gt;If you liked the blog, lets connect&lt;br&gt;
Twitter:&lt;a href="https://x.com/Tej_Codes" rel="noopener noreferrer"&gt;https://x.com/Tej_Codes&lt;/a&gt;&lt;br&gt;
Linkedin:&lt;a href="https://www.linkedin.com/in/tejaswa-hinduja-b585b6323/" rel="noopener noreferrer"&gt;https://www.linkedin.com/in/tejaswa-hinduja-b585b6323/&lt;/a&gt;&lt;br&gt;
Github:&lt;a href="https://github.com/TejaswaHinduja" rel="noopener noreferrer"&gt;https://github.com/TejaswaHinduja&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sources:-&lt;br&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CORS&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/watch?v=WWnR4xptSRk" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=WWnR4xptSRk&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>beginners</category>
    </item>
    <item>
      <title>JWT Authentication in typescript,express</title>
      <dc:creator>Tejaswa Hinduja</dc:creator>
      <pubDate>Sat, 22 Nov 2025 08:23:22 +0000</pubDate>
      <link>https://dev.to/tejaswahinduja/jwt-authentication-in-typescriptexpress-5ek2</link>
      <guid>https://dev.to/tejaswahinduja/jwt-authentication-in-typescriptexpress-5ek2</guid>
      <description>&lt;p&gt;Assuming you have express and typescript setup , Lets get right into it&lt;/p&gt;

&lt;p&gt;Step1:- To protect a route we need to first create a token when a user logs in and then verify it when the user tries to reach a protected route.So lets create a function to generate tokens&lt;/p&gt;

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

&lt;p&gt;How this function works:-&lt;br&gt;
The jwt.sign() function takes in 3 parameters as input:-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;payload(in our case it is the Id):-payload is the data which we               want to imbed in our token&lt;/li&gt;
&lt;li&gt;secret:-This is a private key which we will define&lt;/li&gt;
&lt;li&gt;{options}:-There are various optional functionalities we can add such as an expiry timing for the token, the issuer, audience ,etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will create a token for us,Now we need to store this token somewhere so that whenever the user tries to reach a protected route they also send us the token which we can verify.&lt;br&gt;
The best way to store the token is to store it in the cookies.&lt;/p&gt;

&lt;p&gt;The res.cookie() function takes in 3 parameters:-&lt;br&gt;
-name:- this is the name of the cookie , eg “jwt”,&lt;br&gt;
-value:-token in our case is the value&lt;br&gt;
-{options}:- other features like how long should the cookie last , security settings&lt;/p&gt;

&lt;p&gt;Step2:-Now lets create a middleware to protect our routes&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff86s4a06c660kohwr9nf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff86s4a06c660kohwr9nf.png" alt=" " width="637" height="601"&gt;&lt;/a&gt;&lt;br&gt;
So we get our jwt token from the cookies and then verify it using jwt.verify() function,&lt;br&gt;
the verify() function takes in two arguments&lt;br&gt;
-our token&lt;br&gt;
-the secret which we defined&lt;br&gt;
So what the verify() function does is takes the header and payload from the token and recreates the signature using our secret and then compares it to the signature inside our token.&lt;br&gt;
Here is a sample usage of this auth flow in a signup endpoint&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0wrz8wlhma19boga7gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0wrz8wlhma19boga7gy.png" alt=" " width="719" height="897"&gt;&lt;/a&gt;&lt;br&gt;
Once all the checks are done, then gentoken() function creates the token.&lt;/p&gt;

&lt;p&gt;Connect:-&lt;br&gt;
x.com/Tej_Codes&lt;br&gt;
github.com/TejaswaHinduja&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>express</category>
      <category>typescript</category>
      <category>node</category>
    </item>
  </channel>
</rss>
