Personal portfolio and content site with a Supabase-backed admin CMS. Public pages for projects, articles, notes, videos, and about; protected admin panel for content management.
Repository: github.com/YankovWeb/personal-web-page
| Layer | Technology |
|---|---|
| Framework | Next.js 16 (App Router, React 19) |
| Styling | Tailwind CSS 4 |
| Database & Auth | Supabase (Postgres, RLS, Storage) |
| Resend (contact form notifications) | |
| Animation | Framer Motion |
| Theme | next-themes (light / dark) |
| Markdown | react-markdown + remark-gfm |
- Public site — Home, About (timeline, skills, certifications), Projects (personal vs team), Articles, Notes, Videos, Contact
- Admin CMS — CRUD for profile, articles, notes, videos, projects; contact message inbox
- Accessibility widget — Text size, high contrast, grayscale, link highlighting, readable font, reduce motion (persisted in
localStorage) - Theme toggle — Animated light/dark mode with CSS design tokens
- OG preview — Admin can fetch Open Graph metadata when adding project share URLs
- Motion system — Reusable reveal/stagger primitives; respects reduced-motion preference
1
src/
app/
(public)/ Public routes (shared header/footer layout)
admin/ Protected CMS (middleware + email allowlist)
api/og-preview/ Server-side OG metadata fetch
auth/callback/ Supabase OAuth / code exchange
components/ Feature-grouped UI (about, admin, motion, ui, …)
lib/ Queries, server actions, Supabase clients, types
supabase/migrations/ SQL migrations (apply via Supabase CLI or dashboard)
For AI assistants and contributors, see AGENTS.md for architecture notes and coding conventions.
- Node.js 20+
- A Supabase project with schema and RLS configured
- (Optional) Resend API key for contact email notifications
-
Clone and install
git clone git@github.com:YankovWeb/personal-web-page.git cd personal-web-page npm install -
Environment variables
Copy the example file and fill in your values:
cp .env.local.example .env.local
Variable Description NEXT_PUBLIC_SUPABASE_URLSupabase project URL NEXT_PUBLIC_SUPABASE_ANON_KEYSupabase anon / publishable key ADMIN_EMAILEmail allowed to access admin (server-side check) NEXT_PUBLIC_ADMIN_EMAILSame email (client-side login form pre-check) CONTACT_TO_EMAILInbox for contact form submissions RESEND_API_KEYOptional — sends email when contact form is submitted RESEND_FROM_EMAILOptional — verified sender in Resend -
Supabase Auth
Create an admin user in Supabase Dashboard → Authentication → Users with the same email as
ADMIN_EMAIL. Login uses email + password at/admin/login. -
Run dev server
npm run dev
Open http://localhost:3000.
| Command | Description |
|---|---|
npm run dev |
Start development server |
npm run build |
Production build |
npm run start |
Run production server locally |
npm run lint |
ESLint |
- Push to GitHub and import the repo on Vercel.
- Add all environment variables from
.env.local.examplein Project → Settings → Environment Variables. - In Supabase → Authentication → URL Configuration, set:
- Site URL:
https://your-domain.vercel.app - Redirect URLs:
https://your-domain.vercel.app/**andhttps://your-domain.vercel.app/auth/callback
- Site URL:
- Deploy. Admin panel:
/admin/login.
Migrations live in supabase/migrations/. Apply new migrations through the Supabase dashboard SQL editor or Supabase CLI:
supabase db pushPrivate — personal portfolio project.