How to Build a Free MVP Web App Fast: A Step-by-Step Guide

Till Hoffmann
7 min readJun 16, 2024

--

Photo by Markus Spiske on Unsplash

Building a Minimum Viable Product (MVP) can be approached in various ways, from using platforms like Webflow or using low-code tools such as Zapier, n8n, and Retool. These methods are great for quickly getting a prototype off the ground. However, in this guide, we’ll focus on real development to provide a more robust and scalable solution.

Speed and efficiency are crucial in MVP development. By making use of modern AI powered tools MVP development does not need to be a multiple months long process. Let’s dive into how you can achieve this with Next.js, Tailwind CSS, and Firebase/Supabase, while keeping your costs to 0$.

1. Setting Up Your Project

To kickstart your MVP development, we choose Nextjs 14 (or later). You probably already heared about NestJs, if not it provides a modern way to develop fullstack applications. It offers us a React frontend and a nodejs like backend in one hand. So there is no complicated setup for things like cors etc.. Follow these steps to set up your project:

  1. Install Next.js, TypeScript, and Tailwind:
npx create-next-app@latest my-mvp-app --typescript --tailwind --eslint
cd my-mvp-app

2. Run the Development Server:

npm run dev

3. Explore the Project Structure:
-
Understand the default file and folder setup.
- Familiarize yourself with the key configuration files (next.config.js, tsconfig.json).

2. Styling with Tailwind CSS and shadcn

To efficiently style your MVP, use Tailwind CSS and ShadCN. Tailwind CSS provides a utility-first approach to styling, allowing you to rapidly build modern designs. ShadCN further simplifies component styling with pre-built components.

  1. Setup shadcn:
 npx shadcn-ui@latest init

2. Follow the setup:
The process will ask you some question. You can leave the defaults or use some custom values. After that you can optionally setup some custom fond, we will skip it here to keep it simple (full guide here)

3. The /ui folder:
In the /ui folder you will find the installed components by shadcn. Here is an example how you can install an component:

npx shadcn-ui@latest add button

3. Connecting to a Backend

Choosing the right backend for your MVP is crucial for a smooth development process. Firebase and Supabase are both excellent options, each with its own strengths. To decide which platform to use, consider the following questions:

Key Questions to Help You Choose:

  1. What kind of database do you prefer?
  • Firebase: Uses a NoSQL database (Firestore) that’s great for hierarchical data and real-time updates.
  • Supabase: Uses PostgreSQL, a powerful SQL database that offers relational data management and more advanced querying capabilities.

2. How important is real-time functionality?

  • Firebase: Known for its real-time database features, making it ideal for applications that require instant data updates (e.g., chat applications).
  • Supabase: While it also supports real-time subscriptions, its real-time capabilities are built on top of PostgreSQL, which may be preferable for traditional relational data needs.

3. What ecosystem and additional services do you need?

  • Firebase: Provides a comprehensive suite of tools including cloud functions, machine learning, and analytics, making it a one-stop-shop for many developers.
  • Supabase: Focuses on providing an open-source alternative to Firebase with strong SQL support, and integrates well with existing PostgreSQL tools and libraries.

If you choose supabase you will find a great setup tutorial here:

If you choose firebase you can follow this guide:

4. Accelerating Development with Vercel’s v0.com

To accelerate your MVP development, leverage Vercel’s v0.com for component generation. This tool allows you to quickly create components using simple prompts, saving you time and effort. v0.com is a tool by Vercel that generates Next.js components based on your specifications. It uses prompts to create ready-to-use components in Next.js, Tailwind CSS, and ShadCN.

  1. Generating Components Using Prompts:
    - Visit v0.com: Go to v0.com and log in with your Vercel account.
    - Create a New Component: Enter a prompt describing the component you need. For example, “Create a responsive profile page with avatar, personal data, and settings”
    - Review the Generated Code: v0.com will generate three components based on your prompt. Review each and choose the best one. Optionally you can modify the code directly in the browser.
  2. Integrating Generated Components into Your Project:
    - Copy the NPX Command: v0.com provides an NPX command to integrate the generated component into your project.
    - Run the NPX Command: Open your terminal and run the command in your project directory:
    npx v0-cli@latest integrate <component-name> — path ./components
    - Verify Integration: Ensure the component files are added to the specified directory and import them into your pages or other components as needed.
  3. Customizing Colors Using VSCode’s Replace Feature:
    - Find and Replace Colors: Use the find and replace feature in VSCode to customize hardcoded colors in the generated components.
    - Press `Ctrl+Shift+H` (Windows/Linux) or `Cmd+Shift+H` (Mac) to open the Replace in Files panel.
    - Enter the color value to be replaced and the new color value. Something like “bg-background” or “text-primary”.
    - Click “Replace All” to update the colors throughout your component files.

5. Focusing on Core Features

When building an MVP, it’s crucial to focus on the core feature that sets your application apart. By identifying and developing the most important feature first, you can ensure that your product delivers real value to users from the start.

  • Break Down the Feature: Divide the main feature into smaller, manageable tasks. This makes development more manageable and progress easier to track. For example, if your core feature is a real-time chat, break it down into tasks like user authentication, message sending, message receiving, and UI design.
  • Set Milestones: Establish clear milestones to measure your progress. This helps keep development on track and ensures timely completion.
    - Milestone 1: User authentication
    - Milestone 2: Sending messages
    - Milestone 3: Receiving messages
    - Milestone 4: UI/UX design
  • Leverage Existing Tools and Libraries: Save time by using pre-built tools and libraries instead of building everything from scratch.

6. Optimizing API Requests with Tanstack Query

Optimizing API requests is crucial for enhancing the performance and user experience of your MVP. Tanstack Query is a powerful tool that simplifies data fetching, caching, and synchronization in React applications.

  1. Installing Tanstack Query: npm i @tanstack/react-query
  2. Steps to Install and Configure Tanstack Query:
    Create a QueryClient instance and wrap your application with the QueryClientProvider.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
// Create a client
const queryClient = new QueryClient()

function App() {
return (
// Provide the client to your App
<QueryClientProvider client={queryClient}>
<Todos />
</QueryClientProvider>
)
}

How I use tanstack query

I usually try to abstract as much as possible. Thats why I use a hooks pattern. First I put all the server request logic in a service. That can look like this for supabase: services/content.ts

export const getAllContent = async (): Promise<Content[]> => {
const { data: content, error: contentError } = await supabase
.from('content')
.select('*');

if (contentError) {
throw contentError;
}

return content;

After that I wrap this service in a tanstack query hook: hooks/useContent.ts

export const useGetAllContent = () => useQuery({
queryKey: ['content'],
queryFn: () => getAllContent(),
});

Finally we can simply use that hook in our component: components/content-table.tsx

export default function ContentTable() {
const { data: contents, isLoading, error } = useGetAllContent();

return (
<section>
{isLoading && <div className="text-muted">Loading...</div>}
{error && <div className="text-destructive">Error: {error}</div>}
{!isLoading && !error && <DataTable content={contents} />}
</section>
)
}

Benefits of Using Tanstack Query

  • Caching: Automatically caches the fetched data, reducing the number of requests.
  • State Management: Manages the loading, error, and success states out of the box.
  • Error Handling: Provides a standardized way to handle errors in your API requests.
  • Refetching: Supports automatic and manual refetching of data, keeping the UI up-to-date.

7. Deployment and Hosting

Deploying your MVP efficiently is crucial for getting it into the hands of users. Vercel offers seamless deployment for Next.js applications, while Firebase and Supabase provide robust backend hosting options.

Step-by-Step Guide to Deploying Your Next.js Application on Vercel:

  1. Create a Vercel Account: Sign up at vercel.com.
  2. Link Your Git Repository: Connect your GitHub account to Vercel.
  3. Deploy Your Project: Select your Next.js project repository and configure the deployment settings.
  4. Set Environment Variables: Add any necessary environment variables in the Vercel dashboard.
  5. Deploy: Click “Deploy” and wait for Vercel to build and deploy your application. Your app will be available at a Vercel-provided URL.

8. Monitoring and Improving User Experience

Monitoring user behavior and improving user experience is essential for the success of your MVP. Posthog offers powerful analytics and features to track user interactions and optimize your application.

  1. Installing and Configuring Posthog: Posthog is an open-source product analytics platform that allows you to track user actions, analyze trends, and improve user experience. Create an account on Posthog and set up your project.
  2. Setting Up Posthog and Tracking Custom Events: Follow the installation instructions provided by Posthog , you can find them here: https://posthog.com/docs/libraries/next-js
  3. Track Custom Events: Use client-side library to track specific actions users take in your application, such as button clicks, form submissions, or page views. You can capture your custom events in every component with the following code: posthog.capture(‘button_clicked’, { button_name: ‘Sign Up’ });
  4. Posthog’s Features:
    - Session Recordings: Capture and replay user sessions to understand how users interact with your application.
    - Feature Flags: Implement feature flags to roll out new features gradually and gather feedback from users in real-time.

Conclusion

In this guide, we’ve explored a streamlined approach to building Minimum Viable Products (MVPs) efficiently and for free. Starting with setting up a Next.js project with TypeScript and styling it using Tailwind CSS and ShadCN, we emphasized the importance of choosing the right backend between Firebase and Supabase. We accelerated development with Vercel’s v0.com for component generation and optimized API requests using Tanstack Query. Deployment strategies with Vercel and backend hosting options with Firebase or Supabase were also discussed to ensure scalability and performance. Finally, we highlighted the significance of monitoring user experience with Posthog for analytics and continuous improvement.

Connect with me on LinkedIn: https://www.linkedin.com/in/tillhoffmann/

Visit my website: https://www.till-hoffmann.me/

--

--

Till Hoffmann

Founder and Freelancer in software and product development.