Yesterday on Day 58, I built a Task Manager app with Next.js, MongoDB, and Server Actions. The app worked, but it looked rough. Today was all about making it actually nice to use.
What I Used
- Tailwind CSS — for layout and spacing utilities
- Shadcn UI — for pre-built, accessible components I can own and customize
Setting Up Shadcn
npx shadcn@latest init
npx shadcn@latest add button card badge input textarea select label
This drops the component source directly into your project under /components/ui. No black-box library — you own the code.
What I Styled
Layout — A clean navbar with a centered max-w-4xl main container across all pages.
Task List — A responsive 2-column grid on larger screens, with a friendly empty state when no tasks exist yet.
Task Cards — Each task is wrapped in a Card with the title, a colored status badge, description, timestamps, and Edit/Delete actions.
Task Form — Proper Label + Input/Textarea/Select combinations with placeholders, and a dynamic submit button that says "Create Task" or "Update Task" depending on the context.
A Gotcha with Shadcn Badge
Shadcn's
Badgeonly ships with 4 variants:default,secondary,destructive,outline. There's no built-insuccessorwarning.
Instead of extending the component, I used a simple helper with Tailwind classes directly:
const statusStyles = (status) => {
if (status === "completed") return "bg-green-100 text-green-700 hover:bg-green-100";
if (status === "in-progress") return "bg-yellow-100 text-yellow-700 hover:bg-yellow-100";
return "bg-gray-100 text-gray-600 hover:bg-gray-100";
};
<Badge className={statusStyles(task.status)}>{task.status}</Badge>
Clean enough, and no need to touch the component internals.
Using Button with asChild
Shadcn's Button has an asChild prop that lets you pass a Link inside it and get all the button styles applied to the anchor — no wrapper divs needed:
<Button asChild variant="outline" size="sm">
<Link href={`/tasks/${task._id}`}>Edit</Link>
</Button>
This is one of those small things that makes Shadcn feel really well thought out.
Key Takeaway
Shadcn isn't a traditional component library. You install only what you need, and the code lives in your project. That means full control — no fighting with overrides or !important hacks.
Tomorrow, for Day 60, I'll be deploying the app on Vercel.
Top comments (0)