A musician landing page with an admin panel for content management.
- Landing page:
- Header with navigation
- Hero section
- Music section (YouTube previews)
- Photo gallery section
- Footer with contacts and copyright
- Admin panel (
/admin):- Hero content editing
- Track management (YouTube links)
- Photo uploads to Cloudinary
- Contact data editing
- React + TypeScript + Vite
- React Router
- Firebase Firestore (content)
- Cloudinary (images)
- Install dependencies:
npm install-
Create a
.envfile based on.env.example. -
Fill in Firebase and Cloudinary variables:
VITE_FIREBASE_API_KEY=
VITE_FIREBASE_AUTH_DOMAIN=
VITE_FIREBASE_PROJECT_ID=
VITE_FIREBASE_STORAGE_BUCKET=
VITE_FIREBASE_MESSAGING_SENDER_ID=
VITE_FIREBASE_APP_ID=
VITE_CLOUDINARY_CLOUD_NAME=
VITE_CLOUDINARY_UPLOAD_PRESET=- Start development server:
npm run dev- Production build:
npm run buildDocument: landing/main
Includes:
- artistName
- heroTitle
- heroSubtitle
- heroImageUrl
- heroImagePositionX
- heroImagePositionY
- navItems[]
- tracks[]
- gallery[]
- contacts
Additional collections used for admin security and auditing:
admin_users/{uid}: admin allowlist entry. Create documents manually in Firestore for users who can access/adminand save changes.admin_logs/{autoId}: immutable audit log entries created on each save from admin panel.
Audit log document fields:
createdAt(server timestamp)actorEmailactorUidaction(save_landing_content)targetPath(landing/main)savedSummary(what was saved: artist, hero text, counts, contacts)
Workflow: .github/workflows/firebase-hosting-deploy.yml
Deployment runs:
- on
pushto branchmain_git - manually via
workflow_dispatch
Required GitHub Secrets:
FIREBASE_SERVICE_ACCOUNT_MY_DIGITAL_PROFILE_E9F92VITE_FIREBASE_API_KEYVITE_FIREBASE_AUTH_DOMAINVITE_FIREBASE_PROJECT_IDVITE_FIREBASE_STORAGE_BUCKETVITE_FIREBASE_MESSAGING_SENDER_IDVITE_FIREBASE_APP_IDVITE_CLOUDINARY_CLOUD_NAMEVITE_CLOUDINARY_UPLOAD_PRESET
The Firebase project is set in .firebaserc as my-digital-profile-e9f92.