- Shared SubpageShell (HeaderClient paper strip + ink footer) and SubpageIntro, btn/ghost/card helpers in app/_ui/subpage.tsx - Projects list: poster cards with hard ink shadows, filter pills, ink search field; no fake 800ms skeleton and no framer-motion opacity:0 in SSR - Project detail: poster hero, .plakat-prose markdown, links/stack aside, back link works without JS - Books: server-side fetch (visible without JS), cover + rating pills - Legal notice / privacy: moved to app/_ui/*Client.tsx, root routes removed (middleware always redirects to /[locale]), consent reset via useConsent - ProjectThumbnail rebuilt on Plakat tokens - Old Header.tsx + test removed; brown/cream/sand palettes and unused glass-panel/admin-glass(-light)/liquid-bg-blob/float CSS dropped (liquid palette, glass-card, admin-glass-card stay for admin + 404) - .plakat-prose replaces the missing typography plugin Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.9 KiB
How to Change Texts on the Website
This guide explains how to edit text content on your portfolio website.
Overview
The website uses next-intl for internationalization (i18n), supporting multiple languages. All text strings are stored in JSON files, making them easy to edit.
Where are the Texts?
All translatable texts are located in the /messages/ directory:
/messages/
├── en.json (English translations)
└── de.json (German translations)
How to Edit Texts
1. Open the Translation File
Choose the language file you want to edit:
- For English:
/messages/en.json - For German:
/messages/de.json
2. Find the Text Section
The JSON file is organized by sections:
{
"nav": {
"home": "Home",
"about": "About",
"projects": "Projects",
"contact": "Contact"
},
"home": {
"hero": {
"description": "Your hero description here",
"ctaWork": "View My Work",
"ctaContact": "Contact Me"
}
}
}
3. Edit the Text
Simply change the value (the text after the colon):
Before:
"ctaWork": "View My Work"
After:
"ctaWork": "See My Projects"
4. Save and Reload
After saving the file:
- In development: The changes appear immediately
- In production: Restart the application
Common Text Sections
Navigation (nav)
home,about,projects,contact
Home Page (home)
hero.description- Main hero descriptionhero.ctaWork- Primary call-to-action buttonhero.ctaContact- Contact buttonabout.title- About section titleabout.p1,about.p2,about.p3- About paragraphs
Projects (projects)
title- Projects page titleviewDetails- "View Details" button textcategories.*- Project category names
Contact (contact)
title- Contact form titleform.*- Form field labelssubmit- Submit button text
Footer (footer)
copyright- Copyright textmadeWith- "Made with" text
Privacy Policy & Legal Notice
The privacy policy and legal notice use a dynamic CMS system:
Option 1: Edit via Admin Dashboard (Recommended)
- Go to
/manage(requires login) - Navigate to "Content Manager"
- Select "Privacy Policy" or "Legal Notice"
- Edit using the rich text editor
- Click "Save"
Option 2: Edit Static Fallback
If you haven't set up CMS content, the fallback static content is in:
- Privacy Policy:
/app/_ui/PrivacyPolicyClient.tsx(Fallback-Text, sonst CMS-Seiteprivacy-policy) - Legal Notice:
/app/_ui/LegalNoticeClient.tsx(Fallback-Text, sonst CMS-Seitelegal-notice)
⚠️ Note: Static content is hardcoded in German. For CMS-based content, you can manage both languages separately.
Adding a New Language
To add a new language (e.g., French):
- Create translation file: Create
/messages/fr.json - Copy structure: Copy from
en.jsonand translate all values - Update i18n config: Edit
/i18n/request.tsexport const locales = ['en', 'de', 'fr'] as const; - Update middleware: Ensure the new locale is supported in
/middleware.ts
Best Practices
- ✅ DO: Keep the JSON structure intact
- ✅ DO: Test changes in development first
- ✅ DO: Keep translations consistent across languages
- ❌ DON'T: Change the keys (left side of the colon)
- ❌ DON'T: Break the JSON format (watch commas and quotes)
Validation
To check if your JSON is valid:
# Install a JSON validator
npm install -g jsonlint
# Validate the file
jsonlint messages/en.json
jsonlint messages/de.json
Or use an online tool: https://jsonlint.com/
Examples
Changing the Hero Description
File: /messages/en.json
{
"home": {
"hero": {
"description": "New description here - passionate developer building amazing things"
}
}
}
Changing Navigation Items
File: /messages/de.json
{
"nav": {
"home": "Startseite",
"about": "Über mich",
"projects": "Projekte",
"contact": "Kontakt"
}
}
Changing Button Text
File: /messages/en.json
{
"home": {
"hero": {
"ctaWork": "Browse My Portfolio",
"ctaContact": "Get In Touch"
}
}
}
Troubleshooting
Changes Don't Appear
- Clear your browser cache
- In development: Stop and restart
npm run dev - In production: Rebuild and restart the container
JSON Syntax Error
- Check for missing commas
- Check for unescaped quotes in text
- Use a JSON validator to find the error
Missing Translation
- Check that the key exists in all language files
- Default language (English) is used if a translation is missing
Need Help?
- Check the Next-intl documentation: https://next-intl-docs.vercel.app/
- Review existing translations for examples
- Test changes in development environment first
Last Updated: January 2026