Modern React + TypeScript portfolio powered by Vite, Tailwind CSS, and Framer Motion.
- React 19, TypeScript, Vite 7
- Tailwind CSS 4, PostCSS, Styled Components
- Framer Motion (animations), Lucide Icons
- Chart.js + react-chartjs-2 (lazy-loaded Bar)
- Vitest + Testing Library (unit tests)
Prereqs: Node 20+, Yarn 1.x.
Install deps
yarn install
Dev server
yarn dev
Build
yarn build
Preview
yarn preview
- lint: eslint .
- test: vitest run
- test:watch: vitest
- test:coverage: vitest run --coverage
- docker:dev: docker-compose up Vite dev (5173, HMR 24678)
- docker:prod: docker-compose up web-prod (nginx at 8080)
- deploy: builds, switches to production branch, rsyncs dist/, commits if changed, pushes, and switches back
- Dockerfile has multi-stage targets: dev (Vite), build, prod (nginx)
- docker-compose.yml defines:
- web: bind-mount dev with hot reload on http://localhost:5173
- web-prod: serves built assets via nginx on http://localhost:8080
- .dockerignore is configured to keep the build context small
Common
yarn docker:dev # dev with HMR
yarn docker:prod # serve built site on :8080
- Vitest + @testing-library/react
- Framer Motion is mocked in test setup (src/test-setup.ts) for stable DOM
- Hooks are mocked per test with vi.mocked(...) patterns
Run
yarn test
yarn test:watch
yarn test:coverage
- Public JSON data: public/data/profile.json, public/data/resume.json
- Hooks: src/hooks/useProfileData.ts, src/hooks/useResumeData.ts
- Key components: src/components/Portfolio.tsx, src/components/Resume.tsx
- Resume sections are collapsible (accessible), default-expanded
GA4 is integrated via gtag in index.html using measurement ID G-2J7SWPGLE4. If you prefer GTM, replace the GA snippet with your GTM container snippet.
Deployment is now handled automatically via GitHub Actions:
yarn deploy
This will:
- Run tests and build your project
- Commit and push changes to the
master
branch - Trigger a GitHub Actions workflow that builds and deploys to GitHub Pages
Your site is published at zkm.tw using a CNAME file in public/CNAME
.
If you change your domain, update public/CNAME
and push to master.
- Check deployment status in the GitHub Actions tab
- Ensure GitHub Pages source is set to "GitHub Actions" in repository settings
- Confirm your DNS records point to GitHub Pages
src/
components/
Portfolio.tsx
Resume.tsx
hooks/
useProfileData.ts
useResumeData.ts
__tests__/
public/
data/
profile.json
resume.json
Created by Zach Schneider