Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
59842d7
Set up `example-app-router-patterns`
amannn Aug 29, 2025
5b23c25
Set up design system
amannn Aug 29, 2025
0f3f97c
feat: Add Next.js project files and configurations
Adebesin-Cell Oct 13, 2025
e16db8a
feat: Add 'playground' to packages list
Adebesin-Cell Oct 13, 2025
3ce3957
feat: Add new components and update dependencies
Adebesin-Cell Oct 18, 2025
675e533
style: Update styling in Home component
Adebesin-Cell Oct 18, 2025
37201bd
feat: Add Client Components and Server Components pages and components
Adebesin-Cell Nov 8, 2025
4208d3f
fix: merge conflicts
Adebesin-Cell Nov 8, 2025
adae65c
fix: lockfile
Adebesin-Cell Nov 8, 2025
41ed301
fix: merge conflicts
Adebesin-Cell Nov 8, 2025
b4fb489
docs: Add v1 implementation plan for playground refactor
Adebesin-Cell May 8, 2026
2542c8a
chore(playground): add MDX, Code Hike consumers, next-intl deps
Adebesin-Cell May 8, 2026
5a9c8be
feat(playground): configure @next/mdx and Code Hike plugins
Adebesin-Cell May 8, 2026
5686703
feat(playground): wire MDX components map with stub <Code>
Adebesin-Cell May 8, 2026
337adbc
feat(playground): set up next-intl routing and message catalogs
Adebesin-Cell May 8, 2026
ea3b26f
refactor(playground): move app routes under [locale] segment
Adebesin-Cell May 8, 2026
7e0a9eb
refactor(playground): move chrome components to src/components/playgr…
Adebesin-Cell May 8, 2026
b7f2a9a
refactor(playground): keep client providers as a pure theme wrapper
Adebesin-Cell May 8, 2026
f44bb0c
chore(playground): drop turbopack flag (incompatible with @next/mdx +…
Adebesin-Cell May 8, 2026
3de4122
feat(playground): scaffold filename header
Adebesin-Cell May 8, 2026
fa5c90b
feat(playground): add mark annotation handler
Adebesin-Cell May 8, 2026
c997228
feat(playground): add callout annotation handler
Adebesin-Cell May 8, 2026
d2da339
feat(playground): add focus annotation handler
Adebesin-Cell May 8, 2026
91d9da5
feat(playground): add link annotation handler
Adebesin-Cell May 8, 2026
55730c5
feat(playground): add fold annotation handler
Adebesin-Cell May 8, 2026
be923e3
feat(playground): add line-numbers annotation handler
Adebesin-Cell May 8, 2026
4aac591
feat(playground): export annotation handlers from barrel
Adebesin-Cell May 8, 2026
77ee713
feat(playground): wire <Code> RSC with Code Hike highlight + theme
Adebesin-Cell May 8, 2026
8d90418
refactor(playground): restructure sidebar nav and apply design nits
Adebesin-Cell May 8, 2026
5fad482
feat(playground): add shadcn dropdown-menu primitive
Adebesin-Cell May 8, 2026
c33109c
feat(playground): add locale switcher
Adebesin-Cell May 8, 2026
678d9cf
feat(playground): add shadcn badge primitive
Adebesin-Cell May 8, 2026
dc3cdd1
feat(playground): add TwoColumn MDX layout
Adebesin-Cell May 8, 2026
a8e8837
feat(playground): add DemoCard wrapper
Adebesin-Cell May 8, 2026
d324958
refactor(playground): tighten GitHubLink markup
Adebesin-Cell May 8, 2026
152f45b
refactor(playground): point Byline source link at next-intl repo
Adebesin-Cell May 8, 2026
87bb90c
feat(playground): add MDX content for Server Components page
Adebesin-Cell May 8, 2026
054351a
feat(playground): rewrite Server Components live demo
Adebesin-Cell May 8, 2026
96019f3
feat(playground): wire Server Components page shell
Adebesin-Cell May 8, 2026
2f729ca
docs(playground): slim Server Components README to a pointer
Adebesin-Cell May 8, 2026
b922b42
feat(playground): add MDX content for Client Components page
Adebesin-Cell May 8, 2026
d1ecd8e
feat(playground): rewrite Client Components live demo
Adebesin-Cell May 8, 2026
69f8b54
feat(playground): wire Client Components page shell
Adebesin-Cell May 8, 2026
e0ca0cf
docs(playground): slim Client Components README to a pointer
Adebesin-Cell May 8, 2026
122c8dc
feat(playground): localize landing page and hide empty categories
Adebesin-Cell May 8, 2026
e53baae
test(playground): add Playwright smoke tests + docs + lint cleanup
Adebesin-Cell May 8, 2026
8fe1b94
style(playground): proper page hierarchy, MDX prose, tighter chrome
Adebesin-Cell May 8, 2026
6024bc0
fix(playground): use getTranslations in server components + boundary …
Adebesin-Cell May 8, 2026
c169a34
style(playground): refine layout polish — sidebar icons + dotgrid out…
Adebesin-Cell May 8, 2026
31044e0
feat(playground): make sidebar Playground header a link to home
Adebesin-Cell May 8, 2026
165037b
fix(playground): mobile responsiveness — viewport padding, single-col…
Adebesin-Cell May 8, 2026
c66b795
chore(playground): bump next to 15.5.15 (patches CVE-2025-66478)
Adebesin-Cell May 8, 2026
b28d1e5
chore(playground): gitignore local screenshots dir
Adebesin-Cell May 8, 2026
70fc563
Merge remote-tracking branch 'upstream/main' into docs/refactor-playg…
Adebesin-Cell May 8, 2026
7602243
chore: remove superseded implementation plan
Adebesin-Cell May 8, 2026
a14f68f
Merge branch 'main' into docs/refactor-playground
Adebesin-Cell May 13, 2026
557f5c9
refactor(playground): move into example-app-router-patterns, address …
Adebesin-Cell May 29, 2026
2c8467a
fix(playground): encode dynamic segments in GitHub source links
Adebesin-Cell May 29, 2026
4702b44
Merge remote-tracking branch 'upstream/main' into docs/refactor-playg…
Adebesin-Cell May 29, 2026
166be1a
Merge remote-tracking branch 'upstream/main' into docs/refactor-playg…
Adebesin-Cell Jun 16, 2026
29c384f
refactor(example-app-router-patterns): address review feedback
Adebesin-Cell Jun 16, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions examples/example-app-router-patterns/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/node_modules
/.next/
.DS_Store
tsconfig.tsbuildinfo
9 changes: 9 additions & 0 deletions examples/example-app-router-patterns/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# example-app-router-patterns

This example demonstrates various use cases and patterns for using `next-intl` with the App Router.

## Deploy your own

By deploying to [Vercel](https://vercel.com), you can check out the example in action. Note that you'll be prompted to create a new GitHub repository as part of this, allowing you to make subsequent changes.

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/amannn/next-intl/tree/main/examples/example-app-router-patterns)
22 changes: 22 additions & 0 deletions examples/example-app-router-patterns/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {dirname} from 'path';
import {fileURLToPath} from 'url';
import {FlatCompat} from '@eslint/eslintrc';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const compat = new FlatCompat({
baseDirectory: __dirname
});

const eslintConfig = [
...compat.extends('next/core-web-vitals', 'next/typescript'),
{
rules: {
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-ts-comment': 'off'
}
}
];

export default eslintConfig;
136 changes: 136 additions & 0 deletions examples/example-app-router-patterns/messages/de.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
msgid ""
msgstr ""
"Language: de\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: next-intl\n"
"X-Crowdin-SourceKey: msgstr\n"

#: src/app/[locale]/page.tsx
#: src/app/[locale]/translations/client-components/page.tsx
#: src/app/[locale]/translations/server-components/page.tsx
#: src/components/PlaygroundSidebar.tsx
msgid "aFyu8N"
msgstr "Übersetzungen"

#: src/app/[locale]/page.tsx
#: src/app/[locale]/translations/server-components/page.tsx
#: src/components/PlaygroundSidebar.tsx
msgid "Jm_gm4"
msgstr "Server-Komponenten"

#: src/app/[locale]/page.tsx
msgid "kka9Id"
msgstr "Übersetzte Strings in Server-Komponenten lesen."

#: src/app/[locale]/page.tsx
#: src/app/[locale]/translations/client-components/page.tsx
#: src/components/PlaygroundSidebar.tsx
msgid "qwpdfx"
msgstr "Client-Komponenten"

#: src/app/[locale]/page.tsx
msgid "5oEQPR"
msgstr "Übersetzungen in interaktiven Client-Komponenten nutzen."

#: src/app/[locale]/page.tsx
msgid "k2qvag"
msgstr "next-intl Playground"

#: src/app/[locale]/page.tsx
msgid "zllk1P"
msgstr "Übersetzungen, Formatierung, Routing und Patterns mit Next.js."

#: src/app/[locale]/page.tsx
msgid "CxfKLC"
msgstr "Seiten"

#: src/app/[locale]/translations/client-components/ClientExample.tsx
msgid "vlKhIl"
msgstr "Dein Name"

#: src/app/[locale]/translations/client-components/ClientExample.tsx
msgid "nCfqYd"
msgstr "Frodo"

#: src/app/[locale]/translations/client-components/ClientExample.tsx
msgid "tBFOH1"
msgstr "Hallo, {name}!"

#: src/app/[locale]/translations/client-components/page.tsx
msgid "3L0BvJ"
msgstr "useTranslations kann in Client-Komponenten aufgerufen werden, um clientseitigen State einzubeziehen."

#: src/app/[locale]/translations/client-components/page.tsx
msgid "3mdXe-"
msgstr "ICU-Argumente wie '{name}' werden im Browser aufgelöst, wenn sich der State ändert."

#: src/app/[locale]/translations/client-components/page.tsx
#: src/app/[locale]/translations/server-components/page.tsx
msgid "h2vipu"
msgstr "Code"

#: src/app/[locale]/translations/client-components/page.tsx
#: src/app/[locale]/translations/server-components/page.tsx
msgid "fio5op"
msgstr "Ausgabe"

#: src/app/[locale]/translations/server-components/page.tsx
msgid "n5Juxa"
msgstr "Nachrichten bleiben auf dem Server, es wird also keine Übersetzungs-Runtime an den Client ausgeliefert."

#: src/app/[locale]/translations/server-components/page.tsx
msgid "fZd-wY"
msgstr "Async-Komponenten"

#: src/app/[locale]/translations/server-components/page.tsx
msgid "4-bDMC"
msgstr "In async Server-Komponenten getTranslations awaiten, um Nachrichten zu lesen."

#: src/app/[locale]/translations/server-components/page.tsx
msgid "xh8Irc"
msgstr "Nicht-async-Komponenten"

#: src/app/[locale]/translations/server-components/page.tsx
msgid "OLpN6c"
msgstr "In nicht-async Server-Komponenten useTranslations direkt aufrufen — kein await nötig."

#: src/app/[locale]/translations/server-components/ServerExample.tsx
msgid "wVJ82J"
msgstr "Hallo, Welt!"

#: src/components/GitHubLink.tsx
msgid "80g19N"
msgstr "Auf GitHub ansehen"

#: src/components/LocaleSwitcher.tsx
msgid "dISpGP"
msgstr "Sprache wechseln"

#: src/components/PlaygroundByline.tsx
msgid "GAUX9p"
msgstr "Quellcode"

#: src/components/PlaygroundByline.tsx
msgid "_6_sPX"
msgstr "Dokumentation"

#: src/components/PlaygroundSidebar.tsx
msgid "XqRXu6"
msgstr "Playground"

#: src/components/PlaygroundSidebar.tsx
msgid "SRsuWF"
msgstr "Navigation schließen"

#: src/components/PlaygroundSidebar.tsx
msgid "oM3yjO"
msgstr "Navigation öffnen"

#: src/components/ThemeToggle.tsx
msgid "dLFYnK"
msgstr "Zum hellen Design wechseln"

#: src/components/ThemeToggle.tsx
msgid "sDxHcF"
msgstr "Zum dunklen Design wechseln"
136 changes: 136 additions & 0 deletions examples/example-app-router-patterns/messages/en.po
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
msgid ""
msgstr ""
"Language: en\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"X-Generator: next-intl\n"
"X-Crowdin-SourceKey: msgstr\n"

#: src/app/[locale]/page.tsx
#: src/app/[locale]/translations/client-components/page.tsx
#: src/app/[locale]/translations/server-components/page.tsx
#: src/components/PlaygroundSidebar.tsx
msgid "aFyu8N"
msgstr "Translations"

#: src/app/[locale]/page.tsx
#: src/app/[locale]/translations/server-components/page.tsx
#: src/components/PlaygroundSidebar.tsx
msgid "Jm_gm4"
msgstr "Server Components"

#: src/app/[locale]/page.tsx
msgid "kka9Id"
msgstr "Read translated strings inside Server Components."

#: src/app/[locale]/page.tsx
#: src/app/[locale]/translations/client-components/page.tsx
#: src/components/PlaygroundSidebar.tsx
msgid "qwpdfx"
msgstr "Client Components"

#: src/app/[locale]/page.tsx
msgid "5oEQPR"
msgstr "Use translations in interactive Client Components."

#: src/app/[locale]/page.tsx
msgid "k2qvag"
msgstr "next-intl playground"

#: src/app/[locale]/page.tsx
msgid "zllk1P"
msgstr "Translations, formatting, routing and patterns with Next.js."

#: src/app/[locale]/page.tsx
msgid "CxfKLC"
msgstr "Pages"

#: src/app/[locale]/translations/client-components/ClientExample.tsx
msgid "vlKhIl"
msgstr "Your name"

#: src/app/[locale]/translations/client-components/ClientExample.tsx
msgid "nCfqYd"
msgstr "Frodo"

#: src/app/[locale]/translations/client-components/ClientExample.tsx
msgid "tBFOH1"
msgstr "Hello, {name}!"

#: src/app/[locale]/translations/client-components/page.tsx
msgid "3L0BvJ"
msgstr "useTranslations can be called in Client Components to incorporate client-side state."

#: src/app/[locale]/translations/client-components/page.tsx
msgid "3mdXe-"
msgstr "ICU arguments like '{name}' are resolved in the browser as state changes."

#: src/app/[locale]/translations/client-components/page.tsx
#: src/app/[locale]/translations/server-components/page.tsx
msgid "h2vipu"
msgstr "Code"

#: src/app/[locale]/translations/client-components/page.tsx
#: src/app/[locale]/translations/server-components/page.tsx
msgid "fio5op"
msgstr "Output"

#: src/app/[locale]/translations/server-components/page.tsx
msgid "n5Juxa"
msgstr "Messages stay on the server, so no translation runtime is shipped to the client."

#: src/app/[locale]/translations/server-components/page.tsx
msgid "fZd-wY"
msgstr "Async components"

#: src/app/[locale]/translations/server-components/page.tsx
msgid "4-bDMC"
msgstr "In async Server Components, await getTranslations to read messages."

#: src/app/[locale]/translations/server-components/page.tsx
msgid "xh8Irc"
msgstr "Non-async components"

#: src/app/[locale]/translations/server-components/page.tsx
msgid "OLpN6c"
msgstr "In non-async Server Components, call useTranslations directly — no await needed."

#: src/app/[locale]/translations/server-components/ServerExample.tsx
msgid "wVJ82J"
msgstr "Hello, world!"

#: src/components/GitHubLink.tsx
msgid "80g19N"
msgstr "View on GitHub"

#: src/components/LocaleSwitcher.tsx
msgid "dISpGP"
msgstr "Switch language"

#: src/components/PlaygroundByline.tsx
msgid "GAUX9p"
msgstr "Source code"

#: src/components/PlaygroundByline.tsx
msgid "_6_sPX"
msgstr "Docs"

#: src/components/PlaygroundSidebar.tsx
msgid "XqRXu6"
msgstr "Playground"

#: src/components/PlaygroundSidebar.tsx
msgid "SRsuWF"
msgstr "Close navigation"

#: src/components/PlaygroundSidebar.tsx
msgid "oM3yjO"
msgstr "Open navigation"

#: src/components/ThemeToggle.tsx
msgid "dLFYnK"
msgstr "Switch to light theme"

#: src/components/ThemeToggle.tsx
msgid "sDxHcF"
msgstr "Switch to dark theme"
6 changes: 6 additions & 0 deletions examples/example-app-router-patterns/next-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference path="./.next/types/routes.d.ts" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
21 changes: 21 additions & 0 deletions examples/example-app-router-patterns/next.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import createNextIntlPlugin from 'next-intl/plugin';

const withNextIntl = createNextIntlPlugin({
requestConfig: './src/i18n/request.ts',
experimental: {
extract: true,
srcPath: './src',
messages: {
path: './messages',
format: 'po',
locales: 'infer',
sourceLocale: 'en',
precompile: true
}
}
});

/** @type {import('next').NextConfig} */
const nextConfig = {};

export default withNextIntl(nextConfig);
47 changes: 47 additions & 0 deletions examples/example-app-router-patterns/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "example-app-router-patterns",
"private": true,
"scripts": {
"dev": "next dev",
"lint": "eslint src && prettier src --check",
"build": "next build",
"start": "next start"
},
"dependencies": {
"clsx": "^2.1.1",
"codehike": "^1.0.7",
"lucide-react": "^0.545.0",
"next": "^15.5.0",
"next-intl": "^4.0.0",
"next-themes": "^0.4.6",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"tailwindcss": "^4.1.12"
},
"devDependencies": {
"@eslint/eslintrc": "^3.1.0",
"@tailwindcss/postcss": "^4.1.12",
"@types/node": "^20.14.5",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"eslint": "9.11.1",
"eslint-config-next": "^15.5.0",
"postcss": "^8.5.3",
"prettier": "^3.3.3",
"prettier-plugin-organize-imports": "^4.2.0",
"prettier-plugin-tailwindcss": "^0.6.14",
"typescript": "^5.5.3"
},
"prettier": {
"singleQuote": true,
"bracketSpacing": false,
"trailingComma": "none",
"plugins": [
"prettier-plugin-organize-imports",
"prettier-plugin-tailwindcss"
]
},
"engines": {
"node": ">=20.0.0"
}
}
6 changes: 6 additions & 0 deletions examples/example-app-router-patterns/postcss.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const config = {
plugins: {
'@tailwindcss/postcss': {}
}
};
export default config;
Loading
Loading