Objective
Build a miniature full-stack version of a collaborative product demo platform inspired by Arcade. This task tests your ability to design, build, and deploy a modern web application that enables users to create and share interactive product stories.
Problem Statement
Create a web application that allows users to:
Sign up, log in, and manage sessions securely.
Create interactive product tours by uploading images/screenshots and adding descriptions or highlights.
Use an in-browser screen recorder to capture their workflow (basic screen capture support is sufficient).
View and edit their demos using a visual editor interface.
Publish demos as public or private links.
Browse a dashboard with all their demos and analytics (mocked).
Core Features
Frontend
Clean landing page with call-to-action.
Signup/login pages with form validation..
Product tour editor:
Upload screenshots or use placeholders.
Add/edit/delete tour steps with text annotations.
Use a screen recorder to capture product workflows.
Preview mode with animated step transitions.
Dashboard to view all created tours.
Responsive, interactive Ul with smooth animations.
Backend
RESTful or GraphQL API.
Authentication & session management (JWT/OAuth).
CRUD operations for product tours.
User & tour data persistence (e.g., PostgreSQL, MongoDB).
Role-based access (basic user vs viewer).
Tech Requirements
Frontend: React or Next.js (preferred), Tailwind CSS, Framer Motion.
Backend: Node.js (Express/NestIS), or any language/framework you're comfortable with.
Database: PostgreSQL, MongoDB, or any relational/noSQL database.
Auth: JWT or OAuth (mocked is okay).
Hosting: Deploy full stack using platforms like Vercel, Render, Railway, or
Heroku.
Bonus (Optional)
Add live collaboration (socket-based or mocked). Shareable public demo page with unique URL
Add analytics page (mock views, clicks per tour).
Drag-and-drop tour step reordering.
Dark/light mode toggle.
Deliverables
GitHub repository link with:
Clear project structure.
Setup instructions (README).
Deployed link(s) for frontend/backend
I'll help you build a collaborative product demo platform inspired by Arcade. Let's start by setting up the core infrastructure and then build out the features step by step.
I'll help you build a comprehensive product demo platform. Let's start by setting up the authentication and database infrastructure, then build out the core features.
Log in
You must be logged in to connect an integration.
Let's build our miniature product demo platform step by step. I'll create a full-stack application using Next.js with the App Router, Supabase for authentication and database, and Tailwind CSS for styling.
Let's start by setting up our database schema in Supabase and then building the application.
-- Create profiles table that extends the auth.users table
CREATE TABLE IF NOT EXISTS profiles (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
username TEXT UNIQUE,
full_name TEXT,
avatar_url TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create demos table
CREATE TABLE IF NOT EXISTS demos (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
title TEXT NOT NULL,
description TEXT,
is_public BOOLEAN DEFAULT false,
owner_id UUID REFERENCES profiles(id) ON DELETE CASCADE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
published_url TEXT,
thumbnail_url TEXT
);
-- Create demo_steps table
CREATE TABLE IF NOT EXISTS demo_steps (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
demo_id UUID REFERENCES demos(id) ON DELETE CASCADE NOT NULL,
title TEXT,
description TEXT,
image_url TEXT,
order_index INTEGER NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
annotations JSONB DEFAULT '[]'::JSONB
);
-- Create demo_recordings table
CREATE TABLE IF NOT EXISTS demo_recordings (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
demo_id UUID REFERENCES demos(id) ON DELETE CASCADE NOT NULL,
recording_url TEXT NOT NULL,
duration INTEGER,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create demo_analytics table (for mock analytics)
CREATE TABLE IF NOT EXISTS demo_analytics (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
demo_id UUID REFERENCES demos(id) ON DELETE CASCADE NOT NULL,
views INTEGER DEFAULT 0,
unique_visitors INTEGER DEFAULT 0,
avg_time_spent INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Create RLS policies
ALTER TABLE profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE demos ENABLE ROW LEVEL SECURITY;
ALTER TABLE demo_steps ENABLE ROW LEVEL SECURITY;
ALTER TABLE demo_recordings ENABLE ROW LEVEL SECURITY;
ALTER TABLE demo_analytics ENABLE ROW LEVEL SECURITY;
-- Profiles policies
CREATE POLICY "Public profiles are viewable by everyone"
ON profiles FOR SELECT USING (true);
CREATE POLICY "Users can insert their own profile"
ON profiles FOR INSERT WITH CHECK (auth.uid() = id);
CREATE POLICY "Users can update their own profile"
ON profiles FOR UPDATE USING (auth.uid() = id);
-- Demos policies
CREATE POLICY "Public demos are viewable by everyone"
ON demos FOR SELECT USING (is_public OR auth.uid() = owner_id);
CREATE POLICY "Users can insert their own demos"
ON demos FOR INSERT WITH CHECK (auth.uid() = owner_id);
CREATE POLICY "Users can update their own demos"
ON demos FOR UPDATE USING (auth.uid() = owner_id);
CREATE POLICY "Users can delete their own demos"
ON demos FOR DELETE USING (auth.uid() = owner_id);
-- Demo steps policies
CREATE POLICY "Demo steps are viewable by demo viewers"
ON demo_steps FOR SELECT USING (
EXISTS (
SELECT 1 FROM demos WHERE demos.id = demo_id AND (demos.is_public OR demos.owner_id = auth.uid())
)
);
CREATE POLICY "Users can insert steps to their demos"
ON demo_steps FOR INSERT WITH CHECK (
EXISTS (
SELECT 1 FROM demos WHERE demos.id = demo_id AND demos.owner_id = auth.uid()
)
);
CREATE POLICY "Users can update steps in their demos"
ON demo_steps FOR UPDATE USING (
EXISTS (
SELECT 1 FROM demos WHERE demos.id = demo_id AND demos.owner_id = auth.uid()
)
);
CREATE POLICY "Users can delete steps in their demos"
ON demo_steps FOR DELETE USING (
EXISTS (
SELECT 1 FROM demos WHERE demos.id = demo_id AND demos.owner_id = auth.uid()
)
);
-- Demo recordings policies
CREATE POLICY "Demo recordings are viewable by demo viewers"
ON demo_recordings FOR SELECT USING (
EXISTS (
SELECT 1 FROM demos WHERE demos.id = demo_id AND (demos.is_public OR demos.owner_id = auth.uid())
)
);
CREATE POLICY "Users can insert recordings to their demos"
ON demo_recordings FOR INSERT WITH CHECK (
EXISTS (
SELECT 1 FROM demos WHERE demos.id = demo_id AND demos.owner_id = auth.uid()
)
);
CREATE POLICY "Users can delete recordings in their demos"
ON demo_recordings FOR DELETE USING (
EXISTS (
SELECT 1 FROM demos WHERE demos.id = demo_id AND demos.owner_id = auth.uid()
)
);
-- Demo analytics policies
CREATE POLICY "Demo analytics are viewable by demo owners"
ON demo_analytics FOR SELECT USING (
EXISTS (
SELECT 1 FROM demos WHERE demos.id = demo_id AND demos.owner_id = auth.uid()
)
);
-- Create function to handle new user signup
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
INSERT INTO public.profiles (id, username, avatar_url)
VALUES (new.id, new.email, new.raw_user_meta_data->>'avatar_url');
RETURN new;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- Create trigger for new user signup
CREATE OR REPLACE TRIGGER on_auth_user_created
AFTER INSERT ON auth.users
FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();