Personal portfolio for BT — Software Engineer. Trilingual (TR / EN / FR), GSAP choreography, ambient particle field, and gated Coolify deployment.
Every push must clear, in order, before Coolify deploys:
| Gate | Tooling | Threshold |
|---|---|---|
| Lint | eslint (TS/React/Next plugins) | zero errors |
| Types | tsc --noEmit | zero errors |
| Content schema | scripts/validate-content.mjs | MDX + messages parity |
| Unit | vitest + Testing Library | all pass |
| Audit | pnpm audit --prod | no high/critical CVEs |
| E2E | Playwright (chromium + Pixel 7) | 67 scenarios × 2 projects |
| Lighthouse | lhci (en/tr/fr + digitalisation) | a11y ≥ 0.9, BP ≥ 0.9, SEO ≥ 0.9, perf ≥ 0.7 |
| Build | via Playwright webServer / lhci | zero errors |
Local pre-push hook runs the same chain via pnpm ci:full.
pnpm install
cp .env.example .env.local # set ADMIN_API_TOKEN for /admin writes
pnpm test:e2e:install # one-time: Chromium for Playwright
pnpm dev # http://localhost:3000
pnpm test
pnpm test:e2e
pnpm format # Prettier
pnpm validate:content
pnpm ci:checks # lint + typecheck + content + unit + audit
pnpm ci:local # ci:checks + production build
pnpm ci:full # ci:checks + e2e (pre-push hook)See CONTRIBUTING.md for PR expectations.
| Var | Purpose | Default |
|---|---|---|
NEXT_PUBLIC_SITE_URL |
Canonical URL for sitemap, OG, hreflang, RSS | https://berkayturk.com |
NEXT_PUBLIC_CONTACT_EMAIL |
Contact CTA + JSON-LD | hello@berkayturk.com |
NEXT_PUBLIC_BOOKING_URL |
Optional CTA URL (legacy; unused while /work is retired) |
mailto fallback |
NEXT_PUBLIC_SENTRY_DSN |
Browser error reporting | unset |
SENTRY_DSN |
Server-only Sentry override | unset |
SENTRY_*_TRACES_SAMPLE_RATE |
Performance trace sampling | 0.1 |
SENTRY_AUTH_TOKEN |
Source map upload (CI build only) | unset |
NEXT_PUBLIC_APP_ENV |
Sentry environment label | NODE_ENV |
ADMIN_API_TOKEN |
Bearer token for dev /api/admin/* |
unset (no auth if unset) |
NEXT_REACT_COMPILER |
Opt-in React Compiler build | unset |
| Secret | Purpose |
|---|---|
COOLIFY_DEPLOY_WEBHOOK |
Deploy webhook after all jobs pass (required on main) |
COOLIFY_API_TOKEN |
Bearer token for the webhook |
- CSP per request:
proxy.ts— nonce +'strict-dynamic'; productionreport-uri /api/csp-report - HSTS, COOP, CORP — tested in
e2e/security.spec.ts /.well-known/security.txt— contact coordinates- Admin stripped at Docker build —
app/(admin),app/api/admin,lib/admin,components/adminremoved beforepnpm build - Dev admin auth:
ADMIN_API_TOKEN+Authorization: Beareron write APIs - Sentry:
sendDefaultPii: false, extension noise filtered client-side
.github/workflows/ci.yml: static → unit → e2e → audit → lighthouse → deploy.
Set Coolify auto-deploy to manual; CI webhook is the sole production trigger.
- + New Resource → Docker Compose, branch
main. - Set
NEXT_PUBLIC_*env vars as build-time variables in Coolify. - Add domain
berkayturk.com. TLS is terminated by Coolify's reverse proxy (Traefik by default);docker-compose.ymlusesexpose: 3000only — no host port publish. - Configure
COOLIFY_DEPLOY_WEBHOOKin GitHub Actions secrets.
docker build -t berkayturk:dev .
docker run --rm -p 3100:3000 \
-e NEXT_PUBLIC_SITE_URL=http://localhost:3100 \
berkayturk:devpnpm dev → http://localhost:3000/admin. File-based CMS (no DB). Set ADMIN_API_TOKEN in .env.local.
Production: admin code is not in the Docker image; NODE_ENV=production returns 404 for /admin.
Next.js 16 · TypeScript · Tailwind v4 · next-intl · GSAP · Vitest · Playwright · Lighthouse CI · Sentry