Learn step by step how to build a scheduling app with Lovable, from setup and UI to calendar sync, notifications, and deployment best practices.!!

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Build a simple scheduling app in Lovable by: 1) adding a small React UI + API route to create/list events, 2) connecting it to Supabase for persistence (set up via the Supabase dashboard), and 3) configuring secrets in Lovable Cloud. Do everything inside Lovable Chat Mode (edits, patches, Preview, Publish). If you need to run DB migrations or use the Supabase CLI, do that in the Supabase dashboard or via GitHub export (outside Lovable).
Simple scheduling app: a single-page UI to pick date/time, create events, and list upcoming events. Backed by Supabase table events. Lovable will add frontend pages/components and a server-side API route that uses Lovable Cloud Secrets for Supabase credentials.
Work entirely in Chat Mode: ask Lovable to create/modify files, add package.json dependency, and wire a server API route that uses process.env (Lovable Cloud Secrets). Preview to run and test. Publish to deploy. No terminal needed unless you must run local DB migrations — then use Supabase dashboard or GitHub export.
Prompt 1 — Initialize scheduling UI and Supabase client
Goal: Add UI and client code to create/list events.
Exact files to create/modify:
@supabase/supabase-js dependencyAcceptance criteria (done when…): The app shows a form to enter title + date/time, a "Create" button, and a list of events fetched from the server. The Supabase client is exported from src/lib/supabase.ts and uses process.env vars.
Secrets/integration steps: Add two Lovable Cloud Secrets: SUPABASE_URL and SUPABASE_ANON_KEY via Lovable Secrets UI. Also create a Supabase project and table as described in Prompt 2.
Patch (paste into Lovable Chat Mode):
// Create src/lib/supabase.ts
// Initialize and export a Supabase client using server-side-safe keys from process.env
import { createClient } from '@supabase/supabase-js'
const url = process.env.SUPABASE_URL
const key = process.env.SUPABASE_ANON_KEY
// export client for server and browser usage
export const supabase = createClient(url!, key!)
// Create src/pages/index.tsx
// Simple React page: form to add event, fetch list from /api/events
import React, { useEffect, useState } from 'react'
type EventItem = { id: number; title: string; start_at: string }
export default function Home() {
const [events, setEvents] = useState<EventItem[]>([])
const [title, setTitle] = useState('')
const [startAt, setStartAt] = useState('')
async function load() {
const res = await fetch('/api/events')
setEvents(await res.json())
}
useEffect(() => { load() }, [])
async function create() {
await fetch('/api/events', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ title, start_at: startAt })
})
setTitle(''); setStartAt('')
load()
}
return (
<div style={{ padding: 20 }}>
<h1>Scheduling</h1>
<input placeholder="Title" value={title} onChange={e => setTitle(e.target.value)} />
<input type="datetime-local" value={startAt} onChange={e => setStartAt(e.target.value)} />
<button onClick={create}>Create</button>
<ul>
{events.map(ev => <li key={ev.id}>{ev.title} — {new Date(ev.start_at).toLocaleString()}</li>)}
</ul>
</div>
)
}
// Modify package.json to include @supabase/supabase-js
// If package.json doesn't exist, create one with the project name and that dependency
{
"name": "lovable-scheduling",
"version": "0.1.0",
"dependencies": {
"@supabase/supabase-js": "^2.0.0",
"react": "18.x",
"react-dom": "18.x"
}
}
Prompt 2 — Add server API route using Supabase (create/list events)
Goal: Create an API endpoint that uses Supabase server-side to insert and read events.
Exact files to create:
Acceptance criteria: POST to /api/events inserts into Supabase table events; GET returns JSON list ordered by start_at.
Secrets/integration: Uses same Lovable Secrets (SUPABASE_URL, SUPABASE_ANON_KEY).
Patch:
// Create src/pages/api/events.ts
// Provides GET (list events) and POST (create event) handlers
import { NextApiRequest, NextApiResponse } from 'next'
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(process.env.SUPABASE_URL!, process.env.SUPABASE_ANON_KEY!)
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method === 'GET') {
const { data, error } = await supabase
.from('events')
.select('*')
.order('start_at', { ascending: true })
if (error) return res.status(500).json({ error: error.message })
return res.json(data)
}
if (req.method === 'POST') {
const { title, start_at } = req.body
const { data, error } = await supabase.from('events').insert([{ title, start_at }]).select()
if (error) return res.status(500).json({ error: error.message })
return res.status(201).json(data[0])
}
res.status(405).end()
}
This prompt helps an AI assistant understand your setup and guide to build the feature
This prompt helps an AI assistant understand your setup and guide to build the feature
This prompt helps an AI assistant understand your setup and guide to build the feature

Book a call with an Expert
Starting a new venture? Need to upgrade your web app? RapidDev builds application with your growth in mind.
Build small, reliable pieces, enforce atomic booking in the database, treat timezones carefully, store and rotate secrets with Lovable Secrets, use Preview and Chat Mode to iterate, and export to GitHub or use the provider’s web UI to run migrations or scheduled jobs (because Lovable has no terminal).
Decide what must never break: no double-booking, correct timezone handling, idempotent webhooks, clear retry behavior. Design your data model and API around those invariants so AI-generated code is checked against them.
Do it in the DB. Use a single SQL function (Postgres RPC) or a transaction that checks slot availability and inserts in one atomic step. Don’t rely on "check then insert" from separate queries — AI code often forgets races.
-- Create a safe atomic booking function in Postgres (Supabase)
CREATE OR REPLACE FUNCTION create_booking(p_user_id uuid, p_slot timestamptz)
RETURNS uuid AS $$
DECLARE new_id uuid;
BEGIN
IF EXISTS (SELECT 1 FROM bookings WHERE slot = p_slot) THEN
RAISE EXCEPTION 'slot_taken';
END IF;
new_id := gen_random_uuid(); -- pgcrypto available on Supabase
INSERT INTO bookings (id, user_id, slot) VALUES (new_id, p_user_id, p_slot);
RETURN new_id;
END;
$$ LANGUAGE plpgsql;
// Node / API route using supabase-js
const { createClient } = require('@supabase/supabase-js');
const SUPABASE_URL = process.env.SUPABASE_URL; // set in Lovable Secrets
const SUPABASE_KEY = process.env.SUPABASE_SERVICE_ROLE; // set in Lovable Secrets
const supabase = createClient(SUPABASE_URL, SUPABASE_KEY);
async function createBooking(userId, slotIso) {
// slotIso must be normalized to UTC ISO string before calling
const { data, error } = await supabase.rpc('create_booking', { p_user_id: userId, p_slot: slotIso });
if (error) {
if (error.message.includes('slot_taken')) throw new Error('Slot already available');
throw error;
}
return data;
}
Bottom line: use Lovable for fast, chat-driven iteration (code, SQL, UI) and its Secrets + Preview for safe testing. Keep critical invariants inside the DB (atomic functions/unique constraints), run scheduled jobs and migrations via the cloud provider or GitHub workflows (export from Lovable), and treat timezones, idempotency, and OAuth carefully.
From startups to enterprises and everything in between, see for yourself our incredible impact.
Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.