DEV Community

Cover image for Build Collaborative Vercel-like Toolbar with Lovable, Windsurf, and Velt
Arindam Majumder
Arindam Majumder Subscriber

Posted on

Build Collaborative Vercel-like Toolbar with Lovable, Windsurf, and Velt

On many websites and web apps, it helps when users can leave quick comments or feedback directly on the page. Instead of switching between tools or sending screenshots, it’s easier when everything happens right in the interface, like Figma’s commenting. In this blog, we’ll show how to build a feature like that using Lovable, Windsurf, and Velt.

To make this process faster and smoother, a new AI-powered approach is becoming popular: "Vibe Coding." You might have seen developers on X building whole applications in just a few hours using AI. That's vibe coding in action. It's about using AI to do the heavy lifting in development, like writing code and solving complex problems, so you can build things much faster.

Vibe Coding is not one time code-generation. It's a workflow where you team up with an AI to build and improve your project step-by-step. This way of working makes it possible to create powerful applications with less effort.

In this guide, we’ll walk through a complete vibe coding process to build a modern landing page that includes real-time collaboration features-highlighted by a custom toolbar similar to the Vercel Toolbar.

Image0

We'll start by generating a modern landing page from a simple prompt using Lovable. Then, we'll take the generated code into Windsurf, an AI-powered IDE, to write more complex code and add our collaborative features. Specifically, we'll use Velt to integrate live cursors, pin commenting features that will transform our website into a collaborative workspace.

Key Features We'll Add:

  • Beautiful Landing Page UI: A stylish landing page designed by Lovable AI.
  • Live Cursors and Presence: See who else is looking at the landing page in real-time.
  • Figma-Style Pin Comments: Add comments and feedback directly on any part of the landing page, similar to Figma where comments attach to elements as well.
  • Vercel-Style Toolbar: We're creating a Vercel-style toolbar which will let us access all our collaborative tools right from one place.

By the end of this tutorial, you'll see how easy it is to combine these tools to build collaborative projects with beautiful interfaces in very short amount of time.

What is the Vercel Toolbar?

The Vercel Toolbar shows up on your site when you deploy it with Vercel, mainly for preview links. It helps you and your team review the site before it goes live. You can:

  • Quickly share links to your preview site.
  • Leave comments and feedback directly on the page.
  • Switch between different versions (branches) of your site.
  • Check for common issues like layout shifts or accessibility problems.

This toolbar makes it much simpler to collaborate and take actions on the deployed projects on Vercel.

Here's how the Vercel toolbar looks on a page:

Image1

We'll use a similar toolbar in our app to let users control the collaborative nature of our landing page, for example, adding comments, switching users, and more.

Understanding why it's becoming difficult to ship without using tools and SDKs

Today, users expect rich features like real-time updates, smooth interactions, and seamless experiences. It’s no longer just about writing some HTML and CSS and calling it done.

Also, many apps are used by teams who need to work together, like adding comments, making changes together, or reviewing updates live. But without the right tools, people end up taking screenshots and chatting in separate apps, which is slow and disconnected from the actual product.

The Real Problems You Face

Problem 1: Everything Takes Forever Want to add user authentication? That's weeks of work just to handle login, signup, password reset, and security. Want real-time features? You need to learn WebSockets, set up servers, handle connection drops, and manage state across users.

Problem 2: You Become a Jack of All Trades, Master of None Instead of focusing on your main product, you're now:

  • A security expert (handling user data)
  • A performance engineer (making things fast)
  • A mobile developer (responsive design)
  • A backend developer (APIs and databases)
  • A DevOps engineer (deployment and scaling)

Problem 3: Maintenance Never Ends Every piece of code you write from scratch becomes your responsibility forever. When browsers update, when security issues pop up, when users report bugs - it's all on you.

This is why modern developers increasingly rely on specialized tools and SDKs (Software Development Kits). Let's compare the traditional approach to building a collaborative feature with the modern SDK-based approach.

The Traditional Approach: Building from Scratch

Let's say we want to add a seemingly simple feature: live cursors, so teammates can see each other's mouse movements on the page. If you build this yourself, you're signing up for a lot of work.

First, you need a backend server to handle real-time communication, probably using WebSockets.

Example: Server-side code (conceptual)

// server.js - Simplified exampleconst WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

// When a new user connects...
wss.on('connection', ws => {
// When a user moves their cursor, they send a message
  ws.on('message', message => {
// We have to send this message to every other user
    wss.clients.forEach(client => {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send(message);
      }
    });
  });
});

Enter fullscreen mode Exit fullscreen mode

Then, you need the client-side code to send the user's cursor position and render the cursors of other users.

Example: Client-side code (conceptual)

// client.js - And you need this on the frontendconst socket = new WebSocket('ws://localhost:8080');

// Listen for messages from other users
socket.onmessage = (event) => {
  const cursorData = JSON.parse(event.data);
// Code to create or move a cursor element on the screenrenderAnotherUsersCursor(cursorData);
};

// Send our own cursor position on every movedocument.addEventListener('mousemove', (event) => {
  const position = { x: event.clientX, y: event.clientY };
  socket.send(JSON.stringify(position));
});

Enter fullscreen mode Exit fullscreen mode

The downsides of this approach are clear:

  • High Complexity: This is a simplified example. A real-world version would need to handle user authentication, different cursor designs, performance optimizations (so you don't overload the server), and error handling. It's a full-blown feature, not a quick add-on.
  • Slows You Down: All the time spent building and debugging this is time not spent improving your core product.
  • Maintenance Burden: You own this code forever. When it breaks or needs updates, it's on your team to fix it.

The SDK Approach: Using a Tool like Velt

Now, let's see the Velt approach. Velt has already built and perfected all that complex infrastructure. To add live cursors, you just use their React component.

Example: The Velt way

import { VeltProvider, VeltCursor } from '@veltdev/react';

function App() {
  return (
    <VeltProvider apiKey="YOUR_API_KEY">
      {/* This one component handles everything */}
      <VeltCursor />

      <YourLandingPageComponent />
    </VeltProvider>
  );
}

Enter fullscreen mode Exit fullscreen mode

The benefits are obvious:

  • Speed & Simplicity: You get a production-ready feature in minutes. All the complexity of servers, WebSockets, and state management is handled for you.
  • Focus: Your team can stay focused on building the landing page and business logic, not on reinventing collaboration tools.
  • Expertise: You get a feature that is maintained and improved by a team of experts whose only job is to make it great.

For our project, using an SDK is the clear choice. It allows us to move fast and add powerful features without getting slowed down.

This modern approach of combining specialized tools is exactly what makes vibe coding so effective. We use AI to get our initial design, an AI-powered IDE to code our logic, and powerful SDKs to handle the complex parts. Let's take a look at the specific tools we'll be using.

The tools we'll be using

Let's talk a bit about the tools we'll use the build our collaborative project:

Lovable: Lovable is an AI powered UI generator that takes a prompt and converts it into beautiful web UI. It's trained to give the best looking results (UI-wise) for any prompt.

Windsurf: It's an IDE with AI agent support. It's a fork of VS Code but with some extra AI features that basically allows AI as an agent to edit your code and make changes in real-time making it what feels like an AI pair-programming experience.

Velt: Velt is an SDK that helps us add real-time collaboration capabilities to our project. It provides us with simple methods that we can add to our projects which let's us add complicated features like live cursors, annotations, comments etc. We'll use Windsurf to help us integrate this into our project.

Vibe Coding Our Solution with Lovable, Velt, and Windsurf

Let's build our collaborative landing page!

Step 1: Generate the Landing Page UI with Lovable

With Lovable, we can describe the landing page we want, or even give it an image of a design we like, and it will generate the code for us.

Tips for a good Lovable prompt for a landing page:

  • Clearly state you want a "landing page."
  • Mention key sections: e.g., "a hero section with a call-to-action button," "a features section with three columns," "a simple contact form."
  • Describe the style: e.g., "modern and clean," "playful and colorful."
  • Specify any particular elements: e.g., "use a dark theme for the footer."

I went ahead and found a nice design on Dribble that I really liked and thought my new landing page should reference it. Here's the design I am talking about.

So I took a screenshot of the design and gave it to Lovable as an image. And added a prompt to make it look like a landing page for a mobile app.

this is a nice landing page I found on dribble, it's about a financing software.

I want you to take this as a reference (for theme, font, UI, style, animations, visuals and everything) and build a full landing page for me for a fictional Blockchain based UPI app.

It will basically run all transactions on the blockchain and users can even scan QR to pay in bitcoin!!

make it interesting and nice to see

Enter fullscreen mode Exit fullscreen mode

I went with a very basic prompt, but you can be more specific and detailed with your prompt.

Then I added an image of the Vercel Toolbar and asked it to add it to our landing page at the center bottom. I chose to create a separate prompt for this but you can instruct it in the first prompt itself.

Image2

And the results in the first try were amazing! Now that we have our base landing page, we can take the code and get ready for the next step: adding our custom collaboration features using Windsurf.

In order to be able to edit the code, you need to sync your GitHub account with Lovable so it can create a brand new repository for you. You will then be able to clone the repository and edit the code

To do this, find the option to sync your GitHub account at the top right corner of the Lovable editor:

Image3

Step 2: Add Real-time Collaboration with Velt using Windsurf

Now that the code is in a GitHub repository, we can clone it to our computer and open it in Windsurf. This is where we shift from generating the UI to programming the interactive features with our AI assistant.

Image4

First, we need to install the Velt SDK. You can open a terminal directly within Windsurf and run the following command:

npm install @veltdev/react

Enter fullscreen mode Exit fullscreen mode

With Velt installed, our next step is to add relevant Velt documentation for Windsurf and instruct it to turn our landing page into a Velt-powered app!

To add the Velt documentation simply type @docs:velt or it should automatically suggest it for you:

Image5

Creating the Base Velt Setup

Let's start by creating a simple Velt provider wrapper. We'll ask Windsurf to create this for us.

Prompt for Windsurf:

"Create a new file at src/components/VeltProvider.tsx. This should be a simple wrapper around Velt's BaseVeltProvider that takes an API key from environment variables and wraps children components."

Windsurf will generate a clean, simple provider:

// src/components/VeltProvider.tsximport { ReactNode } from 'react';
import { VeltProvider as BaseVeltProvider } from '@veltdev/react';

// Get API key from environment variable or use a placeholderconst VELT_API_KEY = import.meta.env.VITE_VELT_API_KEY || '';

export function VeltProvider({ children }: { children: ReactNode }) {
  return (
    <BaseVeltProvider apiKey={VELT_API_KEY}>
      {children}
    </BaseVeltProvider>
  );
}

Enter fullscreen mode Exit fullscreen mode

Image6

Adding Core Velt Components

Next, let's create a component that houses all our main Velt features.

Prompt for Windsurf:

"Create a new file at src/components/VeltComponents.tsx. Import VeltCursor, VeltComments, and VeltCommentTool from @veltdev/react. Export a component called VeltComponents that renders all three of these components."

// src/components/VeltComponents.tsximport { VeltCursor, VeltComments, VeltCommentTool } from '@veltdev/react';

export function VeltComponents() {
  return (
    <>
      <VeltCursor />
      <VeltComments />
    </>
  );
}

Enter fullscreen mode Exit fullscreen mode

Image7

Creating the User Switcher

Now we need a way to switch between users for testing our collaboration features.

Prompt for Windsurf:

"Create a src/components/UserSwitcher.tsx file. Use the useVeltClient hook to manage user switching. Create an array of demo users with IDs, names, and photo URLs. Add a VeltPresence component and a function to switch between users. Make it return a button that shows the current user and switches to the other when clicked."

// src/components/UserSwitcher.tsximport React, { useState } from 'react';
import { useVeltClient } from '@veltdev/react';
import { VeltPresence } from '@veltdev/react';

const DEMO_USERS = [
  {
    userId: 'user-1',
    name: 'Alex Johnson',
    photoUrl: 'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=100&h=100&fit=crop&crop=face',
    email: 'alex@blockpay.app'
  },
  {
    userId: 'user-2',
    name: 'Maria Garcia',
    photoUrl: 'https://images.unsplash.com/photo-1494790108755-2616b612b5e5?w=100&h=100&fit=crop&crop=face',
    email: 'maria@blockpay.app'
  }
];

export function UserSwitcher() {
  const [currentUserIndex, setCurrentUserIndex] = useState(0);
  const { client } = useVeltClient();

  const switchUser = () => {
    const newIndex = currentUserIndex === 0 ? 1 : 0;
    const newUser = DEMO_USERS[newIndex];

    client.identify(newUser);
    setCurrentUserIndex(newIndex);
  };

  const currentUser = DEMO_USERS[currentUserIndex];

  return (
    <div className="flex items-center gap-2">
      <VeltPresence />
      <button
        onClick={switchUser}
        className="flex items-center gap-2 px-3 py-1.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors"
      >
        <img
          src={currentUser.photoUrl}
          alt={currentUser.name}
          className="w-6 h-6 rounded-full"
        />
        <span className="text-sm">Switch to {DEMO_USERS[1 - currentUserIndex].name}</span>
      </button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Image8

Note: While prompting, it's helpful to first check the Velt documentation to understand what components are available and their capabilities. This makes your prompts more precise and helps get better, more focused results. For example, knowing that VeltCommentsVeltCommentsSidebar, and VeltCommentTool are separate components with specific purposes will help you structure your prompts more effectively.

Creating the Interactive Toolbar

Now let's make our toolbar functional by integrating it with Velt's collaboration features.

Prompt for Windsurf:

"Create a src/components/BottomToolbar.tsx component. Import VeltComments, VeltCommentsSidebar, VeltSidebarButton, and VeltCommentTool from @veltdev/react. Also import useTheme from next-themes. Create a toolbar that shows these Velt components and responds to the current theme (light/dark). The toolbar should be fixed at the bottom of the screen and styled like the Vercel toolbar."

// src/components/BottomToolbar.tsximport React from 'react';
import { useTheme } from 'next-themes';
import { UserSwitcher } from './UserSwitcher';
import { VeltComments, VeltCommentsSidebar, VeltSidebarButton, VeltCommentTool } from '@veltdev/react';

export function BottomToolbar() {
  const { theme } = useTheme();

  return (
    <>
      <VeltComments darkMode={theme === "dark"} popoverTriangleComponent={false} />
      <VeltCommentsSidebar darkMode={theme === "dark"} />

      <div className="fixed bottom-4 left-1/2 transform -translate-x-1/2 z-50">
        <div className="bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border rounded-lg shadow-lg px-4 py-2">
          <div className="flex items-center gap-4">
            <UserSwitcher />
            <div className="h-6 w-px bg-border" />
            <VeltSidebarButton darkMode={theme === "dark"}>
              <button className="flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors">
                Comments
              </button>
            </VeltSidebarButton>
            <VeltCommentTool darkMode={theme === "dark"}>
              <button className="flex items-center gap-2 px-3 py-1.5 text-sm font-medium text-muted-foreground hover:text-foreground transition-colors">
                Add Comment
              </button>
            </VeltCommentTool>
          </div>
        </div>
      </div>
    </>
  );
}

Enter fullscreen mode Exit fullscreen mode

And then similarly we created the rest of the components using just prompts and natural language. But a good practice when it comes to vibe coding is to also understand the generated outputs. Here's what every component involved from Velt means:

A Quick Look at the Velt Components We Used

When building with tools like Velt, it’s important to understand what each part of your code is doing. Here’s a straightforward explanation of the components we used:

VeltProvider: The Base Layer

This wraps your entire app (or the parts you want to make collaborative). It connects to Velt’s backend using your API key and handles real-time communication and authentication in the background.

Live Presence: VeltCursor and VeltPresence

  • <VeltCursor /> shows the live position of your teammates’ cursors with no extra setup.
  • <VeltPresence /> displays the avatars of users currently viewing the page. We placed it inside the UserSwitchercomponent to give a quick view of who's online.

Commenting Tools

  • <VeltCommentTool />: Adds a button that switches the app into comment mode, letting users drop comment pins.
  • <VeltComments />: Displays the pins and handles the comment threads.
  • <VeltCommentsSidebar />: Lists all the comment threads in a sidebar for easier navigation.
  • <VeltSidebarButton />: A button that toggles the sidebar open and closed.

Programmatic Access: useVeltClient

We used this hook inside UserSwitcher to call client.identify() and set the current user. This is helpful when you need to handle things like user sessions or dynamic identity changes manually.

With just these components, we were able to build a collaborative landing page that supports live presence and structured feedback.

You can check it out here.

and you can also find the code for the same in this Github Repo.

It was easy right? With just a few prompts, and a bit of documentation reading, we have a fully working project ready with us. And at the same time we also learned so much, thanks to our pair-programmer buddy!

Conclusion

Building modern websites doesn't have to be hard. By using the right tools together you can build something that would normally take weeks in just a few hours. This is what vibe coding is all about. Instead of fighting with complex code or spending months building basic features, you let AI and specialized tools do the heavy lifting. You focus on the fun stuff: making your product better and getting feedback from users.

And at the same time you're not just copying and pasting code blindly. You're learning how these tools work together while building something real. Each prompt teaches you something new, and each component you add makes more sense than the last.

Try this approach on your next project. Start with a simple idea, use AI to get the basics done, then add the features that make your product special. You'll be surprised how much you can build when you're not stuck writing the same code everyone else has already written.

The future of building software is here, and it's about being smart with your tools, not just working harder.

Top comments (4)

Collapse
 
astrodevil profile image
Astrodevil

Nice read!

Collapse
 
arindam_1729 profile image
Arindam Majumder

Thanks for checking out!

Collapse
 
djones profile image
David Jones

Great Write-up!

Collapse
 
arindam_1729 profile image
Arindam Majumder

Glad you liked it