Every freelance web developer knows this pain: A client asks for a "simple" scheduling page. Suddenly, you're deep in the trenches fighting with JavaScript Date objects, timezone conversions, and installing massive, bloated UI libraries just to render a basic calendar grid.
I used to rely on heavy third-party packages for this, but customizing them to fit a modern, minimal design (like a Link-in-Bio page) always felt like wrestling a bear.
Recently, I decided to build a custom 3-step booking flow strictly using Next.js and Tailwind CSS. Here is the architectural approach that finally worked for me without the bloat.
The Multi-Step State Architecture
Instead of dumping everything into one massive component, you need to isolate the state of your booking flow. I typically break it down into three distinct steps:Date Selection: The calendar grid.
Time Selection: Available slots based on the chosen date.
User Details: Name, email, and confirmation.
By keeping the state at a parent level, you can easily slide between these components:
`import { useState } from 'react';
export default function BookingFlow() {
const [step, setStep] = useState(1);
const [bookingData, setBookingData] = useState({
date: null,
time: null,
details: {}
});
const nextStep = () => setStep((prev) => prev + 1);
return (
{step === 1 && { setBookingData({...bookingData, date}); nextStep(); }} />}
{step === 2 && { setBookingData({...bookingData, time}); nextStep(); }} />}
{step === 3 && completeBooking(details)} />}
);
}`
- Ditching heavy UI libraries for Tailwind Grid
You don't need a 2MB library to draw a calendar. CSS Grid + Tailwind makes this incredibly simple. A basic 7-column grid for the days of the week is all you need:
`
{/* Day Headers */}
{['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'].map(day => (
{day}
))}
{/* Date Cells */}
`
{daysInMonth.map(day => (
key={day}
className="p-2 rounded-lg hover:bg-black hover:text-white transition-colors"
>
{day}
))}
The Result: LinkSync
I got so tired of rewriting this exact logic for different freelance clients that I finally packaged it into a clean, reusable boilerplate called LinkSync.Itβs a minimal Link-in-Bio profile that expands seamlessly into this exact fast, responsive booking flow.
π You can play with the live demo here: https://linksync-demo.vercel.app/demo
If you want to save yourself ~10 hours of setup time on your next client project, I'm currently selling the full source code. As a thank you to the dev community, I'm giving a 50% discount to the first 3 buyers:
π https://nospaa.gumroad.com/l/fdoaub/FIRST3How do you usually handle complex date selections in your React apps? Let me know in the comments!
Top comments (0)