How I made a note sharing app on v0.dev

Harvey DucayHarvey Ducay
5 min read

In today's fast-paced tech world, developers are constantly seeking ways to streamline their workflow and bring ideas to life quickly. Enter v0.dev, an AI-powered development assistant that's revolutionizing the way we build web applications. This tool is particularly valuable for front-end developers, UI/UX designers, and anyone looking to rapidly prototype React-based applications. In this post, we'll explore the process of creating a note-sharing app using v0.dev, demonstrating its capabilities and showing how it can significantly speed up your development process. We'll cover the basics of v0.dev, walk through the app creation process step-by-step, and provide tips for making the most of this innovative tool.

What is v0.dev, and Why Does it Matter?

v0.dev is an AI-powered development assistant created by Vercel. It generates React components based on natural language descriptions, leveraging the power of artificial intelligence to streamline the coding process. This tool matters because it addresses one of the most time-consuming aspects of web development: creating and styling UI components.

For developers, v0.dev can significantly reduce the time spent on boilerplate code, allowing more focus on core functionality and business logic. For designers, it offers a way to quickly translate ideas into functional prototypes. And for businesses, it means faster iteration cycles and reduced time-to-market for new features or products.

How to Create a Note Sharing App with v0.dev

Let's walk through the process of creating a note-sharing app using v0.dev. We'll break this down into several key steps.

Step 1: Creating the File Upload component

First, we need to create the file upload component for our app. Here's how we can do this with v0.dev:

  1. Open v0.dev in your browser.

  2. In the prompt, type: "make a file upload component where I can drag and drop pdf files i have to be stored in supabase storage buckets"

  3. v0.dev will generate a React component. Here's what it might look like:

Step 2: Creating the File Display component

Next, we'll create a file display component to display whatever files we have on our supabase storage.

  1. In v0.dev, prompt: "can you do a component that displays the PDF files within a supabase storage for file sharing"

  2. There’s no proper preview for the component as there is no files to be rendered, here’s the code generated instead:

'use client'

import { useState, useEffect } from 'react'
import { createClient } from '@supabase/supabase-js'
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { ScrollArea } from "@/components/ui/scroll-area"
import { FileIcon, Eye, Download } from 'lucide-react'

// Initialize the Supabase client
const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)

interface PDFFile {
  name: string
  url: string
}

export default function PDFViewer() {
  const [pdfFiles, setPdfFiles] = useState<PDFFile[]>([])
  const [selectedPDF, setSelectedPDF] = useState<string | null>(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    async function fetchPDFs() {
      try {
        setLoading(true)
        // Replace 'your-bucket-name' with your actual bucket name
        const { data, error } = await supabase.storage.from('your-bucket-name').list()

        if (error) {
          throw new Error('Error fetching PDF files')
        }

        if (data) {
          const pdfFiles = data
            .filter(file => file.name.toLowerCase().endsWith('.pdf'))
            .map(file => ({
              name: file.name,
              url: supabase.storage.from('your-bucket-name').getPublicUrl(file.name).data.publicUrl
            }))

          setPdfFiles(pdfFiles)
        }
      } catch (err) {
        setError(err instanceof Error ? err.message : 'An unknown error occurred')
      } finally {
        setLoading(false)
      }
    }

    fetchPDFs()
  }, [])

  if (loading) {
    return <div className="text-center p-4">Loading PDF files...</div>
  }

  if (error) {
    return <div className="text-center text-red-500 p-4">{error}</div>
  }

  return (
    <div className="container mx-auto p-4">
      <h1 className="text-2xl font-bold mb-4">PDF File Viewer</h1>
      <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
        <Card>
          <CardHeader>
            <CardTitle>PDF Files</CardTitle>
          </CardHeader>
          <CardContent>
            <ScrollArea className="h-[400px]">
              {pdfFiles.map((pdf, index) => (
                <div key={index} className="flex items-center justify-between p-2 hover:bg-gray-100 rounded">
                  <div className="flex items-center">
                    <FileIcon className="mr-2 h-4 w-4" />
                    <span className="text-sm">{pdf.name}</span>
                  </div>
                  <div>
                    <Button variant="ghost" size="icon" onClick={() => setSelectedPDF(pdf.url)} aria-label={`View ${pdf.name}`}>
                      <Eye className="h-4 w-4" />
                    </Button>
                    <Button variant="ghost" size="icon" onClick={() => window.open(pdf.url, '_blank')} aria-label={`Download ${pdf.name}`}>
                      <Download className="h-4 w-4" />
                    </Button>
                  </div>
                </div>
              ))}
            </ScrollArea>
          </CardContent>
        </Card>
        <Card>
          <CardHeader>
            <CardTitle>PDF Viewer</CardTitle>
          </CardHeader>
          <CardContent>
            {selectedPDF ? (
              <iframe
                src={`${selectedPDF}#toolbar=0`}
                className="w-full h-[400px] border-0"
                title="PDF Viewer"
              />
            ) : (
              <div className="flex items-center justify-center h-[400px] text-gray-500">
                Select a PDF to view
              </div>
            )}
          </CardContent>
        </Card>
      </div>
    </div>
  )
}

Step 3: Creating the Whiteboard component

Next, we'll create a component to have a whiteboard, possible for collaborating within the app:

  1. In v0.dev, prompt: "make a side by side component of a canvas-based shared whiteboard and a PDF viewer for collaborative annotations"

  2. v0.dev will generate a component like this:

Step 4: Creating the Feedback Form component

Whenever we create apps, its important to ask feedback from your app users in order to improve your existing product

  1. In v0.dev, prompt: "make me a feedback form that the data goes into my supabase table named "feedback_notes" , collect their "feedback" and "name" both of which are strings"

  2. v0.dev will generate a component like this:

Finally, we paste it all into vscode and we have this app live:

I forgot, to include my generation of the pomodoro timer! Well, with all these step by step indicated, it might be good practice to try generating components by your own now :).

Tips and Reminders for Using v0.dev

  1. Be specific in your prompts: The more detailed your description, the more accurate the generated component will be.

  2. Iterate and refine: Don't hesitate to regenerate components with slightly different prompts to get the exact result you want.

  3. Customize the output: While v0.dev provides a great starting point, remember to adjust the generated code to fit your specific needs.

  4. Leverage v0.dev for rapid prototyping: Use it to quickly create multiple versions of a component to compare and choose from.

  5. Combine with your expertise: v0.dev is a powerful tool, but it's most effective when combined with your development knowledge and experience.

Conclusion

Creating a note-sharing app with v0.dev demonstrates the power of AI-assisted development. By leveraging this tool, we were able to rapidly generate the core components of our app, significantly reducing development time. While v0.dev isn't a replacement for a developer's expertise, it's an invaluable asset for speeding up the development process, especially in the initial stages of a project.

As AI continues to evolve, tools like v0.dev will play an increasingly important role in web development. By embracing these technologies, developers can focus more on solving complex problems and less on repetitive coding tasks.

Ready to supercharge your development process? Try v0.dev today and experience the future of AI-assisted coding. Visit v0.dev to get started and revolutionize the way you build web applications! Make sure to see our other articles about v0.dev too.

0
Subscribe to my newsletter

Read articles from Harvey Ducay directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Harvey Ducay
Harvey Ducay