Implementation guide for building an account registration screen with Tailwind CSS and shadcn (Next.js compatible)
Introduction
This is the concrete work for [Part 2] of the tutorial series where we build an authentication mechanism with Next.js.
In this article, we will explain how to implement an account registration screen using Next.js, Tailwind CSS, and shadcn. By combining these technologies, we will create a modern and user-friendly form design and learn implementation methods that are close to real-world applications. We will first build the design base using a card component, and then proceed step by step to add a login screen and social login buttons.
Through this tutorial, you will learn the basics of page construction in Next.js, using components with shadcn, and styling with Tailwind CSS.
Goal for this article
The goal of this article is to use Tailwind CSS and shadcn to build an account registration screen like the one below.
If you already know how to use Tailwind CSS and shadcn, you can skip that article without any problem.
Using the card component
We will use shadcn’s card component to build the overall structure of the account registration screen.
Install shadcn’s card component with the following command:
$ npx shadcn@latest add card
Once the installation is complete, a card.tsx file will be created under /components/ui.
// Partial excerpt
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }
At the very end, there are several components being exported.
Since the account registration screen and the login screen will have relatively similar designs, we will create a CardWrapper component under /components/auth that groups these components together, and then use that.
'use client'
import { Card, CardContent, CardFooter, CardHeader } from '@/components/ui/card'
interface CardWrapperProps {
children: React.ReactNode
headerLabel: string
buttonLabel?: string
buttonHref?: string
showSocial?: boolean
}
export const CardWrapper = ({
children,
buttonLabel,
buttonHref,
showSocial,
}: CardWrapperProps) => {
return (
<Card className="w-[400px] shadow-md">
<CardHeader></CardHeader>
<CardContent>{children}</CardContent>
{showSocial && <CardFooter></CardFooter>}
{buttonLabel && buttonHref && <CardFooter></CardFooter>}
</Card>
)
}
This component is designed to receive several props when used; their purposes are summarized below:
- children: Receives the input form
- headerLabel: Receives the string for the card title
- buttonLabel: Receives the label for the button placed in the card footer
- buttonHref: Sets the destination to navigate to when the button is clicked
- showSocial: Controls whether to display social icons
Creating the card header component
Now that the card frame is complete, we will create its contents.
First is the component corresponding to the header section.
Create header.tsx under /components/auth and use it.
interface HeaderProps {
label: string
}
export const Header = ({ label }: HeaderProps) => {
return (
<div className="flex w-full flex-col items-center justify-center gap-y-4">
<h1 className='text-2xl font-semibold'>Authentication Tutorial</h1>
<p className="text-sm text-muted-foreground">{label}</p>
</div>
)
}
Creating the button component for the footer
import Link from 'next/link'
import { Button } from '@/components/ui/button'
interface FooterButtonProps {
href: string
label: string
}
export const FooterButton = ({ href, label }: FooterButtonProps) => {
return (
<Button variant="link" className="w-full font-normal" size="sm" asChild>
<Link href={href}>{label}</Link>
</Button>
)
}
We have defined a button component again.
Using Next.js’s Link component, we enable navigation between pages.
For the design, we are using shadcn’s button component.
Creating the component that displays social icons
This is the last component used in CardWrapper.
In this authentication tutorial, we will first build a mechanism that allows login with email address and password. After that, we will also introduce how to log in with Google or GitHub accounts. The component will first become useful at that stage, but we will create it now.
First, to use icons, add the library with the following command:
$ npm i react-icons
react-icons is a library that aggregates many icons.
It is a convenient library that works in both Next.js server components and client components.
As of September 2024, it seems to provide about 48,000 icons.
Checking all 48,000 one by one would be tough, so use the search field on the homepage we just saw and type in google or github to find them. You can search for icons like this, and once you find one you want to use, it will show you how to write the import statement; you can copy and paste that to display the icon on the screen.
Find the Google and GitHub icons on this site, then create social.tsx under /components/auth and use the icons.
import { FaGithub } from 'react-icons/fa'
import { FcGoogle } from 'react-icons/fc'
import { Button } from '@/components/ui/button'
export const Social = () => {
return (
<div className="flex w-full items-center gap-x-2">
<Button size="lg" className="w-full" variant="outline">
<FcGoogle className="size-5" />
</Button>
<Button size="lg" className="w-full" variant="outline">
<FaGithub className="size-5" />
</Button>
</div>
)
}
Now we have all the components needed to build the account registration screen.
Let’s assemble them and check that they actually render.
Implementing the account registration screen
First, update CardWrapper:
'use client'
import { Card, CardContent, CardFooter, CardHeader } from '@/components/ui/card'
+import { FooterButton } from './footer-button'
+import { Header } from './header'
+import { Social } from './social'
interface CardWrapperProps {
children: React.ReactNode
headerLabel: string
buttonLabel?: string
buttonHref?: string
showSocial?: boolean
}
export const CardWrapper = ({
children,
+ headerLabel,
buttonLabel,
buttonHref,
showSocial,
}: CardWrapperProps) => {
return (
<Card className="w-[400px] shadow-md">
- <CardHeader></CardHeader>
+ <CardHeader>
+ <Header label={headerLabel} />
+ </CardHeader>
<CardContent>{children}</CardContent>
- {showSocial && <CardFooter></CardFooter>}
+ {showSocial && (
+ <CardFooter>
+ <Social />
+ </CardFooter>
)}
- {buttonLabel && buttonHref && <CardFooter></CardFooter>}
+ {buttonLabel && buttonHref && (
+ <CardFooter>
+ <FooterButton label={buttonLabel} href={buttonHref} />
+ </CardFooter>
)}
</Card>
)
}
Basically, we are placing the FooterButton, Header, and Social components we just created in the appropriate places.
Next, create a component dedicated to account registration.
Create a register-form.tsx file under /components/auth, and use the CardWrapper we created above to build the component.
import { CardWrapper } from './card-wrapper'
export const RegisterForm = () => {
return (
<CardWrapper
headerLabel="Fill in each field to create an account"
buttonLabel="If you already have an account, click here"
buttonHref="/auth/login"
showSocial
>
Input form
</CardWrapper>
)
}
We will build the actual input form here—where users can enter their email address, password, etc.—in the next article, so for now we will just put some text in.
On the registration screen, we provide a separate button that allows users who have already registered an account to navigate to the login screen.
Next, we will use the RegisterForm above and actually display it on the screen.
Update page.tsx under /app/auth/register.
+import { RegisterForm } from '@/components/auth/register-form'
const RegisterPage = () => {
- return <div>Account Registration Screen</div>
+ return <RegisterForm />
}
export default RegisterPage
We have replaced the text-only "Account Registration Screen" with RegisterForm.
Finally, we will adjust the layout of the screen.
Create layout.tsx under /app/auth and refine the design.
const AuthLayout = ({ children }: { children: React.ReactNode }) => {
return (
<div className="flex h-full items-center justify-center bg-gradient-to-br from-sky-100 to-blue-300">
{children}
</div>
)
}
export default AuthLayout
Start Next.js, and if you navigate from the top page to the account registration screen and see a screen like the one below, you are all set.
You should see the text "If you already have an account, click here". Please also check that clicking this takes you to the login screen.
Conclusion
In this article, we created several components using Tailwind CSS and shadcn, and then combined them to the point where they actually render.
I hope this gives you a sense that, because shadcn provides commonly used components, you can create decent-looking components with relatively little work.
Next time, we will build the input form on this screen and implement validation functionality to check the input values.
Here is the next article
Questions about this article 📝
If you have any questions or feedback about the content, please feel free to contact us.Go to inquiry form
Related Articles
Chat App (with Image/PDF Sending and Video Call Features)
2024/07/15Practical Component Design Guide with React × Tailwind CSS × Emotion: The Optimal Approach to Design Systems, State Management, and Reusability
2024/11/22Building and Operating a Design System Using Chakra UI, ShadCN, and Material UI
2024/03/12Management Dashboard Features (Graph Display, Data Import)
2024/06/02Tutorial for Implementing Authentication with Next.js and Auth.js
2024/09/13Thorough Comparison of the Best ORMs for the Next.js App Router: How to Choose Between Prisma / Drizzle / Kysely / TypeORM [Part 1]
2025/03/13Test Strategy in the Next.js App Router Era: Development Confidence Backed by Jest, RTL, and Playwright
2025/04/22Done in 10 minutes. Easy deployment procedure for a Next.js app using the official AWS Amplify template
2024/11/05

