A personal website that grew into a small social platform — a portfolio / About page, a database-backed blog, live streaming, and a full-featured community ("VoiceUP"). Built with the Next.js App Router and Supabase, with an immunology-inspired theme.
🔗 Live: https://nkcells2004.com
- Editable About / profile page (admin CMS, stored in Supabase)
- News, Research, and Notes sections backed by the database
- Bilingual UI (Japanese / English) via cookie-based locale + middleware
- Theming and accessibility options (reduced motion, text size)
- Posts, comments, and reactions (likes)
- Rich composer: emoji picker, slash commands, image & file uploads (Supabase Storage)
- Search users by name and posts by content
- Follow with followers / following lists
- Reposts, merged into a single time-sorted timeline
- @mentions with linkification and notifications
- Private (locked) accounts with follow-request approval
- Interest hashtags and per-tag discussion boards
- Public profiles (
/u/[id]) with avatar, banner, bio, links, and a deterministic "Cell of the Day" badge
- Live page with YouTube / Twitch embeds and a Supabase Realtime chat
- Supabase email authentication
- Account settings: password change, account deletion (server-side admin)
- Notification preferences, privacy (private account), language, theme, accessibility
| Layer | Tools |
|---|---|
| Framework | Next.js 14 (App Router), TypeScript, React Server Components & Server Actions |
| Styling | Tailwind CSS |
| Backend | Supabase — Postgres, Auth, Realtime, Storage, Row-Level Security |
| Hosting | Vercel |
- All data access is guarded by Row-Level Security (RLS); mutations go through Server Actions.
- Notifications (comments, mentions) are generated by
SECURITY DEFINERPostgres triggers. - Private-account visibility is enforced in both queries and policies.
- Realtime chat and feed updates use Supabase Realtime.
- Node.js 18+
- A Supabase project
npm installCopy the example file and fill in your own Supabase values:
cp .env.example .env.local| Variable | Description |
|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Supabase project URL (public) |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Supabase anon key (public — protected by RLS) |
SUPABASE_SERVICE_ROLE_KEY |
Service-role key — server-only secret, never expose. Used only for account deletion. |
The app expects a set of Supabase tables (profiles, posts, comments, reactions, follows, reposts, notifications, tag tables, live_settings, site_profile, …) together with their RLS policies and notification triggers. Schema changes are applied via the Supabase SQL editor.
npm run devOpen http://localhost:3000.
src/
app/ # App Router routes (about, community, live, settings, u/[id], …)
components/ # Shared UI (header, rich composer, lists, …)
content/ # Static content & site configuration
lib/ # Supabase clients and helpers
middleware.ts # Locale detection
public/ # Static assets
Deployed on Vercel with automatic deploys on push to the default branch. Set the same environment variables in the Vercel project settings, and mark SUPABASE_SERVICE_ROLE_KEY as Sensitive.
Personal project. No open-source license is granted by default — please ask before reusing the code.