| name | changelog-json |
| description | Generate user-facing changelog JSON entries for src/data/changelog.json. Matches existing Neuland Next wording, tone, length, and bilingual structure (de/en). Validates icons for iOS SF Symbols, Android Material Symbols, and web Lucide. Use when preparing a release, adding What's New entries, or updating changelog.json for a new app version. |
Changelog JSON Entries
Generate entries for src/data/changelog.json — the in-app What's New screen and settings changelog. Entries must match the project's established voice and pass icon/type checks on all platforms.
When to use
- Bumping
app.config.json expo.version for a release
- Writing What's New copy from a PR, issue, or feature list
- Adding or refreshing entries under a
version["x.y"] key
Not for CHANGELOG.md (that is generated by bun changelog / git-cliff from git history).
File and schema
Path: src/data/changelog.json
{
"version": {
"0.16": [
{
"title": { "de": "…", "en": "…" },
"description": { "de": "…", "en": "…" },
"icon": { "ios": "…", "android": "…", "web": "…" }
}
]
}
}
| Field | Rules |
|---|
| Version key | Major.minor only (0.16, not 0.16.0). Patch releases share the same key. See _note at top of JSON. |
title | Short headline, both de and en. |
description | 1–2 sentences, both de and en. Shown on What's New; changelog screen shows title + icon only. |
icon | All three platforms required. Typed as Version in src/types/data.ts. |
CI: bun changelog:check fails if app.config.json expo.version has no matching key with ≥1 entry.
Workflow
- [ ] 1. Read app version → derive key with convertToMajorMinorPatch (e.g. 0.16.0 → "0.16")
- [ ] 2. Read recent entries in changelog.json for tone/length (same major line or last 2–3 versions)
- [ ] 3. Draft 1–4 entries from the release scope (features first, then improvements, then bug fixes)
- [ ] 4. Pick icons — reuse a proven triplet when possible (see references/icon-triplets.md)
- [ ] 5. Validate icons on all platforms (see below)
- [ ] 6. Append to version["x.y"] in changelog.json (tabs, single quotes in TS imports only — JSON uses double quotes)
- [ ] 7. Run bun changelog:check and bun tsc --noEmit
How many entries?
| Release type | Typical entries |
|---|
| Major feature release | 2–4 (one per headline feature + optional bug-fix card) |
| Small improvement release | 1 (Verbesserungen / Improvements) |
| Bugfix-only (patch) | Often no new JSON key — patches reuse the minor key; only add text if the minor release had no entry yet |
Reuse the standard bug-fix entry verbatim when appropriate (see references/style-guide.md).
Voice and style
Read src/data/changelog.json before writing. Match length and tone of neighboring versions, not marketing blog posts.
Titles
- Length: ~2–4 words (≤30 characters per language when possible).
- EN: Title Case for multi-word titles (
Event Details, Quick Links). Single concepts stay as-is (Map, Bug Fixes).
- DE: Short noun phrases; compounds without hyphens are fine (
Karten Darkmode, Performance Verbesserungen, Profil Tab).
- Name the user-visible surface (tab, card, screen, map) — not internal refactors.
Descriptions
- Length: One sentence preferred; two short sentences max. Target ~12–25 words per language (roughly 80–160 characters).
- Focus: What the student gains — not implementation detail.
- DE: Informal du form (
Aktiviere, Tippe, Finde, Erreiche, Klicke).
- EN: Direct, friendly, active voice (
Enable, Tap, Find, Access, Click).
- Avoid: version numbers, API names, file paths, "we", passive stacks of technical terms, exclamation marks.
Standard reusable entries
Copy these exactly when the release is bugfix-only or mixed minor fixes (already used in multiple versions):
| de title | en title | de description | en description |
|---|
| Fehlerbehebungen | Bug Fixes | Viele kleine Fehler wurden behoben, um die App noch besser zu machen. | Many small bugs have been fixed to make the app even better. |
| Verbesserungen | Improvements | Diverse Verbesserungen und Fehlerbehebungen in dieser Version. | Various improvements and bug fixes in this release. |
| Performance Verbesserungen | Performance Improvements | Die App ist nun schneller und flüssiger. Viele kleine Details wurden optimiert. | The app is now faster and smoother. Many small details have been optimized. |
More examples and patterns: references/style-guide.md.
Icons (all platforms)
Icons render via PlatformIcon in src/components/Flow/whats-new-box.tsx. Invalid names show a broken-icon fallback on web or fail silently on native — always validate.
| Platform | Property | Format | Valid source |
|---|
| iOS | icon.ios | SF Symbol name (moon.stars, party.popper) | node_modules/sf-symbols-typescript/dist/index.d.ts |
| Android | icon.android | snake_case Material Symbol | src/types/material-icons.ts (MaterialIcon union) |
| Web | icon.web | PascalCase Lucide export | lucide-react-native/icons (LucideIcon = keyof typeof icons in src/components/Universal/icon.tsx) |
Names do not need to match across platforms — only the meaning should align (e.g. iOS hammer + Android bug_report + web Bug for bug fixes).
Picking icons
- Prefer reuse from
references/icon-triplets.md or src/components/icons.ts (cardIcons).
- For new triplets, choose the same concept on each platform (map →
map / map / Map).
- iOS: plain symbol names work (
map, person); .fill variants are optional (changelog tends to use un-filled names).
- Web: Lucide uses PascalCase (
MoonStar from moon-star icon file).
- Android: only glyphs listed in
material-icons.ts (project ships Material Symbols Rounded font).
Validation (run before committing)
Android — must appear as a quoted union member:
grep -F "'<android_name>'" src/types/material-icons.ts
Web — must be exported from Lucide:
grep -F "exports.<WebName> =" node_modules/lucide-react-native/dist/cjs/icons/index.js
iOS — must appear in SF Symbols types:
grep -F "'<ios.name>'" node_modules/sf-symbols-typescript/dist/index.d.ts
TypeScript (catches invalid Android + web):
bun tsc --noEmit
Changelog key:
bun changelog:check
If any grep returns no match, pick a different icon or add Android glyph to material-icons.ts only when the font actually includes it (rare — prefer an existing name).
JSON formatting
Match the existing file:
- Tabs for indentation
- Trailing commas on array/object items (Biome allows in JSON here)
- One blank line between entries in an array is common but not required
- Keep
version keys sorted logically; the UI sorts semantically by version number
Example (new feature)
For a new dashboard widget:
{
"title": {
"de": "Campus Widget",
"en": "Campus Widget"
},
"description": {
"de": "Sieh auf einen Blick, was heute auf dem Campus passiert — direkt auf dem Dashboard.",
"en": "See what's happening on campus today at a glance — right on your dashboard."
},
"icon": {
"ios": "building.2",
"android": "domain",
"web": "Building2"
}
}
Validate all three icon names before inserting.
Related code
| File | Purpose |
|---|
src/data/changelog.json | Data file to edit |
src/app/(screens)/whatsnew.tsx | What's New screen (descriptions visible) |
src/app/(screens)/changelog.tsx | Settings → full changelog list |
config/check-changelog-version.ts | CI version check |
src/utils/changelog-utils.ts | Validation helper |
src/components/icons.ts | Dashboard card icon triplets |
src/types/data.ts | Version, Changelog types |
References
references/style-guide.md — tone, length, bilingual patterns from existing entries
references/icon-triplets.md — proven icon mappings to reuse