1. Introduction
Most landing pages follow the same structure.
Hero. Features. Social proof. Pricing. FAQ. Call to action.
Yet many developers still rebuild these sections from scratch for every new project. It wastes time and often leads to inconsistent design.
In this guide, we will build a complete SaaS landing page using:
- Next.js with the App Router
- Tailwind CSS
- shadcn UI + Base UI
- Free open source blocks from the Shadcn Space registry
The goal is simple.
Use production-ready blocks as a foundation, then customize them directly inside your own codebase.
You will see:
- How to install free registry blocks
- How the block structure works
- Real block code examples
- How to modify layout, content, and styles
- How to turn static blocks into reusable components
By the end, you will have a fully functional SaaS landing page and a clear understanding of how to extend it for real products.
2. What are we building?
In this tutorial, we are building a SaaS landing page for a fictional product called BuildStack.
BuildStack is a web-based visual builder for frontend developers. It allows teams to compose UI blocks, edit the underlying React and Tailwind code, preview changes instantly, and share live links for feedback.
The product combines visual editing with full code control. It is not a no code tool. It is built for developers who want speed without losing ownership of their code.
Core Value Proposition
Build visually. Control the code. Ship faster.
Sections we will implement
Using free open source Shadcn Space registry blocks, we will build the following landing page sections:
- Hero section with primary call to action
- Features grid explaining the builder capabilities
- Code preview focused section
- Testimonials
- Pricing section
- FAQ section
- Final call to action
- Footer
Final Page Structure
Our landing page composition will look like this:
<Hero />
<Features />
<Portfolio />
<Testimonials />
<Pricing />
<FAQ />
<CTA />
<Footer />Each section will be installed from the Shadcn Space registry and then customized directly in our project so you understand exactly how everything works.
3. Project setup with Base UI using the Shadcn preset
Since Shadcn Space blocks are built using Base UI primitives, we will create our project using the Base UI preset instead of the default Radix setup.
This ensures our landing page uses the same foundation as the blocks we are going to install.
3.1 Create the project with Base UI
Run the following command:
npx shadcn@latest create --preset "https://ui.shadcn.com/init?base=base&style=vega&baseColor=neutral&theme=neutral&iconLibrary=lucide&font=inter&menuAccent=subtle&menuColor=default&radius=default&template=next" --template nextThis command:
- Creates a Next.js project
- Configures Tailwind CSS
- Sets up Base UI as the component foundation
- Uses Vega style preset
- Configures Lucide icons
- Uses Inter font
- Applies neutral theme tokens
You now have a Base UI powered Next.js project ready for Shadcn Space blocks.
3.2 Add the Shadcn Space Registry
Open your components.json and add the following registry configuration:
{
"registries": {
"@shadcn-space": {
"url": "https://shadcnspace.com/r/{name}.json",
"params": {
"email": "${EMAIL}",
"license_key": "${LICENSE_KEY}"
}
}
}
}Note: Replace ${EMAIL} and ${LICENSE_KEY} with your registered Shadcn Space credentials.
This tells the CLI where to fetch components and blocks from Shadcn Space.
For more information about how to use it in your project
4. Two ways to build the Landing Page
Now that the project is set up with Base UI, there are two practical ways to build the landing page using Shadcn blocks:
- Using the CLI directly
- Using the MCP server inside your editor
Both approaches install real source code into your project. The difference is how you select and generate blocks.
Option 1: Build using the CLI
This approach gives you full manual control.
Step 1: Browse Blocks
Visit the block registry and browse free blocks.
Look for sections that match the landing page structure we defined for BuildStack:
Choose blocks that match the visual direction you want.
Step 2: Install Selected Blocks
Once you find a block you like, install it using the CLI:
npx shadcn@latest add @shadcn-space/{block-name}Each command:
- Downloads the block
- Places it inside components/shadcn-space/blocks
- Installs required dependencies
Now your folder might look like:
components/
shadcn-space/
blocks/
hero-01/
features-01/
pricing-01/
testimonial-01/
faq-01/
cta-01/
footer-01/Step 3: Compose the Landing Page
Open app/page.tsx and compose the sections:
import AgencyHeroSection from "@/components/shadcn-space/blocks/hero-01/index";
import Pricing from "@/components/shadcn-space/blocks/pricing-01/pricing";
import Portfolio from "@/components/shadcn-space/blocks/portfolio-01/portfolio";
import Feature01 from "@/components/shadcn-space/blocks/feature-01/index"
import Testimonials from "@/components/shadcn-space/blocks/testimonial-01/testimonial";
import Faq from "@/components/shadcn-space/blocks/faq-01/faq"
import CTA from "@/components/shadcn-space/blocks/cta-01/cta";
import Footer from "@/components/shadcn-space/blocks/footer-01/footer";
export default function Page() {
return (
<main>
<AgencyHeroSection/>
<Feature01 />
<Portfolio />
<Testimonials />
<Pricing />
<Faq />
<CTA />
<Footer />
</main>
)
}That is it.
You now have a complete landing page composed of production-ready sections.
You can now adjust content, layout, spacing, and styling directly inside each block file.
Note: I have used all 1st block of the respective section. You can use it as per your need by visiting Shadcn Space.
Adding a free hero block
Now that our Base UI powered project is ready, we will add a Hero section to start building the landing page.
We will use a free open-source block and bring it directly into our codebase.
4.1 Add the Hero Block
Run the CLI command to add the Hero block:
npx shadcn@latest add @shadcn-space/hero-01The CLI will:
- Download the block source code
- Add it to your components directory
- Install any required dependencies
After installation, you should see:
components/
shadcn-space/
blocks/
hero-01/
index.tsx4.2 Inspecting the block code
Open components/shadcn-space/blocks/hero-01/index.tsx.
You will see something similar to this:
import HeroSection from "@/components/shadcn-space/blocks/hero-01/hero";
import type { NavigationSection } from "@/components/shadcn-space/blocks/hero-01/header";
import Header from "@/components/shadcn-space/blocks/hero-01/header";
import BrandSlider, { BrandList } from "@/components/shadcn-space/blocks/hero-01/brand-slider";
import type { AvatarList } from "@/components/shadcn-space/blocks/hero-01/hero";
export default function AgencyHeroSection() {
const avatarList: AvatarList[] = [...];
const navigationData: NavigationSection[] = [...];
const brandList: BrandList[] = [...];
return (
<div className="relative">
<Header navigationData={navigationData} />
<main>
<HeroSection avatarList={avatarList} />
<BrandSlider brandList={brandList} />
</main>
</div>
);
}Why this matters
This is not a black box component. It is a normal React component that lives directly inside your project. You can open it, read it, edit it, and understand exactly how it works. Nothing is hidden behind compiled abstractions or external styling systems.
It uses Base UI primitives for behavior and accessibility, which means the logic is reliable and standards-compliant. At the same time, styling is handled with Tailwind classes, giving you full control over design without fighting a rigid structure.
The JSX is fully editable. You can rearrange elements, change markup, extract subcomponents, or integrate your own logic. It behaves just like any other component in your codebase.
There is no lock-in. You are free to modify the structure, adjust the layout, replace logic, or restyle everything according to your needs. The component adapts to your system rather than forcing you to adapt to it.
4.3 Render the Hero Section
Now import it inside the app/page.tsx:
import AgencyHeroSection from "@/components/shadcn-space/blocks/hero-01";
export default function page() {
return (
<AgencyHeroSection/>
)
}At this point, the first section of our landing page is added.
Option 2: Build using the MCP server
If you prefer a faster and more automated workflow, you can use the MCP server.
This works inside supported editors such as:
- Antigravity
- VS Code
- Other MCP-compatible editors
Step 1: Install the MCP server
Follow the MCP server documentation and install it using the provided commands for your editor.
Example:
npx shadcn@latest add @shadcn-space/{block-name}After installation, restart your editor.
Step 2: Open chat inside your editor
Once MCP is active, open the chat panel inside your editor.
Now describe what you want to build.
For our example:
Create a SaaS landing page for BuildStack.
It is a visual web builder for developers.
Use shadcn blocks.
Include hero, features, preview section, testimonials, pricing, faq and final CTA.
Use a modern and minimal style.Step 3: Let MCP select and install blocks
Once you describe the landing page you want to build, the MCP server analyzes your prompt and selects appropriate shadcn blocks that match your requirements. It can choose a suitable hero layout, feature section, pricing structure, testimonials, and supporting sections based on your product description. After selecting the blocks, they are installed directly into your project and wired up to create a basic page composition, allowing you to see a working landing page immediately.
All installed sections are added as real source code inside your project. Nothing is hidden or abstracted. You can open any block file, modify the layout, adjust spacing, change typography, rewrite messaging, reorder sections, or restyle components using Tailwind classes. The MCP workflow simply accelerates the initial setup. You still maintain full control over the implementation.
Which method should you use?
Using the CLI
The CLI approach is ideal if you prefer precise control over your layout and want to manually choose each block that goes into your landing page. You can browse available sections, evaluate their structure, and install them one by one based on your design goals. This method gives you full visibility into what is being added and how the page is composed from the start. It is especially useful when you already have a clear layout in mind.
Using the MCP Server
The MCP workflow is better suited for rapid prototyping. Instead of manually selecting each block, you describe the landing page you want to build and let the system choose appropriate sections for you. It installs the blocks and wires them into a working page structure automatically. This gives you a strong starting point in seconds while still allowing you to refine content, adjust layout, reorder sections, and tweak styling afterward.
Both approaches result in real React components being added to your project. The difference is only in how you initialize the page, not in the level of control you retain.
5. Refining the Landing Page for Consistency
Once your sections are installed, the page works. But it might not feel cohesive yet.
Different blocks can have slightly different spacing, heading scales, container widths, or button styles. Even if each block looks good individually, the overall page needs alignment.
Start by checking:
- Vertical spacing between sections
- Consistent container width
- Heading hierarchy
- Button variants
- Background alternation
Unify Section Spacing
If blocks use different padding values, normalize them. For example, standardize around:
<section className="py-24">or
<section className="py-24">Keeping spacing consistent makes the page feel intentional.
Standardize Container Width
Make sure all sections use the same container pattern:
<div className="container mx-auto max-w-6xl px-4">If one block uses max-w-3xl and another uses max-w-7xl, the layout can feel unstable.
Align Typography Scale
Check heading sizes across blocks:
- Hero might use text-5xl
- Features might use text-3xl
- Testimonials might use text-2xl
Ensure hierarchy makes sense:
- One primary H1
- Section titles as H2
- Card titles as H3
Make the Theme Consistent
Since we initialized the project with Base UI and neutral theme tokens, you can adjust colors globally using Tailwind config or CSS variables.
For example, updating primary color tokens once will reflect across all buttons and accents.
That is the benefit of using a unified foundation.
6. Making the Landing Page Production Ready
At this point, your landing page is built and structured. Now it is time to prepare it for real users.
A production-ready landing page is not only about design. It must be optimized, accessible, and technically sound.
Configure Metadata Properly
Open app/layout.tsx and define meaningful metadata for SEO and social sharing.
export const metadata = {
title: "BuildStack | Visual Web Builder for Developers",
description:
"Build visually, review in real time, and control your React and Tailwind code with BuildStack.",
}This ensures your page displays correctly in search results and link previews.
Optimize Images
If your blocks include screenshots or product previews, use the Next.js Image component instead of standard img tags.
Example:
import Image from "next/image"
<Image
src="/preview.png"
alt="BuildStack editor preview"
width={1200}
height={800}
/>This improves loading performance and prevents layout shifts.
Minimize Client Components
Keep sections as server components unless interactivity is required.
Avoid adding “use client” at the top of block files unless necessary. This keeps the page lighter and improves performance.
Verify Responsiveness
Test your landing page on:
- Mobile devices
- Tablets
- Desktop screens
Even if blocks are responsive by default, spacing and layout can shift when combined.
Adjust Tailwind breakpoints if needed.
Ensure Accessibility
Ensure accessibility before shipping. Maintain a proper heading hierarchy so content flows logically for screen readers. Use clear, descriptive button labels and meaningful alt text for images. Verify sufficient color contrast for readability. Accessibility is not optional; it is a core part of production-ready quality.
Clean up unused code
If you experimented with multiple blocks, remove the unused ones.
Keep your components/shadcn-space/blocks directory clean and organized. This improves long-term maintainability.
When these checks are complete, your landing page is no longer a prototype. It is ready for deployment and real traffic.
Final Thoughts
Building a landing page with Shadcn does not require starting from scratch or relying on rigid templates.
With a Base UI powered setup, you can install blocks using the CLI or generate a structured starting point using the MCP server. In both cases, you receive real React components inside your project. You can inspect them, modify them, refactor them, and scale them as your product evolves.
This approach gives you speed without sacrificing control.
If you prefer an even faster starting point, you can use shadcn templates. These templates provide a fully structured landing page layout that you can customize for your product. They are especially useful when you want a complete foundation with consistent spacing, typography, and section hierarchy already in place.
Whether you choose individual blocks or shadcn templates, the core advantage remains the same. You own the code.
That ownership is what makes this workflow practical for real products and long-term development.
Build intentionally. Refine carefully. Ship confidently.
