|
| 1 | +# CLAUDE.md — pkaranje.github.io |
| 2 | + |
| 3 | +Personal portfolio website for Pratik Karanje. Static site deployed to GitHub Pages via GitHub Actions. |
| 4 | + |
| 5 | +## Tech Stack |
| 6 | + |
| 7 | +| Layer | Tool | |
| 8 | +|---|---| |
| 9 | +| Framework | React 18 + TypeScript | |
| 10 | +| Build | Vite 4 | |
| 11 | +| Styling | Tailwind CSS 3 | |
| 12 | +| Animation | Framer Motion 12 | |
| 13 | +| Particles | @tsparticles/react + @tsparticles/slim | |
| 14 | +| Icons | lucide-react v1 (note: no `Github`/`Linkedin` icons — use `GitBranch`/`Link2`) | |
| 15 | +| Utilities | clsx + tailwind-merge → `cn()` at `src/lib/utils.ts` | |
| 16 | +| Deployment | GitHub Actions → GitHub Pages (`dist/`) | |
| 17 | + |
| 18 | +## Commands |
| 19 | + |
| 20 | +```bash |
| 21 | +npm run dev # start dev server at localhost:5173 |
| 22 | +npm run build # tsc type-check + vite build → dist/ |
| 23 | +npm run preview # preview production build at localhost:4173 |
| 24 | +``` |
| 25 | + |
| 26 | +Always run `npm run build` after making changes to confirm zero TypeScript errors before committing. |
| 27 | + |
| 28 | +## Project Structure |
| 29 | + |
| 30 | +``` |
| 31 | +src/ |
| 32 | +├── App.tsx # Root — composes Navbar + all sections |
| 33 | +├── index.css # Tailwind directives + dot-grid utility class |
| 34 | +├── main.tsx # React entry point |
| 35 | +├── data/ |
| 36 | +│ └── resume.ts # ★ Single source of truth for ALL content |
| 37 | +├── lib/ |
| 38 | +│ └── utils.ts # cn() helper (clsx + twMerge) |
| 39 | +└── components/ |
| 40 | + ├── Navbar.tsx # Fixed top nav, active section tracking |
| 41 | + ├── ui/ |
| 42 | + │ └── sparkles.tsx # SparklesCore (tsparticles wrapper) |
| 43 | + └── sections/ |
| 44 | + ├── Hero.tsx # Two-column card: text left / photo right |
| 45 | + ├── Skills.tsx # 8 skill category cards |
| 46 | + ├── Experience.tsx # Work history cards |
| 47 | + ├── Certifications.tsx # Certs + education + languages |
| 48 | + ├── Projects.tsx # 6 project cards |
| 49 | + └── Contact.tsx # Contact link cards + email CTA |
| 50 | +
|
| 51 | +public/ |
| 52 | +├── profile.jpeg # Profile photo (served at /profile.jpeg) |
| 53 | +└── CV_Detailed_Pratik_Karanje.pdf # Resume PDF (linked from hero Download button) |
| 54 | +``` |
| 55 | + |
| 56 | +## Content Updates |
| 57 | + |
| 58 | +**All resume data lives in `src/data/resume.ts` only.** Never hardcode content in components. The file exports: |
| 59 | + |
| 60 | +- `personal` — name, title, email, phone, github, linkedin, location, summary |
| 61 | +- `skills` — array of `{ category, items[] }` |
| 62 | +- `experience` — array of `{ role, company, period, highlights[] }` |
| 63 | +- `projects` — array of `{ name, org, tech[], description, link? }` |
| 64 | +- `certifications` — array of `{ name, issuer, status }` |
| 65 | +- `education` — array of `{ degree, institution, period }` |
| 66 | + |
| 67 | +## Design System |
| 68 | + |
| 69 | +**Theme:** Light. Background `#f0f4f8` (`bg-brand-50`) with `dot-grid` class (radial-gradient dots defined in `index.css`). |
| 70 | + |
| 71 | +**Section alternation:** |
| 72 | +- `dot-grid` sections: Hero, Skills, Certifications, Contact |
| 73 | +- `bg-white` sections: Experience, Projects |
| 74 | + |
| 75 | +**Cards:** `bg-white rounded-2xl border border-gray-100 shadow-sm` — standard card pattern used everywhere. |
| 76 | + |
| 77 | +**Typography:** |
| 78 | +- Section eyebrow: `text-sm font-semibold text-gray-400 uppercase tracking-widest` |
| 79 | +- Section heading: `text-4xl md:text-5xl font-bold text-gray-900` |
| 80 | +- Body: `text-sm text-gray-500 leading-relaxed` |
| 81 | + |
| 82 | +**Buttons:** |
| 83 | +- Primary (dark): `px-6 py-3 rounded-full bg-gray-900 text-white font-semibold hover:bg-gray-700` |
| 84 | +- Secondary (outline): `px-6 py-3 rounded-full border border-gray-200 text-gray-700 hover:border-gray-400` |
| 85 | + |
| 86 | +**Animations:** All use Framer Motion `whileInView` with `viewport={{ once: true }}`. Standard pattern: |
| 87 | +```tsx |
| 88 | +<motion.div |
| 89 | + initial={{ y: 24, opacity: 0 }} |
| 90 | + whileInView={{ y: 0, opacity: 1 }} |
| 91 | + viewport={{ once: true }} |
| 92 | + transition={{ duration: 0.55 }} |
| 93 | +> |
| 94 | +``` |
| 95 | +Use `ease: "easeOut"` (string) not an array — the installed framer-motion version rejects numeric arrays for `ease`. |
| 96 | + |
| 97 | +## Path Alias |
| 98 | + |
| 99 | +`@/` maps to `src/` (configured in both `vite.config.ts` and `tsconfig.json`). |
| 100 | + |
| 101 | +```ts |
| 102 | +import { cn } from "@/lib/utils"; // ✓ |
| 103 | +import { cn } from "../../lib/utils"; // also fine |
| 104 | +``` |
| 105 | + |
| 106 | +## Deployment |
| 107 | + |
| 108 | +Pushing to `main` triggers `.github/workflows/deploy.yml` which: |
| 109 | +1. Runs `npm ci && npm run build` |
| 110 | +2. Uploads `dist/` as a Pages artifact |
| 111 | +3. Deploys to `https://pkaranje.github.io` |
| 112 | + |
| 113 | +GitHub Pages source must be set to **GitHub Actions** (not branch) in repo Settings → Pages. |
| 114 | + |
| 115 | +## Known Constraints |
| 116 | + |
| 117 | +- `lucide-react@1.x` does not export `Github` or `Linkedin` — use `GitBranch` and `Link2` instead. |
| 118 | +- `base: "./"` is set in `vite.config.ts` so asset paths work correctly on GitHub Pages. |
| 119 | +- The `SparklesCore` component (`src/components/ui/sparkles.tsx`) uses `initParticlesEngine` which only initialises once globally — do not instantiate it in components that mount/unmount frequently. |
| 120 | +- Profile photo fallback uses `ui-avatars.com` if `/profile.jpeg` fails to load (Hero component `onError` handler). |
0 commit comments