A soft, Instagram-inspired social app for cats — now backed by Supabase for real multi-user auth, global feed, photo uploads, and live chat.
Stack: Vite + React + TypeScript, Tailwind CSS, Supabase (Auth, Postgres, Storage, Realtime), Context API.
npm install
cp .env.example .env
# fill VITE_SUPABASE_URL + VITE_SUPABASE_ANON_KEY
npm run devnpm run build
npm run preview- Go to https://supabase.com → New project
- Wait until the database is ready
- Open Project Settings → API
- Copy:
- Project URL →
VITE_SUPABASE_URL - anon public key →
VITE_SUPABASE_ANON_KEY
- Project URL →
Local — create .env in the project root:
VITE_SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co
VITE_SUPABASE_ANON_KEY=YOUR_SUPABASE_ANON_KEYVercel — Project → Settings → Environment Variables → add the same two keys for Production / Preview, then redeploy.
- In Supabase → SQL Editor → New query
- Paste the full contents of
supabase/schema.sql - Click Run
This creates:
| Resource | Purpose |
|---|---|
profiles |
Cat profiles linked to auth.users |
posts / likes / comments |
Global feed |
follows |
Friendship / follow graph |
messages (sender_id, receiver_id, content) |
Direct messages |
Storage bucket cat-photos |
Profile + post image uploads |
| RLS policies | Secure per-user access |
| Realtime publication | Live messages + feed updates |
If you already had the older conversation-based DMs schema, also run supabase/migrations/refactor_messages_dm.sql in the SQL Editor.
If a Realtime alter publication line errors because a table is already added, you can ignore that specific error.
Supabase → Authentication → Providers → Email:
- Enable Email provider
- Keep Confirm email ON so friends verify before entering the app
Supabase → Authentication → URL Configuration:
- Site URL: your Vercel domain (e.g.
https://YOUR-APP.vercel.app) - Redirect URLs allow list (add all that apply):
http://localhost:5173/**https://YOUR-APP.vercel.app/**https://YOUR-APP.vercel.app/authhttps://YOUR-APP.vercel.app/reset-password
App env:
VITE_APP_URL=https://YOUR-APP.vercel.app(Locally you can omit it — the app falls back to window.location.origin.)
- Deploy / open the app
- Each friend Signs up with email + password + unique username + cat profile
- Use Search to find cats by
@username, then Follow them - Home feed shows posts from accounts you follow (plus your own)
- Message a friend → realtime chat via Supabase Realtime
If you already ran an older schema, run these in the Supabase SQL Editor as needed:
supabase/migrations/add_username.sql— unique@usernamehandlessupabase/migrations/add_stories.sql— Instagram-like stories table + RLSsupabase/migrations/add_food_streak.sql— legacy (optional; replaced by Treat Catcher)supabase/migrations/add_game_and_notifications.sql—game_high_score+notificationstable/triggerssupabase/migrations/add_message_notifications.sql— DM notification type + previewbodysupabase/migrations/fix_notifications_user_id.sql— required renamerecipient_id→user_id+ RLS (fixes empty notification panel)
Stories upload to the public cat-photos bucket under the stories/ prefix (same bucket policies as other uploads).
Profile isolation: own settings live at /profile; other cats at /profile/:userId (legacy /u/:username redirects).
Treat Catcher: 30s mini-game from the navbar / profile; high score stored on profiles.game_high_score.
Notifications: DB triggers create like/comment/follow rows (no self-actions); heart badge in the header marks them read when opened.
- Light / Dark toggle in the navbar (
ThemeProvider+ Tailwinddark:classes). Preference is stored inlocalStorage. - EN / TR language toggle beside it (
src/i18n/translations.ts).
Palette: soft sunset pastels in light mode; midnight velvet + purple glow borders in dark mode.
ImageUploaduses<input type="file" accept="image/*" />- Instant preview via
URL.createObjectURL(file) - Upload path: public Storage bucket
cat-photos(profiles/…,posts/…) → public URL saved on profile/post rows
- Mock
localStorageauth + seed arrays removed (Mama Streak + language stay local) AppContextsyncs with Supabase session + Postgres- Service layer under
src/services/:supabaseClient.ts— centralcreateClientusingVITE_SUPABASE_*env varsauth.ts— signup / login / logoutposts.ts— global discovery feed, create post, likes, commentsmessages.ts— peer-based DMs (sender_id/receiver_id) + Realtime listenersprofiles.ts— profile CRUD, username search, followsstorage.ts— image uploads to thecat-photosbucketapi.ts— facade re-exportsThemeContext— light/dark mode
- Active chat subscribes to
messagesinserts for the open peer thread - Inbox + Toastify listen for all DMs involving the current user
- Feed refreshes on
posts/likes/commentschanges
| Path | Page |
|---|---|
/auth |
Sign up / Sign in (username required) |
/ |
Global discovery feed + stories + create post |
/search |
Live username / name search |
/profile |
Own editable profile + Treat Catcher entry |
/profile/:userId |
Isolated public profile + high score + follow |
/u/:username |
Redirects to /profile/:userId |
/messages |
Live DM split pane |
src/
components/ # UI (ImageUpload, CreatePost, chat, feed, layout)
context/ # AppProvider synced to Supabase
services/ # Auth, posts, messages, profiles, storage
lib/ # supabase client
pages/
i18n/
types/
supabase/
schema.sql # run once in Supabase SQL Editor
- Push repo to GitHub
- Import in Vercel (framework: Vite, output:
dist) - In Project → Settings → Environment Variables, set for Production (and Preview if needed):
VITE_SUPABASE_URL=https://YOUR_PROJECT_REF.supabase.co(no trailing slash, no quotes)VITE_SUPABASE_ANON_KEY= anon public keyVITE_APP_URL= your Vercel URL (e.g.https://catstagram.vercel.app)
- Confirm
vercel.jsonSPA rewrite is present - Redeploy after any env change (Vite bakes
VITE_*in at build time)
If Auth returns 404 on Vercel but works locally, the build almost always lacked the VITE_ env vars — add them and redeploy.
Keep domain logic in services/, context/, types/, and lib/. A future React Native / Expo app can reuse the same Supabase project and swap only the UI layer.