Cookbook
Fixes your agent reads before it guesses.
293 solution docs. Each one ships in repos that use its battery.
From 26 batteries, the base stack and 31 designs. They land in docs/solutions/, where your agent reads them before it writes code. Every one is published here in full.
293 of 293 docs
Better Auth solution docs
Own your users table. Passwords, magic links, Google, GitHub and Microsoft, all in your database.
Account linking and email verification without account takeovers
When "Continue with Google" joins an existing password account, when it refuses, and why an unverified email address or a trusted provider list can hand one person's account to another.
better-auth · oauth · account-linking · email-verification
Better Auth on the edge: why your session check fails in middleware
Edge runtimes have no TCP sockets and no Node crypto, so a session lookup that works in a page throws in the proxy. Read the cookie there and verify in the render.
better-auth · edge-runtime · middleware · proxy
CSRF, SameSite and the cookie flags that make a session safe
What each session cookie flag actually defends against, why trustedOrigins is your CSRF check, and the three configuration changes that quietly disable both.
better-auth · csrf · cookies · samesite
Guard Better Auth's endpoints, not just your settings forms
Every /api/auth endpoint is a public URL. One hook refuses account changes from an impersonation session and asks for a recent sign-in before a password or provider is added.
better-auth · impersonation · sessions · hooks
The magic-link token: single use, ten minutes, and the scanner that clicks it first
How long the credential lives, why a corporate mail scanner burns it before the human arrives, and why the rate limiter has to be backed by your database rather than by process memory.
better-auth · magic-link · tokens · rate-limit
Moving an existing user table onto Better Auth without logging everyone out
Map your columns to the four required tables, backfill ids and accounts, and let people migrate themselves on next sign-in instead of forcing a password reset.
better-auth · migration · users · passwords
oauth-callback-url-mismatches
Password reset tokens that cannot be replayed, guessed or leaked
One hour, single use, answered the same way for every address, and kept out of logs, Referer headers and search results. What Better Auth does for you and the four things it cannot.
better-auth · passwords · reset · tokens
Modelling roles you will not regret when the admin panel grows
A role column, a ranked vocabulary in one file, and permission checks that name the action, not a boolean isAdmin scattered across forty components.
better-auth · roles · authorization · admin
Session invalidation, or why everyone got logged out on deploy
A rotated secret, a changed cookie name or a wiped database invalidates every session at once. Here is what invalidates what, and how to revoke one user on purpose.
better-auth · sessions · cookies · secrets
Neon solution docs
Serverless Postgres you can branch like git, with a driver built for cold starts.
A Neon branch per preview deployment
Preview deploys that share the production database corrupt it or lie to you. Give every preview its own copy-on-write Neon branch, wired to the deployment's environment variables.
neon · branching · preview-deployments · vercel
Neon cold starts, where the half second goes and what to do about it
Scale-to-zero means an idle branch takes roughly 500 ms to wake, and a serverless function adds its own cold start on top. How to measure the parts and fix the ones that matter.
neon · performance · cold-start · serverless
Connection exhaustion on serverless Postgres, and how to actually fix it
Serverless does not queue requests on a pool, it creates pools. Here is the arithmetic, the four real causes, and the fix for each.
neon · serverless · postgres · connection-pooling
Local Postgres with the Neon serverless driver, no Neon account
The Neon driver speaks HTTPS and WebSocket, not the Postgres wire protocol. A small local proxy plus two neonConfig settings let it run against a Postgres on your laptop, with no code fork.
neon · postgres · local-development · testing
Running migrations on Vercel without a half-applied schema
Vercel has no migration step, so people add one in the wrong place. Where migrations belong in the build, why the direct URL is mandatory, and how to deploy a breaking change in two safe halves.
neon · vercel · migrations · deployment
Neon's pooled and unpooled connection strings, and which one to use where
The -pooler host and the direct host are not interchangeable. Runtime queries need the pooler; migrations, advisory locks and session state need the direct endpoint.
neon · postgres · pgbouncer · connection-pooling
Drizzle ORM solution docs
Typed SQL in TypeScript, no engine binary, and migrations you read as plain SQL.
Adding a NOT NULL column to a table that already has rows
The one-line migration fails on any populated database. Split it into add-nullable, backfill in batches, and enforce: three migrations across two deploys.
drizzle · migrations · postgres · backfill
drizzle-kit generate or drizzle-kit push, and when each is safe
push diffs your schema straight onto the database with no file to review; generate writes SQL you commit. Use push only on a database you can throw away.
drizzle · migrations · postgres · schema
db.query relations or an explicit join: choosing in Drizzle without an N+1
The relational API returns nested objects and one round trip; the core builder returns flat rows and total control. Which to reach for, and the loop that quietly becomes N+1.
drizzle · sql · joins · performance
Transactions in Drizzle on serverless: what works over HTTP and what needs a socket
An interactive db.transaction() needs a real connection held open. On an HTTP driver it silently is not one. Here is what each driver supports and how to write atomic writes without holding a connection.
drizzle · transactions · serverless · neon
Typing partial selects and joins in Drizzle without writing the types by hand
$inferSelect describes the whole row, not the three columns you selected. Use the query builder's inferred types, Awaited<ReturnType<...>>, and helper types instead of hand-maintained interfaces.
drizzle · typescript · types · inference
Stripe solution docs
Hosted Checkout, a customer portal you never build, and webhooks you test locally.
Free trials in Stripe that do not leak access
trialing is an entitled status and trial_will_end is not a payment. Where trials are configured, which events actually matter, and how to stop one person taking ten trials.
stripe · trials · subscriptions · entitlements
Idempotent Stripe webhooks, or claim the event id before you do the work
Stripe delivers at least once, retries for three days and arrives out of order. An event ledger claimed before the handler runs is what stops double grants and lost updates.
stripe · webhooks · idempotency · billing
One-time payments with Stripe Checkout, from lifetime deal to refund
A lifetime deal is a payment-mode Checkout Session, not a subscription. Which id to key it on, when it is really paid, how a receipt goes out, and how a refund or dispute takes the access back.
stripe · checkout · one-time-payments · lifetime-deal
Proration when a customer changes plan, and why you should let the portal do it
Upgrades, downgrades and seat changes each want different proration behaviour. What Stripe actually does, how to preview the amount, and when to build the flow yourself.
stripe · proration · subscriptions · upgrades
Reconciling after a missed Stripe webhook
A customer paid and the app does not know. How to find the gap, replay or re-sync the affected subscriptions and one-time purchases, and build a reconciliation job so the next outage is boring.
stripe · webhooks · reconciliation · incident-response
Stripe Tax, and when you legally need to care
With Stripe you are the merchant of record, so sales tax and VAT are your liability. What Stripe Tax does and does not do, the thresholds that trigger obligations, and when a merchant of record is the better answer.
stripe · tax · vat · sales-tax
Resend solution docs
Transactional email with React Email templates you review in a pull request.
Sending a lot of email without hitting the rate limit or the spam folder
Resend allows a couple of requests a second by default. Use the batch endpoint, add backoff for 429s, keep one idempotency key per recipient, and never batch a magic link.
resend · rate-limits · batching · throughput
Bounces and spam complaints: listen, or lose the inbox for everyone
A hard bounce means the mailbox is gone. Keep sending and mailbox providers downgrade every message from your domain. Wire the webhook, suppress permanently, and never suppress on a soft bounce.
resend · bounces · complaints · webhooks
SPF, DKIM and DMARC: what each record does and why your mail needs all three
Three DNS records decide whether a mailbox provider treats your email as authentic. Here is what each one proves, how to set them up on a subdomain, and how to read a failure.
resend · email · dns · spf
Magic links that actually arrive, and survive the scanner that clicks them first
A sign-in link is the highest-stakes email you send. It has to land in seconds, work once, and survive corporate mail scanners that follow every URL before the human does.
resend · magic-link · deliverability · auth
Previewing React Email templates locally, and what the preview cannot tell you
React Email's preview server renders your templates with realistic props and hot reload. Here is how to set it up, what to check, and the four failure modes only a real client will show you.
resend · react-email · preview · templates
PostHog solution docs
Product analytics, session replay, feature flags and experiments behind one key.
Ad blockers eat a third of your analytics: proxy ingestion through your own domain
Blockers match on hostnames, not behaviour. A first-party /ingest route handler forwards events to PostHog server-side and recovers most of the missing traffic.
posthog · analytics · ad-blockers · reverse-proxy
Event names that still make sense in twelve months
Why analytics projects rot into five spellings of "signup", and the object_verb convention plus a typed catalogue that stops it.
posthog · analytics · naming · conventions
Feature flags without the flicker
Client-side flags render the control experience first and swap it a beat later. Evaluate on the server, pass the decision down, and keep a bootstrap for the client hooks.
posthog · feature-flags · nextjs · ssr
The identify race that empties your signup funnel
Events fired before identify() stay on the anonymous profile forever. Here is why the merge is not retroactive, and the ordering that fixes it.
posthog · analytics · identify · funnels
Server events versus client events, and when each one lies
A browser event is a claim, a server event is a record. Which side to fire from, why serverless drops events without after(), and how to keep the two from double-counting.
posthog · analytics · nextjs · serverless
Sentry solution docs
Stack traces with the release and route attached, scrubbed of user data first.
One issue with 40,000 events: grouping, fingerprints and the helper that ruined them
Sentry groups by stack trace, so a shared fetch wrapper merges every unrelated failure into one useless issue. Fingerprints put the grouping back where the cause is.
sentry · fingerprints · grouping · triage
Scrubbing PII before it leaves your process, not after it reaches Sentry
Server-side scrubbing runs after the data has crossed the network. beforeSend runs in your process, and it is the only layer you fully control.
sentry · pii · privacy · gdpr
Source maps on Vercel: why your production stack traces are unreadable
A minified trace means the build never uploaded source maps. The auth token, the release name and the preview environment are the three things that are usually wrong.
sentry · source-maps · vercel · deployment
Telling a real incident from a bot, a browser extension or a stale tab
Most of a new project's error feed is not your bug. The four signatures of noise, how to filter each one at the right layer, and the three signals that mean it is real.
sentry · triage · noise · bots
Trace sample rates that do not bankrupt you
Errors are cheap and spans are not. How to pick tracesSampleRate, why the edge runtime needs a lower one, and how to keep the traces you actually need while dropping 95% of the rest.
sentry · tracing · performance · cost
Admin panel solution docs
Users, bans, impersonation and an audit log. Your code, any auth provider.
Designing an audit log for an admin panel
One append-only table, namespaced past-tense actions, emails copied in, and a clear rule for when the audit row can share a transaction with the change and when it cannot.
admin · audit-log · postgres · security
Bans that actually sign people out
Setting banned = true stops the next sign-in, not the session already open. What Better Auth, Clerk and Supabase do on a ban, where caches and tokens let a banned user linger, and how to say so.
admin · bans · sessions · security
Empty states that are not sad
An empty state that only says "No data available" is a dead end. It should say what belongs here, why it is missing, and what to do next.
ui · empty-states · admin · design
Making the first admin without a back door
A fresh deploy has no admin, and the admin page needs one to add one. Use a terminal script with database or API credentials, never an env list of emails or a first-user-wins rule.
admin · roles · bootstrap · security
impersonating-users-safely
Paginating admin tables without a client library
Offset pages with a total for the users table, keyset cursors for the audit log, both in the URL and rendered on the server. When to use which, and the details that make each correct.
nextjs · pagination · admin · postgres
Role checks that survive a layout refactor
A check that lives only in a layout disappears the day someone moves the page. Put the boundary where the route is, and check again where the work happens.
nextjs · authorization · admin · layouts
Route group or path segment: how to lay out an admin section
A route group shares a layout without touching the URL; a path segment is the URL. Admin panels need both, and confusing them produces public pages and 404s.
nextjs · app-router · routing · layouts
MDX blog solution docs
Posts are files in your repo. Reviewed in a pull request, shipped with the code.
MDX in the App Router without shipping a compiler
next-mdx-remote compiles every post on every request. Compile at build time with @next/mdx instead, and keep frontmatter with gray-matter.
mdx · nextjs · app-router · performance
OG images that render your font, not Noto
ImageResponse has no system fonts and silently falls back. Load a static TTF from disk, and know why woff2 and variable fonts fail.
opengraph · image-response · satori · fonts
An RSS feed that actually validates
Unescaped ampersands, ISO dates and a missing atom:link are why feed readers reject your feed. Generate it as a static route with escaped text.
rss · feeds · seo · route-handlers
A sitemap and canonical URLs that do not fight each other
lastModified from new Date() teaches crawlers to ignore your dates, and a canonical built from request headers points at your preview deploys.
seo · sitemap · canonical · metadata
Syntax highlighting without a 300kb bundle
Prism and highlight.js in a client component ship a parser to every reader. Highlight at build time with a rehype plugin and ship CSS instead.
mdx · syntax-highlighting · performance · shiki
Polar solution docs
Merchant of record for developers. Polar sells to your customer, so tax is its job.
Merchant of record explained, what Polar takes on that Stripe leaves with you
With Stripe you are the seller and you owe VAT, GST and US sales tax yourself. Polar sells on your behalf and carries that liability. What actually changes, what it costs, and how little of it reaches your code.
polar · stripe · merchant-of-record · tax
Moving from Stripe to Polar without breaking existing customers
You cannot transfer live Stripe subscriptions to Polar. Sell new customers on Polar, keep Stripe's webhook alive for the ones you have, move them at renewal, and let the provider-neutral billing rows carry access through the whole overlap.
polar · stripe · migration · subscriptions
One-time and subscription products on Polar, from lifetime deal to renewal
Polar sells one price per product, so a plan sold monthly, yearly and for life is three products. How each kind checks out, which webhook proves it was paid, where it is stored, and how access resolves when a customer holds both.
polar · one-time-payments · lifetime-deal · subscriptions
Refunds and disputes on Polar, and taking access back exactly once
A refund arrives as order.refunded with the whole order. A dispute arrives as nothing at all. How this repo revokes a lifetime deal in both cases, why partial refunds keep access, and why a late paid delivery cannot give it back.
polar · refunds · disputes · chargebacks
Polar sandbox to production, the checklist that stops launch-day silence
Sandbox and production are separate Polar deployments with separate tokens, product ids and webhook secrets. Nothing carries over. Everything that has to be recreated, in order, and how to prove it worked.
polar · sandbox · production · launch
Polar webhooks arrive twice and sign two ways, make the handler survive both
At-least-once delivery means duplicates and out-of-order events are normal traffic, and Polar changed its signing key format in September 2026. Verify with both keys, claim the webhook-id before any write, re-read subscriptions and let orders only move forward.
polar · webhooks · idempotency · standard-webhooks
AI bundle solution docs
Streaming chat, Zod-checked output and tool calling on the Vercel AI SDK.
Prompt injection through user content: why delimiters are not the fix
Any text a user can influence can carry instructions. Wrapping helps a little; least-privilege tools, human confirmation and never trusting output as authorisation are what actually hold.
ai · security · prompt-injection · tools
Streaming edge cases: aborts, disconnects, backpressure and errors after the first token
A streamed response that fails halfway does not reject anything, and a user who closes the tab keeps billing you. The four cases every streaming route has to handle.
ai · streaming · abort · backpressure
Tool retries and partial failures: what the AI SDK retries and what it does not
The SDK retries the request to the model, never your tool's side effects. A tool that half-succeeded and then got called again is where duplicate charges come from.
ai · tools · retries · idempotency
When to add usage metering to an AI feature, and how to do it in an afternoon
A public AI route is a public spend endpoint. The three signals that say you need metering now, and the smallest implementation that actually protects you.
ai · cost · metering · rate-limiting
When AI work has to move to a background job, and what breaks if you wait
Serverless functions have a hard timeout that no amount of streaming avoids. The four signals that mean the work no longer belongs in the request, and the smallest queue that fixes it.
ai · background-jobs · queues · timeouts
When LLM tracing pays for itself, and the free version to build first
A user reports an answer you cannot reproduce. Without the exact prompt, the tool steps and the model version, you are guessing. But a paid tracing tool is not the first thing to reach for.
ai · observability · tracing · logging
Clerk solution docs
Hosted auth with prebuilt sign-in UI in your design's colours and a user sync webhook.
Clerk impersonation, the act claim, and what to lock while it is on
When an admin signs in as a user from the Clerk dashboard, the session token carries an act claim. Read it on the server, show a banner, and refuse account changes until it ends.
clerk · impersonation · admin · security
Protecting route handlers is not the same as protecting pages
A redirect is the right answer for a page and a terrible answer for fetch. Use 401 and 403 in route handlers, and never let the proxy be the only check.
clerk · nextjs · route-handlers · authorization
Clerk roles: publicMetadata or your own table?
publicMetadata is free and instant but vendor state you cannot join on. A local roles table joins and audits but must be kept in sync. Pick per what you need to query.
clerk · roles · authorization · publicmetadata
Make Clerk's sign-in look native, in light and dark, with CSS variables
Point Clerk's appearance variables at your design's CSS custom properties so the prebuilt components follow your theme and your dark mode, with no copied hex values.
clerk · nextjs · theming · dark-mode
Testing a Clerk webhook locally without a tunnel round trip
Sign the payload yourself and POST it at localhost. You get replays, retry ids and bad-signature cases in one second instead of thirty.
clerk · webhooks · svix · local-development
The proxy matcher that also matches your static assets
A matcher like "/(.*)" runs auth on every CSS file, image and font. The symptoms are an unstyled site, a redirect loop, or a surprising invocation bill.
clerk · nextjs · proxy · middleware
Clerk user-sync webhooks: duplicates, retries and out-of-order events
Svix retries and can deliver twice, and updates can arrive before creates. Make the write idempotent on the user id and reject stale payloads by timestamp.
clerk · webhooks · svix · idempotency
Supabase solution docs
Managed Postgres with row level security, realtime and a local stack in Docker.
Server code should stop using the anon key, and must not reach for the service role instead
The anon key is a public identifier, not a credential. Server work needs either the caller's JWT or a deliberate, audited service-role call. Here is how to tell which.
supabase · security · rls · service-role
Supabase gives you three connection strings: pick the right one or production falls over
Direct on 5432, session pooler on 5432, transaction pooler on 6543. Which one serverless needs, why prepared statements break, and what to run migrations on.
supabase · postgres · supavisor · pgbouncer
Stopping Supabase generated types from drifting out of the schema
Generated database types are only true at the moment they were generated. Commit them, regenerate them in the same commit as the migration, and check them in verify.
supabase · typescript · codegen · migrations
Local Supabase or a hosted branch - pick per environment, not per team
The CLI stack and Supabase branching solve different problems. Use local for the inner loop, a branch for preview deploys, and never share one dev project.
supabase · local-development · branching · preview-environments
Row level security when an ORM is doing the querying
Your ORM connects as the postgres superuser, so RLS never runs. Here is how to keep policies meaningful without giving up typed queries.
supabase · rls · postgres · orm
Sanity blog solution docs
A real editorial CMS your writers can use, with the schema still living in your repo.
Draft mode is on, and the page still shows published content
Draft mode only bypasses caches for reads that know about it. One direct client.fetch, or a token-less client, and the editor sees yesterday's copy.
sanity · draft-mode · caching · app-router
GROQ projections that stop your blog index fetching every article body
*[_type == "post"] returns whole documents, drafts of fields included. Project explicitly, dereference in the query, and slice every list.
sanity · groq · performance · queries
Sanity images without the 4MB original and the layout jump
asset->url hands the browser the raw upload. Build a transform URL with a width, and use the LQIP Sanity already generated as the blur placeholder.
sanity · images · performance · lqip
Modelling references in Sanity without an N+1 on every page
A reference is a pointer, not an embed. Dereference inside the projection, model the direction that reads well, and never resolve in a loop.
sanity · groq · references · data-modelling
Webhook revalidation or a revalidate timer: pick one
A 60-second timer rebuilds pages nobody asked for and still makes editors wait. Tag every read, invalidate on publish, and stop guessing.
sanity · caching · revalidate · webhooks
Cloudflare R2 solution docs
S3-compatible object storage with free egress. You pay for storage and requests.
Orphaned objects in R2: lifecycle rules and the sweep they cannot do
Direct-to-bucket uploads leak objects nobody references. Lifecycle rules clean up a tmp/ prefix and abandoned multipart parts; owner-scoped orphans need a reconciliation job.
r2 · storage · lifecycle · cleanup
The R2 upload that fails in the browser and works in curl: bucket CORS
A presigned PUT from a page is a cross-origin request. Without CORS rules on the bucket it fails with an error that never says CORS, and the signature gets blamed.
r2 · cors · uploads · presigned
Serving R2 objects publicly: custom domains, r2.dev and cache headers
r2.dev is rate-limited and not for production. A custom domain puts Cloudflare's cache in front of the bucket, but only if you wrote Cache-Control at upload time.
r2 · cloudflare · cdn · caching
Presigned PUT or multipart: picking an upload strategy for R2
A single presigned PUT is right up to about 100 MB and restarts from zero when it fails. Above that, multipart is not an optimisation, it is the only thing that works.
r2 · s3 · uploads · presigned
Zero egress fees, and the workloads where R2 actually beats S3
Egress is the line that surprises people on an S3 bill. R2 charges nothing for it and charges for operations instead: here is the arithmetic for deciding, including where R2 loses.
r2 · s3 · cloudflare · cost
Crisp solution docs
Live chat and a shared inbox from one script tag, kept off your critical path.
Consent gating a chat widget without breaking it
Chat sets cookies before anyone types a word, so hiding the launcher is not compliance. Gate the script tag itself, make withdrawal real, and know why a reload is the only honest teardown.
crisp · gdpr · consent · cookies
Keeping the chat bubble off the pages that need a clean hero
hide and show are visibility commands, not load control. Gate the script by route, hide on navigation, and give marketing pages a trigger you designed instead.
crisp · support · routing · conversion
Identifying signed-in users in chat without letting anyone impersonate them
An email set from the browser is a claim anyone can make. Sign it server-side with HMAC, pass the signature through, and give your support team a label they can act on.
crisp · support · security · hmac
Loading a chat widget without wrecking your Core Web Vitals
The vendor snippet is a synchronous script in the head. Move it to next/script with lazyOnload, measure the difference, and keep the click working while it downloads.
crisp · performance · lcp · inp
Routing support conversations with segments and session data
A shared inbox where everything looks the same is a queue, not a support system. Segments route, session data answers the first three questions, and both belong in code.
crisp · support · segments · routing
DataFast solution docs
Web analytics that tells you which channel made money, not just which one made visits.
Cookie consent for DataFast in Next.js without breaking attribution
DataFast sets a year-long first-party cookie, which needs opt-in consent in the EU and UK. Gate the script render, the goal queue and the checkout metadata on one flag.
datafast · consent · gdpr · cookies
DataFast shows nothing on localhost? That is on purpose. How to debug it anyway
The script skips localhost, 127.0.0.1, .local hosts, iframes and browsers flagged with datafast_ignore. Turn on data-allow-localhost for a session, check the network tab, then turn it off.
datafast · debugging · localhost · nextjs
DataFast goals versus page views, and when you need neither
Page views are free and automatic. Goals cost events and need a name, a reason and a side of the network. A decision table, the naming rule, and what never to put in a goal.
datafast · analytics · goals · pageviews
Proxy DataFast through your Next.js domain so ad blockers stop eating visits
Blockers match the datafa.st hostname. Serve the script and the events endpoint from your own origin with two route handlers, and forward the visitor's IP.
datafast · analytics · ad-blockers · reverse-proxy
DataFast shows revenue as direct traffic? Pass the visitor id into checkout metadata
DataFast attributes a payment by reading datafast_visitor_id from the checkout's metadata. Read the cookie on the server when you create the Stripe, Polar, Lemon Squeezy or Dodo checkout.
datafast · revenue-attribution · stripe · polar
Server-side DataFast goals from Next.js, and why the Goals API returns 404
Send goals from route handlers and server actions with POST /api/v1/goals, after the response. The visitor id comes from the request cookie, and it must already have a page view.
datafast · goals · server-side · api
Dodo Payments solution docs
Merchant of record in 220+ countries and regions. Sales tax is Dodo's job.
Selling software from outside the US, and why a merchant of record solves the payout problem
If your company is registered in India, Nigeria, Brazil or most of the world, the hard part is not accepting cards. It is getting paid, and staying compliant in a hundred countries you never visit.
dodo · merchant-of-record · payouts · india
One-time payments and subscriptions on Dodo Payments, side by side
Dodo decides one-time or recurring from the product, and payment.succeeded fires for both. Tell them apart by the payment's subscriptions, store purchases separately, and let a refund take access back.
dodo · one-time · lifetime · subscriptions
Refunds and chargebacks on Dodo, and what they should do to access
A refund or dispute webhook says which payment, not what was bought. Re-read the payment, derive the status from all its refunds and disputes, and never let a late event undo a refund.
dodo · refunds · disputes · chargebacks
Verifying Standard Webhooks signatures, the three headers and the two mistakes
Dodo signs id.timestamp.body with HMAC-SHA256. Verify the raw bytes, pass all three headers, and never write the comparison yourself.
dodo · webhooks · standard-webhooks · hmac
The Dodo subscription lifecycle, which event means what and who keeps access
active, past_due, on_hold, paused, cancelled, failed, expired. Map each to access on purpose, re-read the subscription on every event, and let a grace period decide how failed renewals feel.
dodo · subscriptions · webhooks · lifecycle
Dodo test mode and live mode are two separate worlds
Different API keys, webhook keys, product ids and customers. Nothing carries over, and the mismatch that hurts most is silent.
dodo · test-mode · live-mode · environments
Lemon Squeezy solution docs
Merchant of record with license keys built in. VAT and sales tax are its problem.
Idempotent Lemon Squeezy webhooks when there is no delivery id
Lemon Squeezy signs the raw body with X-Signature, sends no event id, and retries three times. Build your own idempotency key, verify in constant time, and know what to re-read.
lemonsqueezy · webhooks · idempotency · hmac
Lemon Squeezy license keys for desktop apps, CLIs and plugins
Turn on license keys per variant, activate and validate from the client with the public License API, and tie key expiry to the subscription. What to cache and what never to ship.
lemonsqueezy · license-keys · desktop · cli
What "merchant of record" means for your taxes on Lemon Squeezy
Lemon Squeezy sells to your customer and you sell to Lemon Squeezy. What that moves off your plate, what it does not, and how to show prices honestly.
lemonsqueezy · merchant-of-record · tax · vat
One-time purchases on Lemon Squeezy, from lifetime deal to refund
A lifetime deal is a single-payment variant, and order_created fires for subscriptions too. How to tell them apart, find the buyer, show the purchase, and take access back on a refund.
lemonsqueezy · one-time-payments · lifetime-deal · orders
Lemon Squeezy orders, invoices and partial refunds, and what each does to access
The first payment arrives as an order and an invoice, refunded_amount is a running total, and chargebacks send no event. How to record each once and revoke access on the right one.
lemonsqueezy · refunds · orders · invoices
Recovering from missed Lemon Squeezy webhooks
Three retries over about two and a half minutes, then the event is gone. A nightly reconcile from the API, what it can and cannot rebuild, and how to fix the rows it cannot.
lemonsqueezy · webhooks · reconcile · operations
The Lemon Squeezy subscription state machine, and who keeps access
on_trial, active, past_due, unpaid, paused, cancelled, expired. Which unlock your product, how to normalize them, and the two states people get wrong.
lemonsqueezy · subscriptions · lifecycle · dunning
Moving a Lemon Squeezy integration from test mode to live mode
Test and live are separate worlds with separate keys, webhooks and variant ids. The checklist, and the silent mismatch that sells nothing.
lemonsqueezy · test-mode · live-mode · launch
Mailgun solution docs
The veteran sending API. EU data residency and suppression lists kept server-side.
Mailgun returns 401 and your API key is fine: the EU/US region trap
A Mailgun domain lives in the region it was created in. Calling the wrong regional host returns 401 Unauthorized, which reads exactly like a bad API key.
mailgun · email · regions · eu
Mailgun says the message was queued and nobody receives it: sandbox domain limits
The sandbox domain accepts every send and delivers only to five addresses you authorised. Recognise it, use it deliberately, and know when to stop.
mailgun · email · sandbox · authorized-recipients
Suppression lists in Mailgun: stop maintaining your own bounce table
Mailgun stores bounces, complaints and unsubscribes per domain and refuses to send to them. Read that list instead of building a table you have to keep in sync.
mailgun · email · suppressions · bounces
Mailgun templates and recipient variables versus rendering HTML in your app
Mailgun stores Handlebars templates in its dashboard and substitutes variables at send time. Rendering in your app instead keeps email in code review: here is when each one wins.
mailgun · email · templates · handlebars
Open tracking, click tracking and why they are off by default
Mailgun's tracking adds a pixel and rewrites every link. Both are personal data under GDPR, both cost deliverability, and neither belongs on a magic link.
mailgun · email · tracking · privacy
Payload blog solution docs
A full CMS in your own repo and database. No second service, no content API bill.
Payload access control when your app already has auth
Two user tables is the right answer. Map your app's roles onto Payload's rules instead of merging the tables, and never leave an access block undeclared.
payload · access-control · auth · roles
Payload uploads vanish after a deploy: move media to an object store
staticDir writes to a filesystem that disappears on serverless. Add a storage adapter, keep the database rows, and migrate the files you already have.
payload · uploads · storage · s3
Payload migrations on Vercel without a broken deploy
Vercel runs your build, not your migrations. Run them in the build command, forward-only, and split the schema deploy from the code that needs it.
payload · vercel · migrations · deployment
Running Payload inside the same Next.js app
The admin panel is a route group, not a second service. Route groups, withPayload, the import map and why your blog pages must not fetch their own API.
payload · nextjs · app-router · cms
Letting Payload share your Postgres without wrecking your migrations
Two migration tools in one database will fight over table names and drop each other's tables. A separate schema keeps them apart for one config line.
payload · postgres · migrations · drizzle
Postmark solution docs
Transactional email with separate broadcast streams and 45 days of history.
Postmark bounce and spam complaint webhooks, secured without a signature
Postmark does not sign webhooks. Protect the endpoint with basic auth, act only on deactivating bounces, and make every write an upsert.
postmark · webhooks · bounces · spam-complaints
Postmark DKIM and custom Return-Path, and why DMARC fails without them
Postmark needs two DNS records per domain. DKIM signs the mail. The pm-bounces Return-Path CNAME makes SPF align. Skip one and DMARC alignment rests on the other.
postmark · dns · dkim · spf
Postmark error 406: you tried to send to a recipient that has been marked as inactive
A 406 means Postmark deactivated the address after a hard bounce, complaint or manual block. Do not retry it. Surface it, and reactivate only on the owner's request.
postmark · errors · suppression · bounces
Postmark message streams, transactional vs broadcast, and why the split protects your login emails
Postmark sends transactional and broadcast mail through separate streams with separate reputations and suppression lists. Route every send on purpose, and never put marketing on the transactional stream.
postmark · message-streams · broadcast · transactional
Postmark server-side templates vs React Email rendered in your app
Postmark can store templates and fill them with Mustachio. Rendering React Email in your app keeps templates in the repo, typed and reviewed. How to choose, and what each costs.
postmark · templates · react-email · mustachio
Testing Postmark without emailing anyone, POSTMARK_API_TEST vs sandbox servers vs bounce-testing
Postmark has three ways to send without reaching a real inbox. Each tests something different. Pick by what you need to prove.
postmark · testing · sandbox · ci
Prisma solution docs
Schema-first Postgres ORM with generated types, real migrations and a GUI.
Prisma types are wrong after a schema edit: generated client drift
The Prisma client is generated code. Edit the schema without regenerating and TypeScript describes the old database, locally, in CI-free builds and after a cached deploy.
prisma · codegen · typescript · vercel
Prisma in dev: "too many clients already" after a few saves
Next.js hot reload re-runs your module and builds a new PrismaClient every time. Cache one instance on globalThis and the connection leak stops.
prisma · nextjs · hot-reload · connections
Running Prisma migrations on Vercel without breaking production
Put prisma generate and prisma migrate deploy in the Vercel build command, never db push or migrate dev, and design migrations to survive a rolling deploy.
prisma · vercel · migrations · deployment
Fixing N+1 queries in Prisma with include, select and groupBy
A loop that queries per row turns one page load into hundreds of round trips. Fetch relations in the parent query, batch by id, and aggregate in the database.
prisma · performance · n-plus-one · sql
Prisma on serverless: why you need a pooler URL and a direct URL
Each serverless instance opens its own Postgres pool, so traffic exhausts connections. Route runtime queries through a pooler and keep a direct URL for migrations.
prisma · serverless · vercel · connection-pooling
Supabase Auth solution docs
Postgres-native auth where the database, not the API layer, is the last line of defence.
Logged out after an hour: Supabase cookie refresh in the App Router
Access tokens expire hourly and Server Components cannot write cookies, so the refresh has to happen in the proxy and be returned on the same response object.
supabase · nextjs · app-router · cookies
getSession() vs getUser(): the Supabase trust trap
getSession() decodes a cookie the browser controls; getUser() verifies it with the auth server. On the server, only one of them is a security check.
supabase · auth · security · sessions
Admin impersonation on Supabase Auth, bound to one session
Supabase Auth has no "view as user". Build it from a server-side magic link plus an app_metadata marker tied to the new session id, so only that session is flagged and nobody can forge it.
supabase · auth · admin · impersonation
Migrating an app that only ever used the anon key
Tables with RLS off are public. Turn it on table by table behind a feature switch, write the policies, and fix the queries the policies break, in that order.
supabase · rls · migration · security
Show only the OAuth buttons your Supabase project has switched on
Read the public /auth/v1/settings endpoint on the server, cache it, and fail closed, so a sign-in page never shows a Google button that ends on an error page.
supabase · auth · oauth · nextjs
RLS policy patterns for multi-tenant rows
Owner-scoped, org-scoped and role-scoped policies, the with-check clause people forget, and the indexes that stop a policy from turning every read into a scan.
supabase · rls · postgres · multi-tenancy
The blast radius of a leaked Supabase service-role key
The key bypasses every policy for every table. Here is how it leaks, what an attacker gets, how to contain it, and how to make the leak impossible.
supabase · security · service-role · secrets
Supabase Storage solution docs
Object storage in your Supabase project, with the same row level security as tables.
Cleaning up orphaned uploads before they become the bill
Every abandoned upload and every deleted row leaves an object nothing references. Here is where orphans come from, the sweeper that finds them, and the two-phase delete that stops making more.
supabase · storage · cleanup · cost
Serving images from Supabase Storage without shipping 4 MB avatars
On-the-fly transformation resizes at read time, but it is metered and it fights your cache. When to transform, when to resize on upload, and how signed URLs complicate both.
supabase · storage · images · performance
Public bucket or private bucket: decide once, per bucket, on purpose
A public bucket serves every object to anyone who guesses a key, forever. A private one costs you a signing step and a cache problem. Here is how to choose, and why mixing them in one bucket goes wrong.
supabase · storage · security · caching
Row level security on storage buckets, and why yours might not be running
Storage policies are SQL against storage.objects keyed on the path. Here is the policy set that works, the key layout it depends on, and why the service role key silently bypasses all of it.
supabase · storage · rls · postgres
Signed upload URLs versus proxying the file through your server
Proxying uploads through a route handler hits body limits, doubles the transfer and bills you for the wait. Sign a URL instead, and get the order of the checks right.
supabase · storage · uploads · serverless
Vercel Blob solution docs
File storage inside your Vercel project. One env var to wire, no second vendor.
Vercel Blob addRandomSuffix, allowOverwrite, and stale files in the cache
Blob refuses to overwrite by default, and an overwrite can take 60 seconds to show plus whatever the browser cached. Treat blobs as immutable; use new pathnames, not overwrites.
vercel-blob · caching · cdn · allowOverwrite
Vercel Blob: client uploads vs server uploads and the 4.5 MB limit
A Vercel Function accepts at most 4.5 MB of request body. Server uploads hit it; client uploads skip it. How client uploads work, and when a server upload is still right.
vercel-blob · uploads · vercel-functions · body-limit
Deleting orphaned blobs in Vercel Blob
Blobs nobody references still bill every month. Where orphans come from, how to delete them in the same code path as the row, and a safe sweep with list() and del() for the rest.
vercel-blob · cleanup · orphans · del
Vercel Blob handleUpload: never trust the pathname from the client
With client uploads the browser names the pathname and the token is bound to it. Check it in onBeforeGenerateToken, or any signed-in user can write anywhere in your store.
vercel-blob · security · handleUpload · onBeforeGenerateToken
Why Vercel Blob onUploadCompleted never fires on localhost
onUploadCompleted is a webhook from Vercel to your app. It cannot reach localhost, so the SDK skips it. Use a tunnel and VERCEL_BLOB_CALLBACK_URL, and never make the upload depend on it.
vercel-blob · handleUpload · onUploadCompleted · webhooks
Private vs public Vercel Blob stores: picking one you cannot change
A Blob store's access mode is fixed at creation. Private needs a credential for every read; public is readable by anyone with the URL. How to serve each, and why user files belong in private.
vercel-blob · private-storage · public-storage · signed-urls
What Vercel Blob actually costs, and where egress hides
Storage is cheap. Advanced operations and data transfer are the lines that grow. How each is counted, why private delivery can cost more, and the habits that keep the bill flat.
vercel-blob · pricing · egress · data-transfer
Next.js on Vercel solution docs
Next.js 16 on Vercel. A landing page, a token-driven UI kit, local checks, no CI.
Protecting a signed-in app in the App Router, in three layers
A layout that checks the session is not enough, because layouts do not re-render on client navigation. Where the proxy, the layout and the page each check, and why.
nextjs · auth · app-router · layouts
The Compound Engineering loop, and where /ce-plan and /ce-work actually fit
Agents that start typing immediately produce work nobody can review. Plan in a file, execute against it, then write down what you learned so the next pass is shorter.
workflow · planning · compound-engineering · agents
Environment variables on Vercel, without leaking them into the browser
Next.js inlines env reads at build time, so one import can ship a server key to every visitor. Here is the boundary that prevents it and the checks that prove it held.
vercel · nextjs · environment-variables · secrets
What each guard hook blocks, and how to extend one without breaking your session
Claude Code hooks stop the mistakes that cost the most. Here is what each one refuses, how the exit codes work, and the safe way to add a rule of your own.
claude-code · hooks · safety · security
llms.txt for a SaaS site, generated from the same copy as the page
An llms.txt file tells AI agents what your product is and where the important pages are. Build it from the landing page's data so it never goes stale, and serve it as a static file.
llms-txt · seo · ai-agents · nextjs
Selling one-time purchases next to subscriptions without two billing systems
Model a lifetime deal as a one-time price that grants a plan, record it in a purchases table with a monotonic status, and resolve access from subscriptions and purchases in one rule.
billing · one-time-payments · subscriptions · lifetime-deal
A pricing page that renders with no database and no payment keys
Keep the plan catalogue in code, map provider price ids through env vars, and make /pricing a static page whose buttons are plain links to a checkout route.
pricing · nextjs · billing · static-rendering
A privacy policy that lists the vendors you actually use
GDPR and the US state privacy laws expect you to say who processes personal data for you. Let each integration add itself to the list, so the policy changes when the code does.
privacy · gdpr · ccpa · legal
Rate limit checkout in Postgres, before the provider sees it
One small table and one atomic upsert keep a looping user from spending your payment provider's API limit, across every serverless instance, with no Redis.
billing · checkout · rate-limiting · postgres
Refunds and disputes should take access away, exactly once
Which webhook carries a refund or a dispute on each payment provider, how to find the purchase it belongs to, and how to revoke access without a late event giving it back.
billing · refunds · chargebacks · webhooks
Regenerating from agentic.config.json to see what upstream changed
There is no sync service and no template remote. Regenerate a clean copy from your recorded selection, diff it against your repo, and take only the agent layer.
generator · upgrades · diffing · agentic-config
Rules, skills and agents, which one you actually need
The same instruction behaves completely differently depending on where you put it. Rules are ambient constraints, skills are invoked procedures, agents are delegated scopes.
agents · skills · rules · claude-code
Sample testimonials that never reach production
A landing page template needs quotes, logos and numbers to look finished, and publishing invented ones is illegal. Mark them as samples, show them in development, and drop them from the production build.
landing-page · testimonials · ftc · compliance
A collapsible sidebar that remembers its state without a flash
Saving the sidebar's open or collapsed state in localStorage makes every page load jump. A cookie the server reads renders the right width in the first HTML.
nextjs · ui · cookies · hydration
Writing a path-scoped rule that agents actually follow
Rules fail for two reasons: they load when nobody needs them, or they are unfalsifiable. Scope by path, write checkable statements, and give every rule an escape hatch.
rules · agents · conventions · claude-code
Atelier solution docs
Bone serif on carbon, a ridge line across the hero and one blue point at its summit.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Aura solution docs
Bone paper, ink pills lettered in mono capitals, and a soft violet to amber aura where it counts.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Blockhaus solution docs
Cream paper, black ink, wide geometric headlines. Every section is a ruled block and every action a pill.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Blueprint solution docs
Black drafting table, dashed frames, mono labels and one periwinkle pen. Every section reads like a drawing.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Broadcast solution docs
Sage drafting paper, wide squared headlines, tall orange capsules and dark product screens.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Clay solution docs
Cream canvas, saturated clay tiles, chunky rounded headlines and soft pill buttons. Warm, not grey.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Cobalt solution docs
White canvas, black type and one electric blue. Mono labels, hairline bar maps and no shadows.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Daylight solution docs
Hairlines, not shadows. Black buttons, one electric blue, and small tags with a pop of pastel.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Default solution docs
shadcn done carefully. Neutral greys, near-black actions, one blue for links, Geist throughout.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Dossier solution docs
Pure grey, ruled with hairlines and split down one rail. Square panels, tracked caps labels, one bright cyan.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Forge solution docs
Warm near-black, one loud orange slab, dashed rules pinned with square ticks, and pills for every control.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Glow solution docs
A violet night lit from below: an ultraviolet horizon, glass pill buttons and silver headlines.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Grove solution docs
Parchment, forest ink and emerald buttons lettered in mint, with a pastel card for every feature.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Ivory solution docs
White panels float on warm ivory: a capsule header, black pill buttons and coral kept to small marks.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Kite solution docs
A pastel dawn over lavender paper: violet ink serifs, pill buttons and a few sketched stars.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Ledger solution docs
Every edge is a hairline, every corner is square, every headline is a serif. Colour only means status.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Marker solution docs
Warm paper, light black type and one highlighter yellow that marks what matters.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Meadow solution docs
Big serif headlines on sunlit cream, black pill buttons, and sage leaves growing around your product.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Midnight solution docs
Pure black, white grotesque type, 1px hairlines, and one magenta cloud behind the product.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Newsprint solution docs
A quality broadsheet on cream paper. Serif everywhere, black rules, square corners, one yellow button.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Paper solution docs
Serif headlines on white paper, a grainy peach haze, black pill buttons and product sheets that float.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Peach solution docs
Heavy black headlines on peach paper, black buttons, one ember accent and hard block shadows.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Plum solution docs
Cream paper, plum ink, one pale lavender button. Ruled in warm hairlines, labelled in mono caps.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Pulse solution docs
Cream type on a midnight console, an ember and mint pill pair, and a six hue waveform under the hero.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Quill solution docs
A light blue serif, mono keycaps and a drafting frame on warm graph paper. Reads like a technical manual.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Signal solution docs
Warm black bands, bold white Inter and one lime button, with a caret blinking after the headline.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Slab solution docs
Warm paper, black ink and a light slab serif. Hairlines instead of shadows, rust only as text.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Sticker solution docs
Buttercream pages cut by five sunset stripes, with monumental wide caps and pixel labels on pill buttons.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Terminal solution docs
Serif headlines, mono labels and hairline rules on near-black, with one acid lime for the thing that acts.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Voltage solution docs
Pitch black and flat, with violet gradient panels, white pill buttons and a hot magenta spark.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css
Workshop solution docs
Whisper headlines on warm parchment, ink and linen pill buttons, ember links and a painted stage.
A chart palette that survives dark mode
Six brand colours picked on white turn muddy or fluorescent on near-black. Define the series palette as tokens with two values each, assign them in order, and never let colour be the only encoding.
charts · dataviz · design-tokens · dark-mode
A dark mode toggle that works on a machine already set to dark
prefers-color-scheme and a .dark class fight over specificity and order. One extra :not() makes an explicit choice win in both directions, and one inline script kills the flash.
dark-mode · css · accessibility · nextjs
Pasting a shadcn component into a repo that renamed the tokens
shadcn components are written against variable names, not values. Publish those names alongside your own and a paste works unmodified: except for the ones you already claimed.
shadcn · tailwind · design-tokens · theming
Tailwind v4: your dark mode does nothing
Adding a .dark block that overrides your colour variables changes nothing if the utilities were generated with @theme instead of @theme inline. Here is the difference and the fix.
tailwind · tailwind-v4 · dark-mode · css