Key Concepts
- Full-Stack Development: Building both the front-end (user interface) and back-end (server-side logic and database) of an application.
- Trello Clone: Replicating the functionality and design of the Trello project management tool.
- Next.js: A React framework for building server-rendered and statically generated web applications.
- TypeScript: A superset of JavaScript that adds static typing.
- Tailwind CSS: A utility-first CSS framework.
- Superbase: An open-source Firebase alternative providing database, authentication, and real-time functionalities.
- React DND (Drag and Drop): A library for implementing drag-and-drop interfaces in React.
- Shadcn UI: A collection of pre-designed, customizable React components.
- Radix UI: A set of unstyled, accessible React primitives.
- Clerk: A platform for user authentication and billing.
- Stripe: A payment processing platform.
- CRUD Operations: Create, Read, Update, and Delete operations on data.
- RLS (Row Level Security): A Superbase feature to control data access at the row level.
- OAUTH: An open standard for access delegation, commonly used for authentication.
- JWT (JSON Web Token): A standard for securely transmitting information as a JSON object.
Project Setup and Initial Configuration
- Creating a Next.js App: The tutorial begins by creating a new Next.js project using the
npx create-next-appcommand. TypeScript, ESLint, Tailwind CSS, the App Router, and Turbopack are selected during project setup. - Installing Dependencies: A comprehensive list of packages is installed using
npm install, including:superbase-js: For database interactions.react-dnd,dnd-kit-core,dnd-kit-sortable,@dnd-kit/utilities: For drag-and-drop functionality.@radix-ui/react-dialog,@radix-ui/react-label,@radix-ui/react-select,@radix-ui/react-slot: Radix UI components.lucide-react: For icons.class-variance-authority: For compatibility with Radix UI.tailwind-merge,clsx: For managing Tailwind CSS class names.@clerk/nextjs: For authentication and billing.tailwindcss-animate: For Tailwind CSS animations.
- Shadcn UI Setup: Shadcn UI is initialized using
npx shadcn-ui@latest init. The neutral color is chosen as the base color. Components likeButton,Card,Input,Label,Textarea,Dialog,Select, andBadgeare added usingnpx shadcn-ui@latest add. - Environment Variables: Clerk API keys (public publishable key and secret key) and Superbase credentials (URL and anonymous key) are stored in a
.envfile.
Navbar Component
- Creating the Navbar: A
Navbarcomponent is created as a client component (navbar.tsx). - Basic Structure: The navbar includes a logo (Trello icon from Lucid React), the website name ("Trello clone"), and links for sign-in and sign-up.
- Styling: Tailwind CSS classes are used to style the navbar, including borders, background opacity, backdrop blur, sticky positioning, and responsive padding.
- Conditional Rendering: The navbar content changes based on user authentication status. If the user is signed in, it displays a welcome message with the user's name and a link to the dashboard. If not, it shows sign-in and sign-up buttons.
- Clerk Integration: The
useUserhook from Clerk is used to determine the user's authentication status and retrieve user information.
Authentication with Clerk
- Clerk Setup: A new application is created in Clerk, named "Trello clone app." Email/password and GitHub sign-up methods are enabled.
- Middleware Configuration: A
middleware.tsfile is created to handle authentication middleware usingClerkMiddlewarefrom@clerk/nextjs/server. - Clerk Provider: The
ClerkProvidercomponent is used to wrap the entire application in the root layout (app/layout.tsx), providing access to Clerk's functionalities throughout the project. - OAUTH API Keys: The tutorial mentions that while Clerk uses shared pre-configured credentials for development, production deployments require obtaining your own API keys for OAUTH providers like Google or GitHub.
Superbase Database Setup
- Superbase Project Creation: A new project is created in Superbase, including setting a database password and choosing a region.
- Table Creation: Three tables are created in Superbase:
- Boards: Stores information about each board (ID, title, description, color, user ID, created at, updated at).
- Columns: Stores information about columns within a board (ID, board ID, title, sort order, created at). A foreign key relationship is established with the
Boardstable, with cascading delete behavior. - Tasks: Stores information about tasks within a column (ID, column ID, title, description, assignee, due date, priority, sort order, created at). A foreign key relationship is established with the
Columnstable, with cascading delete behavior.
- Data Types: Specific data types are chosen for each column, such as
text,date,int4, andtimestamp. - RLS Policies: Row Level Security (RLS) policies are created for each table to restrict data access based on user authentication. Policies are defined for
SELECT,INSERT,UPDATE, andDELETEoperations. Therequesting_user_id()function is used to securely identify the authenticated user. - Clerk Superbase Integration: The tutorial explains how to integrate Clerk with Superbase by enabling the Superbase integration in Clerk and adding the Clerk domain to Superbase's third-party OAUTH providers. It also details the necessary changes to the Superbase client creation and RLS policies to work with Clerk's authentication.
Superbase Client and Services
- Superbase Models: TypeScript interfaces are created to represent the structure of the database tables (Board, Column, Task) in
lib/superbase/superbase-models.ts. - Superbase Client Setup: Two files are created for Superbase client initialization:
lib/superbase/client.ts: For client-side components, usingcreateBrowserClientfrom@superbase/superbase-js.lib/superbase/server.ts: For server-side components, usingcreateServerClientfrom@superbase/superbase-jsand thecookiesfunction fromnext/headers.
- Board Service: A
BoardServiceobject is created inlib/services.tsto encapsulate CRUD operations for theBoardstable. It includes functions for:getBoards(userId: string): Retrieves all boards for a specific user.createBoard(board: Omit<Board, 'id' | 'created_at' | 'updated_at'>): Creates a new board.getBoard(boardId: string): Retrieves a specific board by ID.updateBoard(boardId: string, updates: Partial<Board>): Updates an existing board.
- Column Service: A
ColumnServiceobject is created inlib/services.tsto encapsulate CRUD operations for theColumnstable. It includes functions for:createColumn(column: Omit<Column, 'id' | 'created_at'>): Creates a new column.getColumns(boardId: string): Retrieves all columns for a specific board.
- Task Service: A
TaskServiceobject is created inlib/services.tsto encapsulate CRUD operations for theTaskstable. It includes functions for:createTask(task: Omit<Task, 'id' | 'created_at'>): Creates a new task.getTasksByBoard(boardId: string): Retrieves all tasks for a specific board.moveTask(taskId: string, newColumnId: string, newOrder: number): Moves a task to a different column.
- Board Data Service: A
BoardDataServiceobject is created inlib/services.tsto handle operations that involve multiple services. It includes a function for:createBoardWithDefaultColumns(boardData: { title: string; description?: string | null; color?: string | null; }, userId: string): Creates a new board with default columns (To Do, In Progress, Review, Done).
Dashboard Page Implementation
- Dashboard Page Structure: The
DashboardPagecomponent (app/dashboard/page.tsx) is created as a client component. It includes a welcome section, statistics about the boards, and a section to display the boards. - Use Boards Hook: A
useBoardshook is created inlib/hooks/use-boards.tsto manage the list of boards, loading state, errors, and functions to alter the boards. It uses theuseStatehook to manage the state and theuseEffecthook to load the boards when the component mounts. - Use Board Hook: A
useBoardhook is created inlib/hooks/use-boards.tsto manage a single board. - Board Display: The boards are displayed in a grid or list format, depending on the selected view mode. Each board is rendered as a link to the individual board page.
- Create Board Functionality: A button is added to allow users to create new boards. The
handleCreateBoardfunction is called when the button is clicked, which calls thecreateBoardWithDefaultColumnsfunction from theBoardDataService. - Loading and Error Handling: The component displays a loading indicator while the boards are being fetched and an error message if there is an error.
Board Page Implementation
- Board Page Structure: The
BoardPagecomponent (app/boards/[id]/page.tsx) is created as a client component. It includes the navbar and a section to display the board columns. - Use Params Hook: The
useParamshook fromnext/navigationis used to get the board ID from the URL. - Column Display: The columns are displayed using a
DroppableColumncomponent, which is a wrapper component that handles the drag-and-drop functionality. - Task Display: The tasks within each column are displayed using a
SortableTaskcomponent, which is a wrapper component that handles the drag-and-drop functionality. - Drag and Drop Implementation: The
DndContextcomponent fromdnd-kit-coreis used to wrap the entire board content, providing the necessary context for drag-and-drop operations. TheuseDroppableanduseSortablehooks fromdnd-kit-coreanddnd-kit-sortableare used to implement the drag-and-drop functionality for the columns and tasks. - Drag and Drop Functions: The
handleDragStart,handleDragOver, andhandleDragEndfunctions are created to handle the drag-and-drop events. These functions update the UI and the database to reflect the new order of the columns and tasks.
Billing and Payment with Clerk
- Clerk Billing Setup: Billing is enabled in the Clerk dashboard, and three plans are created: Free, Pro, and Enterprise.
- Plan Context: A
PlanContextis created inlib/contexts/plan-context.tsxto provide access to the user's plan information throughout the application. - Dashboard Layout: A
DashboardLayoutcomponent (app/dashboard/layout.tsx) is created as a server component to fetch the user's plan information using theClerkOAUTH functions and pass it to thePlanContext. - Conditional Rendering: The UI is updated based on the user's plan. For example, the "Create Board" button is disabled for free users who have already created one board.
- Upgrade Dialogue: A dialogue is displayed to free users who have reached their board limit, prompting them to upgrade to a paid plan.
- Pricing Page: A
PricingPagecomponent (app/pricing/page.tsx) is created to display the available plans using thePricingTablecomponent from@clerk/nextjs. - Subscription Management: Users can manage their subscription through their Clerk account settings.
Conclusion
The tutorial provides a detailed, step-by-step guide to building a full-stack Trello clone using Next.js, TypeScript, Tailwind CSS, Superbase, React DND, Shadcn UI, and Clerk. It covers a wide range of topics, including project setup, database design, authentication, drag-and-drop implementation, and billing. The tutorial emphasizes best practices, such as using TypeScript for type safety, creating reusable components, and encapsulating database logic in services. While the project is complex, the tutorial breaks it down into manageable steps and provides clear explanations of the code. The final result is a functional Trello clone with a professional-looking design and robust features.
AI summaries can miss context or contain errors. Check important details against the original video.





