· 3 min read
Building Interactive Pricing Pages with Next.js
Pricing pages are deceptively complex. They look simple on the surface, but the logic underneath involves dynamic plan selection, real-time cost calculation, feature comparison tables, and responsive layouts that work across dozens of plan configurations. I built the pricing system for a SaaS product website using Next.js, and here’s what I learned.
The Challenge
The product had multiple pricing tiers across several product lines. Each product had its own plan structure, feature comparison table, and volume-based pricing. Some plans were annual, some monthly. Some had usage calculators with range sliders. The pricing data came from a CMS.
The goal was a single, composable pricing system that could handle any product’s pricing page without duplicating code.
Dynamic Components
I built a set of dynamic components that render based on CMS data: plan cards, comparison tables, volume discount sections, FAQ accordions, and banners. Each section is a modular block that the CMS can reorder, show, or hide per product.
The range slider was the most interesting piece. Users drag a slider to select their expected usage (messages per month, video minutes, API calls), and the page recalculates pricing in real-time. The slider needed custom styling, keyboard accessibility, and smooth transitions between values.
I built the RangeSlider as a standalone component with a progress track that fills as you drag. The tricky part was making it work across all browsers. The native <input type="range"> renders differently everywhere, so I styled it with CSS custom properties and pseudo-elements.
Plan Selection Logic
Each product has a different plan structure. Some have legacy plans that need special handling. Others have usage-based options that change the price calculation. The plan button logic needs to know the current plan, the selected plan, whether it’s an upgrade or downgrade, and whether the user is authenticated.
I extracted this into a set of utility functions that each product page imports. The UI component stays simple: it calls getPlanButtonLabel() and getPlanButtonAction() and renders accordingly. The business logic is testable and separate from the presentation.
Feature Comparison Tables
The comparison tables needed to be responsive on mobile without horizontal scrolling. I used a grid layout that collapses to a stacked format on small screens. Each feature row shows the plan name inline so you don’t lose context when the table headers scroll out of view.
Tooltips on feature names explain what each feature means. I kept these as CSS-only tooltips instead of a JavaScript library to avoid adding bundle weight to a marketing page where performance matters.
What I Learned
Pricing pages are marketing pages that behave like applications. They need the interactivity of a dashboard (calculators, dynamic rendering, state management) but the performance expectations of a landing page (fast load, good SEO, minimal JavaScript).
The key insight was treating the CMS as the source of truth for page structure while keeping the interactive logic in React components. The CMS controls what appears and in what order. The code controls how it behaves.