edh.dev-inspired portfolio with a 3D retro computer + CRT terminal hero and scroll transition into 2D sections.
npm install
npm run devOpen http://localhost:3000.
PowerShell starter:
.\scripts\dev.ps1This opens http://localhost:3000/?dev=1 and enables the live dev panel.
Edit these files:
src/content/profile.ts
src/content/projects.ts
src/content/theme.ts
src/content/pages/about.md
src/content/pages/contact.md
src/content/pages/title.md
Validate content:
npm run validate-contentTranslations live here:
src/i18n/translations.ts
Markdown pages are per-language:
src/content/pages/about.tr.md
src/content/pages/about.en.md
src/content/pages/contact.tr.md
src/content/pages/contact.en.md
src/content/pages/title.tr.md
src/content/pages/title.en.md
Projects and profile content are localized inside:
src/content/profile.ts
src/content/projects.ts
To add a new language:
- Extend
Languageinsrc/lib/i18n.ts. - Add translations in
src/i18n/translations.ts. - Add
*.mdpages for the new language.
Language toggle writes to localStorage + cookie and also updates ?lang=tr|en.
Place the model here:
public/models/computer.glb
If the model is missing, the hero uses a placeholder mesh.
For the CRT terminal texture to map correctly, the screen mesh must be a separate object and named:
Screen,Display, orMonitor(case-insensitive)
If no screen mesh is found, a fallback plane is attached and the dev panel shows:
screen mesh not found, using fallback plane
The dev panel lists:
- All mesh names in the GLB
- The selected screen mesh name
- Whether fallback plane is used
help, ls, cd, pwd, show <file.md>, show -all, echo <text>, hello, mkdir <name>, touch <name>
Required APIs:
- run.googleapis.com
- cloudbuild.googleapis.com
- artifactregistry.googleapis.com
- cloudresourcemanager.googleapis.com
- iam.googleapis.com
- serviceusage.googleapis.com
- firebase.googleapis.com
- firebasehosting.googleapis.com
Configured names:
- Artifact Registry repo:
kinin-code - Cloud Run service:
kinin-code-dev
Cloud Build Trigger:
- Cloud Build -> Triggers -> connect GitHub
- Select
mainand usecloudbuild.yaml
Configured values:
- Region:
europe-west1 - Project ID:
kinin-code
Firebase Hosting:
firebase deploy --only hostingCloudflare DNS:
- Add the Firebase-provided DNS records in Cloudflare (DNS only recommended at first).
Local test:
docker build -t kinin-code .
docker run -e PORT=8080 -p 8080:8080 kinin-code
firebase emulators:startNote: max-instances caps cost.
The contact API appends submissions to Google Sheets.
Cloud Run (recommended):
- Set
GOOGLE_SHEETS_SHEET_ID(and optionalGOOGLE_SHEETS_RANGE). - Grant the Cloud Run service account access to the sheet.
- Share the sheet with the service account email.
Local dev (optional):
- Set
GOOGLE_SHEETS_CLIENT_EMAIL+GOOGLE_SHEETS_PRIVATE_KEYin.env.
Default range: Contacts!A:D (timestamp, name, email, message).
- Verify domain in Google Search Console (DNS).
- Submit the sitemap (
/sitemap.xml). - Check indexing with
site:your-domain. - Validate canonical + hreflang tags.
- Test structured data with Google Rich Results / Schema validator.
- For preview/staging set
NEXT_PUBLIC_NO_INDEX=1to prevent indexing.