Portfolio (Vite + React + Tailwind)
Personal portfolio site built with React + TypeScript and styled with Tailwind. Includes a light/dark theme toggle and an optional “Professional Reviews” section backed by Firebase Firestore.
Features
- Responsive single-page app (SPA) with multiple portfolio sections.
- Light/Dark theme with persisted preference (
localStorage). - Professional Reviews
- Read reviews from Firestore on page load.
- Add review modal (name, position, rating, review text).
- If Firebase env vars are missing, reading returns an empty list and adding is disabled.
Tech Stack
- Vite (build + dev server)
- React 19 + TypeScript
- Tailwind CSS v4 (via
@tailwindcss/vite) - Firebase (Firestore) for reviews
- Docker + Nginx for production container
Getting Started (Local Dev)
Prerequisites
- Node.js (recommended: Node 22 to match the Docker build image)
- pnpm (recommended) or npm
If you don’t have pnpm yet:
corepack enable
corepack prepare pnpm@latest --activate
Install
pnpm install
Run dev server
pnpm dev
Vite will print the local URL (typically http://localhost:5173).
Environment Variables (Firebase)
Firebase is optional, but required to use the Reviews feature.
Create a .env file in the project root:
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=...
# Optional
VITE_FIREBASE_MEASUREMENT_ID=...
Vite only exposes environment variables prefixed with VITE_.
Firestore data model
Reviews are stored in a Firestore collection named reviews.
Document shape:
interface Review {
name: string;
rating: number; // 1..5
position: string;
text: string;
};
Firebase / Firestore Setup (for Reviews)
- Create a Firebase project.
- Enable Firestore Database.
- (Recommended for development) Start with permissive rules, then tighten before production.
- Copy your Firebase web app config values into
.env.local.
Notes:
- If Firebase is not configured, the app still runs normally—reviews will simply be empty and adding is disabled.
Scripts
pnpm dev— start Vite dev serverpnpm build— typecheck (tsc -b) then build (vite build)pnpm preview— preview the production build locallypnpm lint— run ESLint
Production (Docker + Nginx)
This repo includes a multi-stage Docker build:
- Node build stage runs
npm install+npm run build - Nginx stage serves the
dist/folder and provides SPA routing (try_files ... /index.html)
Build the image
You must pass Firebase values as build args (they’re embedded at build time by Vite):
docker build \
--build-arg VITE_FIREBASE_API_KEY=... \
--build-arg VITE_FIREBASE_AUTH_DOMAIN=... \
--build-arg VITE_FIREBASE_PROJECT_ID=... \
--build-arg VITE_FIREBASE_STORAGE_BUCKET=... \
--build-arg VITE_FIREBASE_MESSAGING_SENDER_ID=... \
--build-arg VITE_FIREBASE_APP_ID=... \
--build-arg VITE_FIREBASE_MEASUREMENT_ID=... \
-t portfolio:latest .
Run the container
docker run --rm -p 8080:80 portfolio:latest
Then open http://localhost:8080.
Docker Compose
docker-compose.yml is provided and forwards Firebase env vars as build args.
docker compose up --build
Note: the compose file currently uses ports: - "80" (short syntax). That exposes container port 80, for use with reverse proxy services, like Traefik, or more complex deployment methods, like Dokploy or Coolify. If you want a stable port, change it to something like:
ports:
- "8080:80"
Project Structure
.
├─ src/
│ ├─ main.tsx # React entrypoint
│ ├─ App.tsx # Main page composition + reviews modal
│ ├─ firebase.ts # Firebase + Firestore initialization
│ ├─ reviewsApi.ts # Firestore read/write helpers
│ ├─ contexts/
│ │ └─ ThemeContext.tsx # Theme state + CSS variables
│ └─ components/ # Page sections (Hero, Tech, Reviews, Footer, ...)
├─ nginx.conf # SPA routing for production container
├─ Dockerfile # Vite build → Nginx serve
└─ vite.config.ts # Vite config (React + Tailwind)
Customization Notes
- Some sections accept an
isOutOfCollegeprop and are currently disabled by default insrc/App.tsx. If you want those sections to render, passisOutOfCollege={true}into the relevant components. - Contact links are in the Hero section and Footer.
Troubleshooting
- Reviews don’t show up: confirm Firestore is enabled and your Firebase env vars are set (
VITE_FIREBASE_*). - “Firestore is not configured” error: you’re missing one or more required Firebase variables.
- Docker build doesn’t pick up env vars: ensure you pass them as
--build-arg ...(Vite embeds them during build).