<?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: velodeck</title>
    <description>The latest articles on DEV Community by velodeck (@velodeck).</description>
    <link>https://dev.to/velodeck</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4073324%2Ff38f5eef-3a17-430d-ac1e-249ae3b8b8fd.png</url>
      <title>DEV Community: velodeck</title>
      <link>https://dev.to/velodeck</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/velodeck"/>
    <language>en</language>
    <item>
      <title>How to Build Automated GitHub Repo Delivery with Next.js 16, Lemon Squeezy, &amp; Octokit</title>
      <dc:creator>velodeck</dc:creator>
      <pubDate>Mon, 17 Aug 2026 06:37:48 +0000</pubDate>
      <link>https://dev.to/velodeck/how-to-build-automated-github-repo-delivery-with-nextjs-16-lemon-squeezy-octokit-1667</link>
      <guid>https://dev.to/velodeck/how-to-build-automated-github-repo-delivery-with-nextjs-16-lemon-squeezy-octokit-1667</guid>
      <description>&lt;p&gt;Selling a developer starter kit, boilerplate, or private repository manually is a massive time sink. Every time a purchase comes through, you have to log into GitHub and manually invite the customer's handle.&lt;/p&gt;

&lt;p&gt;To solve this, you can build a zero-touch fulfillment pipeline:&lt;/p&gt;

&lt;p&gt;Collect the buyer's GitHub username at checkout.&lt;/p&gt;

&lt;p&gt;Receive a signed HMAC webhook from Lemon Squeezy.&lt;/p&gt;

&lt;p&gt;Verify the payload using the Next.js 16 App Router.&lt;/p&gt;

&lt;p&gt;Automate the repository invitation via Octokit.&lt;/p&gt;

&lt;p&gt;Here is the complete step-by-step implementation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Capture the GitHub Handle at Checkout
When setting up your product on Lemon Squeezy, pass the buyer's GitHub username in the checkout URL as custom data:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TypeScript&lt;br&gt;
const checkoutUrl = &lt;code&gt;https://your-store.lemonsqueezy.com/checkout/buy/variant_id?checkout[custom][github_username]=${username}&lt;/code&gt;;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify the Signed Webhook Signature
To ensure incoming POST requests originate from Lemon Squeezy rather than a malicious source, verify the X-Signature header using your webhook signing secret.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create app/api/webhooks/lemon-squeezy/route.ts:&lt;/p&gt;

&lt;p&gt;TypeScript&lt;br&gt;
import crypto from "node:crypto";&lt;br&gt;
import { NextRequest, NextResponse } from "next/server";&lt;br&gt;
import { Octokit } from "@octokit/rest";&lt;/p&gt;

&lt;p&gt;const octokit = new Octokit({ auth: process.env.GITHUB_PAT });&lt;/p&gt;

&lt;p&gt;export async function POST(request: NextRequest) {&lt;br&gt;
  const secret = process.env.LEMON_SQUEEZY_WEBHOOK_SECRET;&lt;br&gt;
  if (!secret) return NextResponse.json("Missing secret", { status: 500 });&lt;/p&gt;

&lt;p&gt;const rawBody = await request.text();&lt;br&gt;
  const signature = Buffer.from(request.headers.get("X-Signature") ?? "", "hex");&lt;/p&gt;

&lt;p&gt;if (!signature.length || !rawBody.length) {&lt;br&gt;
    return NextResponse.json("Invalid request", { status: 400 });&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;// HMAC SHA-256 verification&lt;br&gt;
  const hmac = Buffer.from(&lt;br&gt;
    crypto.createHmac("sha256", secret).update(rawBody).digest("hex"),&lt;br&gt;
    "hex"&lt;br&gt;
  );&lt;/p&gt;

&lt;p&gt;if (!crypto.timingSafeEqual(hmac, signature)) {&lt;br&gt;
    return NextResponse.json("Unauthorized signature", { status: 401 });&lt;br&gt;
  }&lt;/p&gt;

&lt;p&gt;const payload = JSON.parse(rawBody);&lt;br&gt;
  const eventName = payload.meta.event_name;&lt;/p&gt;

&lt;p&gt;if (eventName === "order_created") {&lt;br&gt;
    const githubUsername = payload.meta.custom_data?.github_username;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (githubUsername) {
  await octokit.rest.repos.addCollaborator({
    owner: process.env.GITHUB_ORG_OR_USER!,
    repo: process.env.GITHUB_PRIVATE_REPO!,
    username: githubUsername,
    permission: "push",
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;return NextResponse.json({ success: true }, { status: 200 });&lt;br&gt;
}&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Environment Setup
Add your keys to your .env.local file:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Code snippet&lt;br&gt;
LEMON_SQUEEZY_WEBHOOK_SECRET=your_webhook_secret&lt;br&gt;
GITHUB_PAT=ghp_your_personal_access_token&lt;br&gt;
GITHUB_ORG_OR_USER=your_github_handle&lt;br&gt;
GITHUB_PRIVATE_REPO=your_private_repo_name&lt;br&gt;
Conclusion&lt;br&gt;
This setup turns your digital product into a completely hands-off system.&lt;/p&gt;

&lt;p&gt;Want to skip setting this up manually?&lt;/p&gt;

&lt;p&gt;If you want a full production-ready Next.js 16 setup with Supabase authentication, database schemas, UI components, and built-in repository fulfillment, check out &lt;a href="//velodeck.pro"&gt;Velodeck&lt;/a&gt; .&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>showdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Building automated GitHub repo delivery using Next.js 16, Supabase, and Lemon Squeezy</title>
      <dc:creator>velodeck</dc:creator>
      <pubDate>Tue, 11 Aug 2026 15:04:36 +0000</pubDate>
      <link>https://dev.to/velodeck/building-automated-github-repo-delivery-using-nextjs-16-supabase-and-lemon-squeezy-3jgc</link>
      <guid>https://dev.to/velodeck/building-automated-github-repo-delivery-using-nextjs-16-supabase-and-lemon-squeezy-3jgc</guid>
      <description>&lt;p&gt;The Problem&lt;br&gt;
Every time I started building a new developer tool or boilerplate, I found myself spending 20+ hours wiring up:&lt;/p&gt;

&lt;p&gt;Payment provider webhooks&lt;/p&gt;

&lt;p&gt;Database schemas and Row Level Security&lt;/p&gt;

&lt;p&gt;Manual repository access control&lt;/p&gt;

&lt;p&gt;To eliminate this headache, I built VeloDeck—a Next.js 16 + Supabase boilerplate designed to automate post-purchase delivery.&lt;/p&gt;

&lt;p&gt;How the Automated Fulfillment Works&lt;br&gt;
Checkout: The buyer provides their GitHub username during checkout.&lt;/p&gt;

&lt;p&gt;Webhook Verification: Lemon Squeezy sends a signed HMAC order_created webhook.&lt;/p&gt;

&lt;p&gt;API Processing: Next.js 16 App Router verifies the request payload signature.&lt;/p&gt;

&lt;p&gt;Octokit Trigger: A serverless function runs Octokit to instantly send a private repository invite to the user.&lt;/p&gt;

&lt;p&gt;Check out the live demo: &lt;a href="https://www.velodeck.pro" rel="noopener noreferrer"&gt;https://www.velodeck.pro&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear your feedback on the architecture!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>showdev</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
