This is the actual personal portfolio I use as my professional showcase. It started as a static vCard site and evolved into a full content platform: every project, post, certificate, skill, and bio link is stored in Supabase and rendered dynamically on the frontend. A separate admin panel lets me update any of it from the browser — no redeploys, no code edits.
Three independent apps live in this repo:
| App | Purpose | Stack |
|---|---|---|
portfolio/ |
Public portfolio site (about, resume, projects, blog, contact) | Vite + Vanilla JS + Supabase |
bio/ |
Linktree-style bio page — bio.mikaeldavid.online | HTML/CSS/JS + Supabase + PWA (service worker) |
panel/ |
Admin panel to manage profile, projects, blog, certificates, analytics | Vite + Vanilla JS + Supabase Auth |


analytics tableapp-ads.txt published at the root for monetizationportfolio/ and panel/The backend is a single Postgres database with the following tables:
profiles — Personal info, bio, social links
projects — Portfolio projects with images and tags
project_images — One-to-many gallery for each project
skills — Skill catalogue grouped by category
certificates — Certifications and credentials
timeline_items — Education / work history entries
services — Services offered (freelance)
blog_posts — Markdown posts with publish state
blog_comments — Comments with approval workflow
linkedin_posts — Cached LinkedIn feed
contact_messages — Inbound contact form submissions
analytics — Page views, sessions, device data
See supabase.sql for the full schema definition.
git clone git@gitlab.com:mikaeldavidlopes/personal-portfolio.git
cd personal-portfolio
Apply the schema from supabase.sql to your Supabase project, then update the Supabase URL and anon key in:
portfolio/src/core/config.jspanel/src/services/supabase.service.jsbio/src/services/supabase.service.jscd portfolio
npm install
npm run dev # http://localhost:5173
cd panel
npm install
npm run dev # http://localhost:5173
cd bio
npm install
npm run dev # http://localhost:3001
Each app builds independently:
cd portfolio && npm run build
cd panel && npm run build
cd bio && npm run preview # bio is plain HTML — no bundle step
personal-portfolio/
├── portfolio/ # Public portfolio site
│ ├── index.html
│ ├── pages/ # about, resume, portfolio, blog, contact
│ ├── src/
│ │ ├── components/ # Sidebar, project details, dynamic assets
│ │ ├── core/ # config, app bootstrap
│ │ ├── pages/ # Dynamic page renderers (Supabase-backed)
│ │ ├── services/ # supabase, profile, blog, linkedin
│ │ └── styles/ # main.css and partials
│ ├── *.mermaid # Class and ER diagrams
│ └── vite.config.js
│
├── panel/ # Admin panel (Supabase Auth)
│ ├── index.html
│ └── src/
│ ├── components/ # blog editor, profile, projects, analytics
│ └── services/ # auth, supabase, upload (storage)
│
├── bio/ # Linktree-style bio page (PWA)
│ ├── index.html
│ ├── sw.js # Service worker
│ └── src/services/ # supabase
│
├── website-demo-image/ # Screenshots used in this README
├── supabase.sql # Full Postgres schema
├── app-ads.txt # Ads.txt for AdSense
└── README.md
The portfolio/ app ships with system diagrams (class diagram, ERD) authored in Mermaid:
portfolio/class_diagram.mermaidportfolio/erd_diagram.mermaidportfolio/system_diagrams.mermaidportfolio/diagrams_summary.mdDistributed under the MIT License. See portfolio/LICENSE for details.
The original public portfolio template is based on the open-source vCard project, then heavily extended with a dynamic Supabase backend, a custom admin panel, and a separate bio app.