Because it is "serverless" (React + Supabase), you don't need a complex server to run it. You need two things:
- The Database: A free project on Supabase.com.
- The Website: Hosted on Vercel, Cloudflare Pages, or your own web server.
Important: Handling API Keys
The public source code contains placeholder addresses (like placeholder.supabase.co). You do not need to edit the code files. Instead, you will provide your real API keys using Environment Variables during the deployment process.
Part 1: Database Setup (Supabase)
Before deploying the app, you must set up the backend.
- Create a free account and a new project at Supabase.com.
- Once your project is ready, go to the SQL Editor (on the left sidebar).
- Paste the following SQL code and click Run. This creates the database structure and ensures only you can see your data:
-- 1. Create the bookmarks table
create table bookmarks (
id bigint generated by default as identity primary key,
created_at timestamp with time zone default timezone('utc'::text, now()) not null,
url text not null,
title text not null,
description text,
tags text[] default '{}',
folders text[] default '{}',
notes text,
to_read boolean default false,
user_id uuid references auth.users not null default auth.uid()
);
-- 2. Enable Security (Row Level Security)
alter table bookmarks enable row level security;
-- 3. Create Access Policies (Only the owner can see/edit their data)
create policy "Users can only see their own bookmarks" on bookmarks for select using (auth.uid() = user_id);
create policy "Users can insert their own bookmarks" on bookmarks for insert with check (auth.uid() = user_id);
create policy "Users can update their own bookmarks" on bookmarks for update using (auth.uid() = user_id);
create policy "Users can delete their own bookmarks" on bookmarks for delete using (auth.uid() = user_id);
-- 4. Setup Image Storage for Avatars
insert into storage.buckets (id, name, public) values ('avatars', 'avatars', true);
create policy "Avatar images are publicly accessible" on storage.objects for select using ( bucket_id = 'avatars' );
create policy "Anyone can upload an avatar" on storage.objects for insert with check ( bucket_id = 'avatars' AND auth.role() = 'authenticated' );
Get your Credentials:
- Go to Project Settings (gear icon) -> API.
- Copy the Project URL.
- Copy the anon public key.
- Keep these safe, you will need them in Part 2.
Make it Private (Optional):
- Go to Authentication -> Providers -> Email. Disable "Confirm email".
- Create your account by logging into your new app later.
- After registration, go to Authentication -> Settings and disable "Allow new users to sign up".
Part 2: Deployment
Choose one of the following methods. Vercel is usually the easiest for React apps.
Option A: Install on Vercel (Recommended)
- Fork the LinkKiste repository to your GitHub account.
- Log in to Vercel and click "Add New Project".
- Select your GitHub repository.
- In the "Configure Project" section, find Environment Variables.
- Add these two variables:
VITE_SUPABASE_URL = https://your-project.supabase.coVITE_SUPABASE_ANON_KEY = your-long-anon-key-string
- Click Deploy.
Option B: Install on Cloudflare Pages
- Fork the LinkKiste repository to your GitHub account.
- Log in to the Cloudflare Dashboard and go to Workers & Pages.
- Click Create Application -> Pages -> Connect to Git.
- Select your repository.
- Build Settings:
- Framework preset: Select Vite or React.
- Build command:
npm run build - Output directory:
dist
- Environment Variables: Add
VITE_SUPABASE_URLandVITE_SUPABASE_ANON_KEY. - Click Save and Deploy.
Note: If you deploy first and then enter the Supabase credentials, you must re-deploy for the changes to take effect.
Option C: Manual Hosting (Apache/Nginx)
If you have your own web server (e.g., via FTP or SSH):
- Clone the repo to your local machine.
- Create a file named
.envin the root folder and add your keys:VITE_SUPABASE_URL=...
VITE_SUPABASE_ANON_KEY=... - Run
npm installand thennpm run build. - Upload the contents of the
distfolder to your web server. - Important: Configure your server for SPA (Single Page Application).
For Apache (.htaccess)
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
For Nginx
try_files $uri $uri/ /index.html;