Claude Code Boilerplate
FeaturesPricingBlogDocs
Get started →

Product

  • Features
  • Pricing
  • Skills

Compare

  • vs ShipFast
  • vs MakerKit
  • vs supastarter

Resources

  • Docs
  • Blog
  • Discord

Legal

  • License
  • Privacy Policy
  • Terms of Service
Claude Code Boilerplate

© 2026 Claude Code Boilerplate. All rights reserved.

← All posts

How to Add an NPS Survey to Your Next.js SaaS -- Track Customer Satisfaction Without Delighted or Survicate

August 15, 2026
nextjssaasdrizzle-ormresendanalytics

You have paying customers. You are not sure if they are happy. You have two options: pay $50-200 a month for a tool like Delighted or Survicate, or build it yourself in a few hours using the database and email infrastructure you already have.

NPS -- Net Promoter Score -- is a single question: "On a scale of 0-10, how likely are you to recommend this to a friend or colleague?" It is the most widely-used satisfaction metric in SaaS because it predicts churn and word-of-mouth growth better than almost anything else you can measure.

This post shows you how to add NPS to a Next.js SaaS boilerplate -- with a Drizzle ORM table, a timing rule that avoids annoying users, and a Resend alert when a score drops.

What the Score Actually Means

Responders fall into three groups:

  • Detractors (0-6): unhappy users who are likely to churn or warn others away
  • Passives (7-8): satisfied but not enthusiastic
  • Promoters (9-10): loyal customers who recommend you unprompted

Your NPS = % promoters minus % detractors. Above 30 is good for B2B SaaS. Above 50 is strong.

The number matters less than the comment. A score of 5 with "I can never find the export button" tells you exactly what to fix. A batch of anonymous 9s just confirms you are not actively broken.

The Three Things You Need to Build

  1. A database table to store responses
  2. A rule for when to show the survey (not too early, not too often)
  3. An alert when someone submits a low score

The boilerplate already has Drizzle ORM and Neon DB for the table, JWT auth so you know exactly which user is responding, Resend for the alert email, and the Shadcn Dialog component for the modal. You are wiring them together, not building from scratch.

The Schema

Add this to your modules folder:

export const npsResponseTable = pgTable(nps_responses, {
  id: uuid(id).defaultRandom().primaryKey(),
  userId: uuid(user_id).notNull().references(() => userTable.id),
  score: integer(score).notNull(), // 0-10
  comment: text(comment),
  createdAt: timestamp(created_at).defaultNow().notNull(),
});

Run npm run db:generate and npm run db:migrate. That is the entire data layer.

When to Show the Survey

Do not show NPS on day one. Users have not had time to form an opinion. A common rule: show it after 14 days, then again no sooner than 90 days after the last response.

Your service layer can enforce this with two checks before returning the survey flag:

function shouldShowNps(user: User, lastResponse: Date | null): boolean {
  const msPerDay = 86_400_000;
  const daysSinceSignup = (Date.now() - user.createdAt.getTime()) / msPerDay;
  if (daysSinceSignup < 14) return false;
  if (!lastResponse) return true;
  const daysSinceLast = (Date.now() - lastResponse.getTime()) / msPerDay;
  return daysSinceLast > 90;
}

Call this in the server component that renders your dashboard. If it returns true, pass a prop down to the client component that mounts the modal.

The Modal

Use the Shadcn Dialog component. Render 11 buttons labeled 0 through 10. Below the buttons, add an optional textarea for a comment and a submit button.

Keep it short. Every extra field drops your response rate. The goal is one question with an optional comment -- nothing else.

On submit, call your API route which writes the score to nps_responses and, if the score is 6 or below, fires a Resend alert to your support inbox.

Low-Score Alerts

This is where the real value lives. When a paying customer gives you a 4, you have a window -- maybe 30-60 days -- to fix the problem before they cancel.

A Resend email that fires on score <= 6 should include:

  • The user email and plan
  • The score
  • The comment verbatim

Your support team can reply personally within an hour. That one conversation is worth more than a month of broadcast emails. For a broader look at using email to fight churn, see How to Reduce SaaS Churn.

When to Use a Third-Party Tool Instead

Delighted, Survicate, and AskNicely give you beautiful trend dashboards, response segmentation, and NPS benchmarks against your industry. If you want all of that on day one and are willing to pay, use them.

Build it yourself when:

  • You want the scores stored next to the rest of your user data for easy cross-referencing
  • You want to trigger follow-ups from the same Resend setup you already use for transactional email
  • You do not want to pay $100 a month before you have 100 paying customers
  • You want to join NPS data to your own analytics events to see whether low scorers use certain features less

The core is one table, one function that decides when to show the survey, and one modal. You can add a score-over-time chart to your metrics dashboard later -- the data will already be there.

Get Started

If you are building a SaaS and want auth, payments, email, and Drizzle ORM already wired up, get the Next.js SaaS Boilerplate and add your NPS survey in an afternoon instead of a week. Your first detractor alert email might be the most valuable thing you send all month.