Plan Recommender
A free pricing plan recommender React component with a guided, transparent chooser for Next.js.
Plan finder
Find the plan that fits how you work
Answer 3 quick questions. Every answer is a visible vote, so the recommendation is easy to understand.
Question 1 of 3
- How many people will use the workspace?: 1
- How often does your team ship meaningful work?: 2
- What level of support would help most?: 3
Customise
Code
<PricingPlanRecommender questions={questions} plans={plans} />Plan Recommender is a free pricing section for Next.js and React, styled with Tailwind and animated with Motion. It asks one native-radio question at a time, counts each answer as a visible vote and recommends the plan with the most matches, using plan order to resolve a tie.
Back, Next, Review answers and Restart preserve a predictable form workflow, while every result explains the recommendation and keeps every alternative plan and CTA available. Question travel, the shared progress indicator and selected-answer lift use bounded transforms only; reduced motion swaps panels instantly without changing the content, focus order or recommendation logic.
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/pricing-plan-recommenderUsage
"use client";
import { PricingPlanRecommender } from "@/components/pricing-plan-recommender";
const questions = [
{
id: "team-size",
prompt: "How many people need access?",
options: [
{ label: "Just me", planId: "starter" },
{ label: "Two to ten", planId: "growth" },
{ label: "More than ten", planId: "scale" },
],
},
{
id: "support",
prompt: "What support do you need?",
options: [
{ label: "Self-serve guides", planId: "starter" },
{ label: "Priority support", planId: "growth" },
{ label: "Dedicated support", planId: "scale" },
],
},
];
const plans = [
{
id: "starter",
name: "Starter",
price: "Free",
description: "For individuals validating a workflow.",
href: "/signup?plan=starter",
},
{
id: "growth",
name: "Growth",
price: "$29 / month",
description: "For teams shipping every week.",
href: "/signup?plan=growth",
},
{
id: "scale",
name: "Scale",
price: "$89 / month",
description: "For larger teams that need dedicated help.",
href: "/contact",
},
];
export default function PricingPage() {
return (
<PricingPlanRecommender
questions={questions}
plans={plans}
onRecommendation={(planId) => {
console.log("Recommended plan:", planId);
}}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| questions | ReadonlyArray<{ id: string; prompt: string; options: ReadonlyArray<{ label: string; planId: string }> }> | required | Two to four questions. Each option votes for a plan id and option order is preserved. |
| plans | ReadonlyArray<{ id: string; name: string; price: string; description: string; href: string }> | required | Two to four plans with unique ids, visible pricing, descriptions and meaningful CTA destinations. |
| layout | "stacked" | "split" | "split" | Wide-screen chooser and result composition. Both modes stack on narrow screens. |
| stepOffset | number | 18 | Question travel in CSS pixels, clamped to the range 0 to 40. |
| indicatorStiffness | number | 320 | Shared progress-indicator spring stiffness, clamped to 120 to 520. |
| answerLift | number | 3 | Selected-answer hover and focus lift in CSS pixels, clamped to 0 to 8. |
| radius | number | 28 | Chooser and result panel radius in CSS pixels, clamped to 0 to 48. |
| onRecommendation | (planId: string) => void | undefined | Called when the deterministic recommendation changes. |
| className | string | undefined | Additional classes merged onto the section. |
Customisation
Plan Recommender exposes three Tier 3 CSS variables. The accent token colours the active indicator and recommended plan, the panel token controls both surfaces and the track token controls inactive progress. Layout and motion geometry stay available through props:
<div
style={{
"--plan-recommender-accent": "var(--ring)",
"--plan-recommender-panel": "var(--card, var(--surface))",
"--plan-recommender-track": "var(--border)",
}}
>
<PricingPlanRecommender
questions={questions}
plans={plans}
layout="stacked"
stepOffset={12}
indicatorStiffness={380}
answerLift={5}
radius={20}
/>
</div>Frequently asked questions
- Is Plan Recommender free for commercial use?
- Yes. Plan Recommender is MIT licensed, so you can use it in personal and commercial projects without attribution.
- Is the pricing plan recommender accessible and performant?
- Yes. It uses one real form with fieldsets, legends, native radios and buttons, predictable focus movement and a polite result announcement. Motion is limited to transform and opacity, content keeps natural height, and reduced motion replaces travel and springs with instant state changes.
- How does Plan Recommender choose a plan?
- Each selected option votes for the plan id supplied in your question data. The plan with the most votes wins, and the original plan order resolves equal totals, so the result is deterministic and there are no hidden scoring rules. Use the geometry props and three CSS variables to customise presentation without changing that logic.