Skip to content

Conversation

@juliomuhlbauer
Copy link
Contributor

@juliomuhlbauer juliomuhlbauer commented Sep 26, 2025

Summary by CodeRabbit

  • New Features

    • Added two React i18n examples (TanStack Router and TanStack Start) with localized routing, locale switcher, and Tailwind styling.
    • Included English/German translations, URL rewriting for localized paths, and prerender setup.
    • Added SEO utility and SSR/server middleware integration (Start example).
  • Documentation

    • New READMEs with step-by-step setup, plugin configuration, and usage examples for Paraglide integrations.
  • Chores

    • Added project configs: Vite, TypeScript, manifests, robots.txt, gitignore, and VS Code settings (ignore generated files, read-only markers).

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 26, 2025

Walkthrough

Adds three React example apps demonstrating Paraglide JS with TanStack Router and TanStack Start. Introduces scaffolding (configs, manifests, Tailwind), i18n message bundles (en/de), Vite plugins with URL localization, router wiring with input/output rewrites, route trees and components, SSR middleware, prerender config, and documentation.

Changes

Cohort / File(s) Summary
Project scaffolding & configs
examples/react/18n-paraglide/.gitignore, examples/react/18n-paraglide/.vscode/settings.json, examples/react/18n-paraglide/package.json, examples/react/18n-paraglide/tsconfig.json, examples/react/18n-paraglide/index.html, examples/react/18n-paraglide/public/*, examples/react/18n-paraglide/project.inlang/*, examples/react/18n-paraglide/src/styles.css, examples/react/i18n-paraglide/.gitignore, examples/react/i18n-paraglide/.vscode/settings.json, examples/react/i18n-paraglide/package.json, examples/react/i18n-paraglide/tsconfig.json, examples/react/i18n-paraglide/index.html, examples/react/i18n-paraglide/public/*, examples/react/i18n-paraglide/project.inlang/*, examples/react/i18n-paraglide/src/styles.css, examples/react/start-i18n-paraglide/.gitignore, examples/react/start-i18n-paraglide/.vscode/*.json, examples/react/start-i18n-paraglide/package.json, examples/react/start-i18n-paraglide/tsconfig.json, examples/react/start-i18n-paraglide/public/*, examples/react/start-i18n-paraglide/project.inlang/*, examples/react/start-i18n-paraglide/src/styles.css
Adds ignore rules, VSCode settings, package metadata, TypeScript configs, HTML entry points, PWA manifests, robots.txt, Inlang settings, and Tailwind CSS import.
Documentation
examples/react/18n-paraglide/README.md, examples/react/i18n-paraglide/README.md, examples/react/start-i18n-paraglide/README.md
New docs describing Paraglide integration with TanStack Router/Start, setup steps, URL rewrite examples, and SSR notes.
i18n message bundles
examples/react/18n-paraglide/messages/*.json, examples/react/i18n-paraglide/messages/*.json, examples/react/start-i18n-paraglide/messages/*.json
Adds en/de JSON messages conforming to Inlang schema.
SPA router wiring (React + TanStack Router)
examples/react/18n-paraglide/src/main.tsx, examples/react/18n-paraglide/src/routeTree.gen.ts, examples/react/18n-paraglide/src/routes/*, examples/react/i18n-paraglide/src/main.tsx, examples/react/i18n-paraglide/src/routeTree.gen.ts, examples/react/i18n-paraglide/src/routes/*
Creates routers with route trees, configures URL input/output rewrites (deLocalizeUrl/localizeUrl), adds root/index/about routes with beforeLoad redirect and locale handling.
SSR/Start router & utilities
examples/react/start-i18n-paraglide/src/routeTree.gen.ts, examples/react/start-i18n-paraglide/src/router.tsx, examples/react/start-i18n-paraglide/src/routes/*, examples/react/start-i18n-paraglide/src/server.ts, examples/react/start-i18n-paraglide/src/utils/prerender.ts, examples/react/start-i18n-paraglide/src/utils/seo.ts, examples/react/start-i18n-paraglide/src/utils/translated-pathnames.ts
Adds Start router factory with URL rewrites, server middleware integration, root shell document, index/about routes including server function, prerender routes, SEO meta helper, and translated pathname utilities.
Build tooling
examples/react/18n-paraglide/vite.config.ts, examples/react/i18n-paraglide/vite.config.ts, examples/react/start-i18n-paraglide/vite.config.ts
Vite configs adding Tailwind, Paraglide plugin (localization strategy, URL patterns), TanStack Router/Start plugins, and path aliases.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant B as Browser
  participant R as TanStack Router
  participant RW as Rewrite (deLocalize/localize)
  participant RT as Routes (beforeLoad)

  B->>R: Navigate to URL (/de/ueber)
  R->>RW: Input rewrite (deLocalizeUrl)
  RW-->>R: Canonical URL (/about)
  R->>RT: Match route + beforeLoad
  RT-->>R: optional redirect URL?
  alt Redirect needed
    R-->>B: Throw redirect to localized URL
  else No redirect
    R->>RW: Output rewrite (localizeUrl)
    RW-->>R: Localized URL (/de/ueber)
    R-->>B: Render route component
  end
Loading
sequenceDiagram
  autonumber
  participant C as Client
  participant S as Server Entry
  participant PM as paraglideMiddleware
  participant H as handler.fetch

  C->>S: HTTP Request (/de/ueber)
  S->>PM: fetch(req)
  PM->>H: Forward with de-localized URL (/about)
  H-->>PM: Response
  PM-->>S: Response (headers/URL localized as needed)
  S-->>C: HTTP Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

documentation

Suggested reviewers

  • schiller-manuel
  • brenelz

Poem

A hop through routes, I tweak and tune,
From de to en, I hum a rune.
I sniff the paths, then localize,
With whiskered wit and bright code eyes.
Now every link is snack-aligned—
A carrot trail, perfectly i18n’d! 🥕✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly states the primary change of adding Paraglide integration examples and directly reflects the content of the pull request without extraneous detail or ambiguity.
✨ Finishing touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Please see the documentation for more information.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 16

🧹 Nitpick comments (14)
examples/react/18n-paraglide/messages/de.json (1)

4-6: Normalize the umlaut

The string on Line 6 uses a combining diaeresis () instead of the precomposed Ü, which can render oddly and break strict string comparisons. Prefer the canonical character.

-  "about_page": "Über uns"
+  "about_page": "Über uns"
examples/react/start-i18n-paraglide/README.md (1)

1-1: Docs polish: typos, tabs, and lint fixes

  • Line 1: “TanSTack” → “TanStack”.
  • Line 3 (MD059): Replace “here” with descriptive link text.
  • Lines 22, 25–27, 39–40 (MD010): Replace hard tabs with spaces.
  • Line 79: “add change the” → “change the”.
  • Line 181: “plguin” → “plugin”.
  • Consistency: Prefer including .js extension in ESM imports in snippets (e.g., localizeHref/shouldRedirect).

Apply this minimal diff to address key issues:

-# TanSTack Start example
+# TanStack Start example

-This example shows how to use Paraglide with TanStack Start. The source code can be found [here](https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-js/examples/tanstack-start).
+This example shows how to use Paraglide with TanStack Start. See the source code in the Paraglide + TanStack Start example repository: https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-js/examples/tanstack-start

-	plugins: [
+  plugins: [
     tanstackStart(),
     react(),
-		paraglideVitePlugin({
-			project: "./project.inlang",
-			outdir: "./app/paraglide",
+    paraglideVitePlugin({
+      project: "./project.inlang",
+      outdir: "./app/paraglide",
       outputStructure: "message-modules",
       cookieName: "PARAGLIDE_LOCALE",
       strategy: ["url", "cookie", "preferredLanguage", "baseLocale"],
       urlPatterns: [
        {
          pattern: "/:path(.*)?",
          localized: [
            ["en", "/en/:path(.*)?"],
          ],
        },
       ],
-		}),
-	],
+    }),
+  ],
 });

-In `__root.tsx` add change the html lang attribute to the current locale.
+In `__root.tsx`, change the html lang attribute to the current locale.

-import { shouldRedirect } from "../paraglide/runtime";
+import { shouldRedirect } from "../paraglide/runtime.js";

-And import into the Paraglide Vite plguin.
+And import into the Paraglide Vite plugin.

Also applies to: 3-3, 22-22, 25-27, 39-40, 79-79, 181-181

examples/react/start-i18n-paraglide/src/utils/prerender.ts (1)

1-8: Consider adding type safety for route paths.

While the implementation is correct, consider defining route paths as constants or using a type-safe approach to prevent typos and ensure consistency with the actual routes.

 import { localizeHref } from "../paraglide/runtime";
 
-export const prerenderRoutes = ["/", "/about"].map((path) => ({
+const PRERENDERABLE_PATHS = ["/", "/about"] as const;
+
+export const prerenderRoutes = PRERENDERABLE_PATHS.map((path) => ({
   path: localizeHref(path),
   prerender: {
     enabled: true,
   },
 }));

This approach provides better maintainability and makes it easier to track which routes are prerendered.

examples/react/18n-paraglide/src/routes/__root.tsx (2)

16-24: Consider error handling for the redirect logic.

The beforeLoad hook throws a redirect but doesn't handle potential errors from shouldRedirect. Consider wrapping in a try-catch for robustness.

   beforeLoad: async () => {
     document.documentElement.setAttribute("lang", getLocale());
 
-    const decision = await shouldRedirect({ url: window.location.href });
-
-    if (decision.redirectUrl) {
-      throw redirect({ href: decision.redirectUrl.href });
+    try {
+      const decision = await shouldRedirect({ url: window.location.href });
+
+      if (decision.redirectUrl) {
+        throw redirect({ href: decision.redirectUrl.href });
+      }
+    } catch (error) {
+      // If it's a redirect, re-throw it
+      if (error && typeof error === 'object' && 'href' in error) {
+        throw error;
+      }
+      // Log other errors but don't block navigation
+      console.error('Error checking redirect:', error);
     }
   },

50-59: Consider adding ARIA labels for better accessibility.

The locale switcher buttons should have ARIA labels to improve screen reader support.

           {locales.map((locale) => (
             <button
               key={locale}
               onClick={() => setLocale(locale)}
               data-active-locale={locale === getLocale()}
+              aria-label={`Switch to ${locale} language`}
+              aria-pressed={locale === getLocale()}
               className="rounded p-1 px-2 border border-gray-300 cursor-pointer [&[data-active-locale=true]]:bg-gray-500 [&[data-active-locale=true]]:text-white"
             >
               {locale}
             </button>
           ))}
examples/react/start-i18n-paraglide/vite.config.ts (2)

9-37: Load tsconfig paths plugin first.

Put viteTsConfigPaths() at the start so path resolution is available to subsequent plugins during their config and transform hooks.

Apply this diff:

   plugins: [
-    paraglideVitePlugin({
+    viteTsConfigPaths(),
+    paraglideVitePlugin({
       project: "./project.inlang",
@@
-    viteTsConfigPaths(),
     tanstackStart(),
     viteReact(),
     tailwindcss(),
   ],

10-31: Optional: Add explicit root pattern for clarity.

Your catch-all will cover “/”, but adding an explicit root mapping makes intent clearer and avoids edge cases.

Apply this diff:

       urlPatterns: [
+        {
+          pattern: "/",
+          localized: [
+            ["en", "/en"],
+            ["de", "/de"],
+          ],
+        },
         {
           pattern: "/about",
examples/react/i18n-paraglide/src/main.tsx (1)

31-39: Hydrate when SSR markup exists; create root otherwise.

Prevents a non-interactive page if markup was server-rendered.

Apply this diff:

-const rootElement = document.getElementById("app");
-if (rootElement && !rootElement.innerHTML) {
-  const root = ReactDOM.createRoot(rootElement);
-  root.render(
-    <StrictMode>
-      <RouterProvider router={router} />
-    </StrictMode>
-  );
-}
+const rootElement = document.getElementById("app");
+if (rootElement) {
+  const app = (
+    <StrictMode>
+      <RouterProvider router={router} />
+    </StrictMode>
+  );
+  if (rootElement.innerHTML) {
+    ReactDOM.hydrateRoot(rootElement, app);
+  } else {
+    ReactDOM.createRoot(rootElement).render(app);
+  }
+}
examples/react/18n-paraglide/vite.config.ts (1)

4-4: Same ESM-safe alias fix applies here.

Avoid __dirname in ESM contexts; use fileURLToPath.

Apply this diff:

-import { resolve } from "node:path";
+import { dirname, resolve } from "node:path";
+import { fileURLToPath } from "node:url";
@@
-export default defineConfig({
+const __dirname = dirname(fileURLToPath(import.meta.url));
+export default defineConfig({
@@
-      "@": resolve(__dirname, "./src"),
+      "@": resolve(__dirname, "src"),

Also applies to: 45-47

examples/react/start-i18n-paraglide/src/routes/__root.tsx (2)

80-90: Gate devtools to development builds.

Avoid shipping devtools in production.

Apply this diff:

-        <TanstackDevtools
-          config={{
-            position: "bottom-left",
-          }}
-          plugins={[
-            {
-              name: "Tanstack Router",
-              render: <TanStackRouterDevtoolsPanel />,
-            },
-          ]}
-        />
+        {import.meta.env.DEV && (
+          <TanstackDevtools
+            config={{ position: "bottom-left" }}
+            plugins={[
+              {
+                name: "Tanstack Router",
+                render: <TanStackRouterDevtoolsPanel />,
+              },
+            ]}
+          />
+        )}

63-71: Improve a11y on locale toggle buttons.

Expose state with aria-pressed and add an accessible label.

Apply this diff:

-            <button
+            <button
               key={locale}
               onClick={() => setLocale(locale)}
               data-active-locale={locale === getLocale()}
-              className="rounded p-1 px-2 border border-gray-300 cursor-pointer [&[data-active-locale=true]]:bg-gray-500 [&[data-active-locale=true]]:text-white"
+              aria-pressed={locale === getLocale()}
+              aria-label={`Switch language to ${locale}`}
+              className="rounded p-1 px-2 border border-gray-300 cursor-pointer [&[data-active-locale=true]]:bg-gray-500 [&[data-active-locale=true]]:text-white"
             >
               {locale}
             </button>
examples/react/i18n-paraglide/src/routes/__root.tsx (2)

16-24: Ensure proper async handling in beforeLoad.

The implementation correctly handles the redirect decision, but consider adding error handling for the shouldRedirect call.

Consider adding error handling:

 beforeLoad: async () => {
   document.documentElement.setAttribute("lang", getLocale());

-  const decision = await shouldRedirect({ url: window.location.href });
-
-  if (decision.redirectUrl) {
-    throw redirect({ href: decision.redirectUrl.href });
+  try {
+    const decision = await shouldRedirect({ url: window.location.href });
+    
+    if (decision.redirectUrl) {
+      throw redirect({ href: decision.redirectUrl.href });
+    }
+  } catch (error) {
+    // Only rethrow if it's a redirect, otherwise log and continue
+    if (error instanceof redirect) {
+      throw error;
+    }
+    console.error('Failed to check redirect decision:', error);
   }
 },

50-60: Consider accessibility improvements for locale switcher.

The locale switcher buttons should have aria-labels for better screen reader support and keyboard navigation improvements.

Add accessibility attributes:

 {locales.map((locale) => (
   <button
     key={locale}
     onClick={() => setLocale(locale)}
     data-active-locale={locale === getLocale()}
+    aria-label={`Switch language to ${locale}`}
+    aria-pressed={locale === getLocale()}
     className="rounded p-1 px-2 border border-gray-300 cursor-pointer [&[data-active-locale=true]]:bg-gray-500 [&[data-active-locale=true]]:text-white"
   >
     {locale}
   </button>
 ))}
examples/react/start-i18n-paraglide/src/routes/index.tsx (1)

6-10: Use Zod for emoji validation
Leverage a Zod schema in the inputValidator for composable, reusable validation:

import { z } from 'zod';

const getServerMessage = createServerFn()
  .inputValidator(z.string().regex(/^\p{Emoji}+$/u, 'Invalid emoji'))
  .handler(ctx => m.server_message({ emoji: ctx.data }));
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0babe5d and 30a2d66.

⛔ Files ignored due to path filters (12)
  • examples/react/18n-paraglide/public/favicon.ico is excluded by !**/*.ico
  • examples/react/18n-paraglide/public/logo192.png is excluded by !**/*.png
  • examples/react/18n-paraglide/public/logo512.png is excluded by !**/*.png
  • examples/react/18n-paraglide/src/logo.svg is excluded by !**/*.svg
  • examples/react/i18n-paraglide/public/favicon.ico is excluded by !**/*.ico
  • examples/react/i18n-paraglide/public/logo192.png is excluded by !**/*.png
  • examples/react/i18n-paraglide/public/logo512.png is excluded by !**/*.png
  • examples/react/i18n-paraglide/src/logo.svg is excluded by !**/*.svg
  • examples/react/start-i18n-paraglide/public/favicon.ico is excluded by !**/*.ico
  • examples/react/start-i18n-paraglide/public/logo192.png is excluded by !**/*.png
  • examples/react/start-i18n-paraglide/public/logo512.png is excluded by !**/*.png
  • examples/react/start-i18n-paraglide/src/logo.svg is excluded by !**/*.svg
📒 Files selected for processing (64)
  • examples/react/18n-paraglide/.gitignore (1 hunks)
  • examples/react/18n-paraglide/.vscode/settings.json (1 hunks)
  • examples/react/18n-paraglide/README.md (1 hunks)
  • examples/react/18n-paraglide/index.html (1 hunks)
  • examples/react/18n-paraglide/messages/de.json (1 hunks)
  • examples/react/18n-paraglide/messages/en.json (1 hunks)
  • examples/react/18n-paraglide/package.json (1 hunks)
  • examples/react/18n-paraglide/project.inlang/.gitignore (1 hunks)
  • examples/react/18n-paraglide/project.inlang/project_id (1 hunks)
  • examples/react/18n-paraglide/project.inlang/settings.json (1 hunks)
  • examples/react/18n-paraglide/public/manifest.json (1 hunks)
  • examples/react/18n-paraglide/public/robots.txt (1 hunks)
  • examples/react/18n-paraglide/src/main.tsx (1 hunks)
  • examples/react/18n-paraglide/src/routeTree.gen.ts (1 hunks)
  • examples/react/18n-paraglide/src/routes/__root.tsx (1 hunks)
  • examples/react/18n-paraglide/src/routes/about.tsx (1 hunks)
  • examples/react/18n-paraglide/src/routes/index.tsx (1 hunks)
  • examples/react/18n-paraglide/src/styles.css (1 hunks)
  • examples/react/18n-paraglide/tsconfig.json (1 hunks)
  • examples/react/18n-paraglide/vite.config.ts (1 hunks)
  • examples/react/i18n-paraglide/.gitignore (1 hunks)
  • examples/react/i18n-paraglide/.vscode/settings.json (1 hunks)
  • examples/react/i18n-paraglide/README.md (1 hunks)
  • examples/react/i18n-paraglide/index.html (1 hunks)
  • examples/react/i18n-paraglide/messages/de.json (1 hunks)
  • examples/react/i18n-paraglide/messages/en.json (1 hunks)
  • examples/react/i18n-paraglide/package.json (1 hunks)
  • examples/react/i18n-paraglide/project.inlang/.gitignore (1 hunks)
  • examples/react/i18n-paraglide/project.inlang/project_id (1 hunks)
  • examples/react/i18n-paraglide/project.inlang/settings.json (1 hunks)
  • examples/react/i18n-paraglide/public/manifest.json (1 hunks)
  • examples/react/i18n-paraglide/public/robots.txt (1 hunks)
  • examples/react/i18n-paraglide/src/main.tsx (1 hunks)
  • examples/react/i18n-paraglide/src/routeTree.gen.ts (1 hunks)
  • examples/react/i18n-paraglide/src/routes/__root.tsx (1 hunks)
  • examples/react/i18n-paraglide/src/routes/about.tsx (1 hunks)
  • examples/react/i18n-paraglide/src/routes/index.tsx (1 hunks)
  • examples/react/i18n-paraglide/src/styles.css (1 hunks)
  • examples/react/i18n-paraglide/tsconfig.json (1 hunks)
  • examples/react/i18n-paraglide/vite.config.ts (1 hunks)
  • examples/react/start-i18n-paraglide/.gitignore (1 hunks)
  • examples/react/start-i18n-paraglide/.vscode/extensions.json (1 hunks)
  • examples/react/start-i18n-paraglide/.vscode/settings.json (1 hunks)
  • examples/react/start-i18n-paraglide/README.md (1 hunks)
  • examples/react/start-i18n-paraglide/messages/de.json (1 hunks)
  • examples/react/start-i18n-paraglide/messages/en.json (1 hunks)
  • examples/react/start-i18n-paraglide/package.json (1 hunks)
  • examples/react/start-i18n-paraglide/project.inlang/.gitignore (1 hunks)
  • examples/react/start-i18n-paraglide/project.inlang/project_id (1 hunks)
  • examples/react/start-i18n-paraglide/project.inlang/settings.json (1 hunks)
  • examples/react/start-i18n-paraglide/public/manifest.json (1 hunks)
  • examples/react/start-i18n-paraglide/public/robots.txt (1 hunks)
  • examples/react/start-i18n-paraglide/src/routeTree.gen.ts (1 hunks)
  • examples/react/start-i18n-paraglide/src/router.tsx (1 hunks)
  • examples/react/start-i18n-paraglide/src/routes/__root.tsx (1 hunks)
  • examples/react/start-i18n-paraglide/src/routes/about.tsx (1 hunks)
  • examples/react/start-i18n-paraglide/src/routes/index.tsx (1 hunks)
  • examples/react/start-i18n-paraglide/src/server.ts (1 hunks)
  • examples/react/start-i18n-paraglide/src/styles.css (1 hunks)
  • examples/react/start-i18n-paraglide/src/utils/prerender.ts (1 hunks)
  • examples/react/start-i18n-paraglide/src/utils/seo.ts (1 hunks)
  • examples/react/start-i18n-paraglide/src/utils/translated-pathnames.ts (1 hunks)
  • examples/react/start-i18n-paraglide/tsconfig.json (1 hunks)
  • examples/react/start-i18n-paraglide/vite.config.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
examples/{react,solid}/**

📄 CodeRabbit inference engine (AGENTS.md)

Keep example applications under examples/react/ and examples/solid/

Files:

  • examples/react/18n-paraglide/index.html
  • examples/react/18n-paraglide/project.inlang/settings.json
  • examples/react/start-i18n-paraglide/public/manifest.json
  • examples/react/18n-paraglide/src/styles.css
  • examples/react/18n-paraglide/messages/en.json
  • examples/react/i18n-paraglide/tsconfig.json
  • examples/react/start-i18n-paraglide/tsconfig.json
  • examples/react/18n-paraglide/project.inlang/project_id
  • examples/react/i18n-paraglide/messages/en.json
  • examples/react/start-i18n-paraglide/project.inlang/project_id
  • examples/react/18n-paraglide/vite.config.ts
  • examples/react/i18n-paraglide/project.inlang/project_id
  • examples/react/18n-paraglide/public/robots.txt
  • examples/react/i18n-paraglide/src/routeTree.gen.ts
  • examples/react/start-i18n-paraglide/project.inlang/settings.json
  • examples/react/start-i18n-paraglide/src/utils/prerender.ts
  • examples/react/18n-paraglide/tsconfig.json
  • examples/react/18n-paraglide/src/main.tsx
  • examples/react/start-i18n-paraglide/vite.config.ts
  • examples/react/start-i18n-paraglide/messages/en.json
  • examples/react/i18n-paraglide/public/manifest.json
  • examples/react/18n-paraglide/src/routes/about.tsx
  • examples/react/18n-paraglide/src/routes/__root.tsx
  • examples/react/start-i18n-paraglide/src/utils/translated-pathnames.ts
  • examples/react/i18n-paraglide/src/routes/index.tsx
  • examples/react/18n-paraglide/public/manifest.json
  • examples/react/i18n-paraglide/messages/de.json
  • examples/react/18n-paraglide/src/routes/index.tsx
  • examples/react/i18n-paraglide/project.inlang/settings.json
  • examples/react/start-i18n-paraglide/src/server.ts
  • examples/react/i18n-paraglide/public/robots.txt
  • examples/react/start-i18n-paraglide/public/robots.txt
  • examples/react/start-i18n-paraglide/src/styles.css
  • examples/react/18n-paraglide/messages/de.json
  • examples/react/start-i18n-paraglide/src/routes/about.tsx
  • examples/react/18n-paraglide/README.md
  • examples/react/i18n-paraglide/src/styles.css
  • examples/react/18n-paraglide/package.json
  • examples/react/i18n-paraglide/package.json
  • examples/react/start-i18n-paraglide/src/router.tsx
  • examples/react/start-i18n-paraglide/README.md
  • examples/react/i18n-paraglide/index.html
  • examples/react/18n-paraglide/src/routeTree.gen.ts
  • examples/react/i18n-paraglide/README.md
  • examples/react/i18n-paraglide/vite.config.ts
  • examples/react/start-i18n-paraglide/package.json
  • examples/react/start-i18n-paraglide/src/utils/seo.ts
  • examples/react/start-i18n-paraglide/src/routes/index.tsx
  • examples/react/i18n-paraglide/src/main.tsx
  • examples/react/start-i18n-paraglide/src/routes/__root.tsx
  • examples/react/start-i18n-paraglide/src/routeTree.gen.ts
  • examples/react/start-i18n-paraglide/messages/de.json
  • examples/react/i18n-paraglide/src/routes/about.tsx
  • examples/react/i18n-paraglide/src/routes/__root.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Use TypeScript in strict mode with extensive type safety across the codebase

Files:

  • examples/react/18n-paraglide/vite.config.ts
  • examples/react/i18n-paraglide/src/routeTree.gen.ts
  • examples/react/start-i18n-paraglide/src/utils/prerender.ts
  • examples/react/18n-paraglide/src/main.tsx
  • examples/react/start-i18n-paraglide/vite.config.ts
  • examples/react/18n-paraglide/src/routes/about.tsx
  • examples/react/18n-paraglide/src/routes/__root.tsx
  • examples/react/start-i18n-paraglide/src/utils/translated-pathnames.ts
  • examples/react/i18n-paraglide/src/routes/index.tsx
  • examples/react/18n-paraglide/src/routes/index.tsx
  • examples/react/start-i18n-paraglide/src/server.ts
  • examples/react/start-i18n-paraglide/src/routes/about.tsx
  • examples/react/start-i18n-paraglide/src/router.tsx
  • examples/react/18n-paraglide/src/routeTree.gen.ts
  • examples/react/i18n-paraglide/vite.config.ts
  • examples/react/start-i18n-paraglide/src/utils/seo.ts
  • examples/react/start-i18n-paraglide/src/routes/index.tsx
  • examples/react/i18n-paraglide/src/main.tsx
  • examples/react/start-i18n-paraglide/src/routes/__root.tsx
  • examples/react/start-i18n-paraglide/src/routeTree.gen.ts
  • examples/react/i18n-paraglide/src/routes/about.tsx
  • examples/react/i18n-paraglide/src/routes/__root.tsx
**/src/routes/**

📄 CodeRabbit inference engine (AGENTS.md)

Place file-based routes under src/routes/ directories

Files:

  • examples/react/18n-paraglide/src/routes/about.tsx
  • examples/react/18n-paraglide/src/routes/__root.tsx
  • examples/react/i18n-paraglide/src/routes/index.tsx
  • examples/react/18n-paraglide/src/routes/index.tsx
  • examples/react/start-i18n-paraglide/src/routes/about.tsx
  • examples/react/start-i18n-paraglide/src/routes/index.tsx
  • examples/react/start-i18n-paraglide/src/routes/__root.tsx
  • examples/react/i18n-paraglide/src/routes/about.tsx
  • examples/react/i18n-paraglide/src/routes/__root.tsx
**/package.json

📄 CodeRabbit inference engine (AGENTS.md)

Use workspace:* protocol for internal dependencies in package.json files

Files:

  • examples/react/18n-paraglide/package.json
  • examples/react/i18n-paraglide/package.json
  • examples/react/start-i18n-paraglide/package.json
🧠 Learnings (2)
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript in strict mode with extensive type safety across the codebase

Applied to files:

  • examples/react/i18n-paraglide/tsconfig.json
  • examples/react/start-i18n-paraglide/tsconfig.json
  • examples/react/18n-paraglide/tsconfig.json
📚 Learning: 2025-09-23T17:36:12.598Z
Learnt from: CR
PR: TanStack/router#0
File: AGENTS.md:0-0
Timestamp: 2025-09-23T17:36:12.598Z
Learning: Applies to packages/{react-router,solid-router}/** : Implement React and Solid bindings/components only in packages/react-router/ and packages/solid-router/

Applied to files:

  • examples/react/18n-paraglide/src/main.tsx
  • examples/react/18n-paraglide/src/routes/__root.tsx
  • examples/react/i18n-paraglide/src/main.tsx
  • examples/react/start-i18n-paraglide/src/routes/__root.tsx
  • examples/react/i18n-paraglide/src/routes/__root.tsx
🧬 Code graph analysis (15)
examples/react/18n-paraglide/src/main.tsx (1)
e2e/react-router/js-only-file-based/src/main.jsx (2)
  • rootElement (15-15)
  • root (18-18)
examples/react/18n-paraglide/src/routes/about.tsx (2)
examples/react/18n-paraglide/src/routes/__root.tsx (1)
  • Route (15-70)
examples/react/18n-paraglide/src/routes/index.tsx (1)
  • Route (4-6)
examples/react/18n-paraglide/src/routes/__root.tsx (1)
examples/react/i18n-paraglide/src/routes/__root.tsx (1)
  • Route (15-70)
examples/react/start-i18n-paraglide/src/utils/translated-pathnames.ts (1)
examples/react/start-i18n-paraglide/src/routeTree.gen.ts (1)
  • FileRoutesByTo (30-33)
examples/react/i18n-paraglide/src/routes/index.tsx (3)
examples/react/i18n-paraglide/src/routes/__root.tsx (1)
  • Route (15-70)
examples/react/i18n-paraglide/src/routes/about.tsx (1)
  • Route (4-6)
examples/react/start-i18n-paraglide/src/routes/index.tsx (1)
  • Route (12-21)
examples/react/18n-paraglide/src/routes/index.tsx (2)
examples/react/18n-paraglide/src/routes/__root.tsx (1)
  • Route (15-70)
examples/react/18n-paraglide/src/routes/about.tsx (1)
  • Route (4-6)
examples/react/start-i18n-paraglide/src/routes/about.tsx (2)
examples/react/start-i18n-paraglide/src/routes/__root.tsx (1)
  • Route (13-31)
examples/react/start-i18n-paraglide/src/routes/index.tsx (1)
  • Route (12-21)
examples/react/18n-paraglide/src/routeTree.gen.ts (2)
examples/react/i18n-paraglide/src/routeTree.gen.ts (6)
  • FileRoutesByFullPath (26-29)
  • FileRoutesByTo (30-33)
  • FileRoutesById (34-38)
  • FileRouteTypes (39-46)
  • RootRouteChildren (47-50)
  • routeTree (75-77)
examples/react/start-i18n-paraglide/src/routeTree.gen.ts (6)
  • FileRoutesByFullPath (26-29)
  • FileRoutesByTo (30-33)
  • FileRoutesById (34-38)
  • FileRouteTypes (39-46)
  • RootRouteChildren (47-50)
  • routeTree (75-77)
examples/react/start-i18n-paraglide/src/utils/seo.ts (1)
scripts/llms-generate.mjs (1)
  • title (96-96)
examples/react/start-i18n-paraglide/src/routes/index.tsx (2)
examples/react/i18n-paraglide/src/routes/index.tsx (1)
  • Route (4-6)
examples/react/start-i18n-paraglide/src/routes/__root.tsx (1)
  • Route (13-31)
examples/react/i18n-paraglide/src/main.tsx (1)
e2e/react-router/js-only-file-based/src/main.jsx (2)
  • rootElement (15-15)
  • root (18-18)
examples/react/start-i18n-paraglide/src/routes/__root.tsx (3)
examples/react/i18n-paraglide/src/routes/__root.tsx (1)
  • Route (15-70)
examples/react/start-i18n-paraglide/src/routes/index.tsx (1)
  • Route (12-21)
packages/react-router-devtools/src/TanStackRouterDevtoolsPanel.tsx (1)
  • TanStackRouterDevtoolsPanel (37-87)
examples/react/start-i18n-paraglide/src/routeTree.gen.ts (1)
examples/react/start-i18n-paraglide/src/router.tsx (1)
  • getRouter (8-18)
examples/react/i18n-paraglide/src/routes/about.tsx (2)
examples/react/i18n-paraglide/src/routes/__root.tsx (1)
  • Route (15-70)
examples/react/i18n-paraglide/src/routes/index.tsx (1)
  • Route (4-6)
examples/react/i18n-paraglide/src/routes/__root.tsx (2)
examples/react/i18n-paraglide/src/routes/about.tsx (1)
  • Route (4-6)
examples/react/i18n-paraglide/src/routes/index.tsx (1)
  • Route (4-6)
🪛 markdownlint-cli2 (0.18.1)
examples/react/18n-paraglide/README.md

3-3: Link text should be descriptive

(MD059, descriptive-link-text)


22-22: Hard tabs
Column: 1

(MD010, no-hard-tabs)


25-25: Hard tabs
Column: 2

(MD010, no-hard-tabs)


26-26: Hard tabs
Column: 2

(MD010, no-hard-tabs)


27-27: Hard tabs
Column: 2

(MD010, no-hard-tabs)


28-28: Hard tabs
Column: 2

(MD010, no-hard-tabs)


29-29: Hard tabs
Column: 1

(MD010, no-hard-tabs)

examples/react/start-i18n-paraglide/README.md

3-3: Link text should be descriptive

(MD059, descriptive-link-text)


22-22: Hard tabs
Column: 1

(MD010, no-hard-tabs)


25-25: Hard tabs
Column: 2

(MD010, no-hard-tabs)


26-26: Hard tabs
Column: 2

(MD010, no-hard-tabs)


27-27: Hard tabs
Column: 2

(MD010, no-hard-tabs)


39-39: Hard tabs
Column: 2

(MD010, no-hard-tabs)


40-40: Hard tabs
Column: 1

(MD010, no-hard-tabs)

examples/react/i18n-paraglide/README.md

3-3: Link text should be descriptive

(MD059, descriptive-link-text)


22-22: Hard tabs
Column: 1

(MD010, no-hard-tabs)


25-25: Hard tabs
Column: 2

(MD010, no-hard-tabs)


26-26: Hard tabs
Column: 2

(MD010, no-hard-tabs)


27-27: Hard tabs
Column: 2

(MD010, no-hard-tabs)


28-28: Hard tabs
Column: 2

(MD010, no-hard-tabs)


29-29: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🔇 Additional comments (64)
examples/react/start-i18n-paraglide/public/robots.txt (1)

1-3: Robots directives look good

Allow-all directives are appropriate for the public demo assets.

examples/react/18n-paraglide/src/styles.css (1)

1-1: Tailwind import looks good

Importing Tailwind via @import "tailwindcss"; aligns with the new Tailwind setup in this example. No issues spotted.

examples/react/start-i18n-paraglide/public/manifest.json (1)

1-25: LGTM!

Manifest fields look consistent with the new example app; no issues spotted.

examples/react/18n-paraglide/project.inlang/.gitignore (1)

1-1: Cache ignore entry LGTM

Ignoring the generated Inlang cache prevents churn in the repo.

examples/react/start-i18n-paraglide/project.inlang/project_id (1)

1-1: Project ID addition looks good

Capturing the Inlang project identifier here keeps the configuration consistent.

examples/react/start-i18n-paraglide/src/styles.css (1)

1-1: Tailwind import wired correctly

The stylesheet now delegates to Tailwind’s entrypoint, matching the plugin setup in this example.

examples/react/start-i18n-paraglide/.vscode/extensions.json (1)

1-5: Helpful editor recommendation

Adding the inlang VS Code extension as a recommendation improves the DX for this example.

examples/react/i18n-paraglide/project.inlang/.gitignore (1)

1-1: Cache artifacts excluded

Good call ignoring the Inlang cache directory for this project.

examples/react/i18n-paraglide/.gitignore (1)

1-9: Comprehensive ignore list

These entries cover the usual build and local artifacts for the example app.

examples/react/18n-paraglide/project.inlang/project_id (1)

1-1: Inlang project ID captured

Storing the generated project ID ensures the tooling can resolve this example’s resources.

examples/react/start-i18n-paraglide/project.inlang/.gitignore (1)

1-1: Cache ignore entry LGTM

Same rationale here—keeps transient cache data out of version control.

examples/react/18n-paraglide/.gitignore (1)

1-9: Good call ignoring generated clutter

Ignoring build artifacts, environment files, and the .tanstack cache will keep example diffs clean and reproducible. Nice touch.

examples/react/i18n-paraglide/src/styles.css (1)

1-1: Confirm Tailwind version compatibility

@import "tailwindcss"; only compiles with the Tailwind v4+ pipeline. If this example is still pinned to Tailwind v3.x (or if consumers copy the setup without the v4 preview), the build will drop all utility classes. Please confirm the packages are aligned, or revert to the v3-style @tailwind base/components/utilities directives.

examples/react/start-i18n-paraglide/.vscode/settings.json (1)

1-10: Nice safeguard for generated route trees

Marking routeTree.gen.ts as excluded and readonly prevents accidental edits while keeping file-watchers quiet. Solid developer-experience improvement.

examples/react/i18n-paraglide/public/robots.txt (1)

1-3: Robots defaults look good

Allowing all crawlers with an empty disallow block is the right default for an example app.

examples/react/18n-paraglide/.vscode/settings.json (1)

1-10: Consistent tooling configuration

Same exclusion/read-only treatment here keeps the generated route tree in sync across examples. 👍

examples/react/i18n-paraglide/public/manifest.json (1)

1-25: Manifest wiring looks standard

Metadata, icons, and display settings line up with the rest of the scaffold. No issues spotted.

examples/react/start-i18n-paraglide/.gitignore (1)

1-10: Mirroring ignore rules

Matching ignore patterns with the other example keeps all the generated bits out of Git. Looks good.

examples/react/18n-paraglide/package.json (1)

13-27: Switch TanStack deps to workspace:*.

Repo guidelines require internal TanStack packages to use the workspace:* protocol so examples stay in lockstep with the monorepo builds. Please update the dependency versions accordingly.
[suggest_essential_refactor]
Apply this diff:

-    "@tanstack/react-router": "^1.132.2",
-    "@tanstack/router-plugin": "^1.132.3",
+    "@tanstack/react-router": "workspace:*",
+    "@tanstack/router-plugin": "workspace:*",

As per coding guidelines

examples/react/i18n-paraglide/package.json (1)

13-27: Switch TanStack deps to workspace:*.

Same as the other example, the internal TanStack packages should reference the local workspace to avoid version skew.
[suggest_essential_refactor]
Apply this diff:

-    "@tanstack/react-router": "^1.132.2",
-    "@tanstack/router-plugin": "^1.132.3",
+    "@tanstack/react-router": "workspace:*",
+    "@tanstack/router-plugin": "workspace:*",

As per coding guidelines

examples/react/start-i18n-paraglide/package.json (1)

12-27: Switch TanStack deps to workspace:*.

Please align the example with the monorepo policy by pointing TanStack dependencies at the workspace.
[suggest_essential_refactor]
Apply this diff:

-    "@tanstack/react-router": "^1.132.7",
-    "@tanstack/react-start": "^1.132.9",
+    "@tanstack/react-router": "workspace:*",
+    "@tanstack/react-start": "workspace:*",

As per coding guidelines

examples/react/i18n-paraglide/README.md (1)

3-29: Tidy markdown per lint warnings.

Markdown lint flagged the generic “here” link text and hard tabs in the Vite diff. Switching to descriptive link text and spaces clears those warnings.
[suggest_optional_refactor]
Apply this diff:

-This example shows how to use Paraglide with TanStack Router. The source code can be found [here](https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-js/examples/tanstack-router).
+This example shows how to use Paraglide with TanStack Router. The source code can be found in the [official Paraglide TanStack Router example](https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-js/examples/tanstack-router).
@@
-export default defineConfig({
-	plugins: [
-    tanstackRouter({ target: 'react', autoCodeSplitting: true }),
-    react(),
-		paraglideVitePlugin({
-			project: "./project.inlang",
-			outdir: "./app/paraglide",
-		}),
-	],
+export default defineConfig({
+  plugins: [
+    tanstackRouter({ target: 'react', autoCodeSplitting: true }),
+    react(),
+    paraglideVitePlugin({
+      project: "./project.inlang",
+      outdir: "./app/paraglide",
+    }),
+  ],
examples/react/start-i18n-paraglide/src/server.ts (1)

4-8: Server middleware wiring looks correct

Paraglide middleware is properly wrapping the Start handler; import extensions align with ESM.

examples/react/18n-paraglide/tsconfig.json (1)

14-15: Good: verbatimModuleSyntax already enabled

This matches recommended ESM/bundler settings and the repo’s strict TS stance.

examples/react/start-i18n-paraglide/messages/en.json (1)

1-8: LGTM: valid Paraglide message schema and keys

Keys and placeholders look consistent; JSON is valid.

examples/react/start-i18n-paraglide/src/utils/translated-pathnames.ts (1)

47-56: Example data aligns with route tree

The mappings for "/" and "/about" look correct for en/de.

examples/react/18n-paraglide/public/robots.txt (1)

1-3: LGTM: permissive robots.txt for examples

Standard config; fine for an example app.

examples/react/i18n-paraglide/messages/en.json (1)

1-7: LGTM: valid schema and message keys

Consistent with the de bundle and example routes’ usage.

examples/react/i18n-paraglide/project.inlang/settings.json (1)

1-15: LGTM! Inlang configuration follows expected patterns.

The Inlang settings correctly configure the i18n setup with proper locale definitions and plugin references.

examples/react/start-i18n-paraglide/src/routes/about.tsx (1)

1-10: LGTM! Clean route implementation with proper i18n integration.

The route follows TanStack Router conventions and correctly uses the Paraglide messages for localization.

examples/react/i18n-paraglide/src/routes/about.tsx (1)

1-10: LGTM! Consistent with the example's i18n pattern.

The route properly integrates with Paraglide messages and follows the file-based routing pattern.

examples/react/18n-paraglide/src/main.tsx (3)

10-22: LGTM! Router configuration with URL rewriting for i18n.

The router setup correctly implements URL localization/delocalization using Paraglide's runtime utilities.


25-29: LGTM! Proper TypeScript module augmentation.

The module augmentation correctly registers the router instance for type safety across the application.


32-40: LGTM! Safe client-side rendering check.

The rendering logic properly checks for both element existence and prevents hydration mismatches by verifying the element is empty.

examples/react/18n-paraglide/src/routes/index.tsx (1)

1-18: LGTM! Clean route implementation with parameterized i18n message.

The component correctly demonstrates passing dynamic parameters to localized messages.

examples/react/18n-paraglide/messages/en.json (1)

1-7: LGTM! Well-structured English message definitions.

The JSON structure follows Inlang's message format schema and provides clear message keys with appropriate parameterization.

examples/react/i18n-paraglide/vite.config.ts (1)

9-43: Config looks solid.

Plugin order and Paraglide urlPatterns (with catch-all last) look good. Router plugin before React is correct.

examples/react/start-i18n-paraglide/vite.config.ts (1)

1-6: No changes needed: @/* path mapping present in tsconfig.json
The examples/react/start-i18n-paraglide/tsconfig.json already defines "paths": { "@/*": ["./src/*"] }.

examples/react/start-i18n-paraglide/src/routes/__root.tsx (1)

42-59: No action: rewrite.output is already configured
The router in src/router.tsx uses localizeUrl for rewrite.output, so plain “/” and “/about” links will localize correctly.

examples/react/start-i18n-paraglide/src/router.tsx (1)

1-18: LGTM! Clean router setup with i18n URL rewriting.

The router configuration correctly integrates Paraglide's URL localization with TanStack Router's rewrite feature. The setup properly handles both input (delocalization) and output (localization) transformations.

examples/react/i18n-paraglide/src/routeTree.gen.ts (1)

1-77: Generated file looks correct.

This is an auto-generated file by TanStack Router that properly sets up the route tree with type safety. The file correctly excludes linter/formatter checks as indicated by the comments.

examples/react/18n-paraglide/src/routeTree.gen.ts (6)

1-10: Auto-generated file with proper warnings and linting exclusions.

The file includes appropriate warnings about being auto-generated and should not be modified, along with proper linting/formatting exclusions.


11-13: Standard TanStack Router imports for file-based routing.

The imports correctly reference the expected route file structure under ./routes/.


15-24: Route definitions follow TanStack Router conventions.

The route updates with id, path, and getParentRoute follow the standard pattern for file-based routing in TanStack Router.


26-50: Comprehensive type definitions for route mapping.

The interfaces provide proper type safety for the router system, covering all necessary route mapping patterns (by full path, by destination, by ID, and children structure).


52-69: Module augmentation for TanStack Router integration.

The module declaration properly extends @tanstack/react-router with file route metadata, enabling type-safe navigation and route resolution.


71-77: Route tree construction follows TanStack Router pattern.

The route tree assembly using _addFileChildren and _addFileTypes is the standard approach for TanStack Router file-based routing.

examples/react/start-i18n-paraglide/src/routeTree.gen.ts (7)

1-10: Auto-generated file with proper warnings and linting exclusions.

The file includes appropriate warnings about being auto-generated and should not be modified, along with proper linting/formatting exclusions.


11-13: Standard TanStack Router imports for file-based routing.

The imports correctly reference the expected route file structure under ./routes/.


15-24: Route definitions follow TanStack Router conventions.

The route updates with id, path, and getParentRoute follow the standard pattern for file-based routing in TanStack Router.


26-50: Comprehensive type definitions for route mapping.

The interfaces provide proper type safety for the router system, covering all necessary route mapping patterns (by full path, by destination, by ID, and children structure).


52-69: Module augmentation for TanStack Router integration.

The module declaration properly extends @tanstack/react-router with file route metadata, enabling type-safe navigation and route resolution.


71-77: Route tree construction follows TanStack Router pattern.

The route tree assembly using _addFileChildren and _addFileTypes is the standard approach for TanStack Router file-based routing.


79-86: TanStack Start integration with proper SSR registration.

The module augmentation for @tanstack/react-start correctly registers the router type with SSR support enabled, which is appropriate for the Start framework integration.

examples/react/i18n-paraglide/.vscode/settings.json (1)

2-10: LGTM on excluding the generated route tree

Keeping routeTree.gen.ts readonly and invisible to watchers prevents noisy editor churn in this example. Nicely aligned with the other samples.

examples/react/i18n-paraglide/tsconfig.json (1)

18-27: Strict TS config looks solid

Appreciate that strictness, unused checks, and bundler resolution are all enabled here—it keeps the example consistent with our strict TS guidance. Based on learnings.

examples/react/start-i18n-paraglide/messages/de.json (1)

2-7: German copy looks good

Translations line up with the keys used elsewhere in the example—no issues spotted.

examples/react/i18n-paraglide/messages/de.json (1)

2-6: Localization entries align with the routes

The localized strings match the route intents (/ueber etc.), so this resource file checks out.

examples/react/i18n-paraglide/project.inlang/project_id (1)

1-1: Project ID recorded

Looks like a standard Inlang project id file—nothing to change.

examples/react/start-i18n-paraglide/project.inlang/settings.json (1)

2-14: Inlang settings wired correctly

Base locale, locale list, plugin modules, and path pattern all line up with the message files added in this example. Good to go.

examples/react/18n-paraglide/project.inlang/settings.json (1)

2-14: Duplicate settings stay consistent

Same configuration as the Start variant, which keeps the examples aligned—no concerns.

examples/react/18n-paraglide/public/manifest.json (1)

2-24: Manifest metadata checks out

Icon set, display mode, and theme colors look standard for the sample PWA manifest.

examples/react/i18n-paraglide/src/routes/index.tsx (1)

4-15: Nice localized home route wiring

createFileRoute and the localized message hook up cleanly. Nothing else needed here.

examples/react/18n-paraglide/src/routes/about.tsx (1)

4-9: About route component looks good

Straightforward route component with localized copy—reads well and fits the pattern.

@@ -0,0 +1,20 @@
<!doctype html>
<html>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add the <html lang> attribute to meet a11y requirements

The document is missing a lang attribute, so assistive tech can’t determine the page’s language until after hydration updates it. This violates WCAG 3.1.1 on first paint. Please add the default locale (en) here so it’s correct even before JS runs.

-<html>
+<html lang="en">
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<html>
<html lang="en">
🤖 Prompt for AI Agents
In examples/react/18n-paraglide/index.html around line 2, the root <html>
element is missing a lang attribute causing accessibility issues on first paint;
update the opening html tag to include lang="en" so the document language is
declared before hydration (use the default locale "en").

@@ -0,0 +1,141 @@
# TanSTack Router example

This example shows how to use Paraglide with TanStack Router. The source code can be found [here](https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-js/examples/tanstack-router).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Make the link text more descriptive.

The generic "here" link text isn't accessible or descriptive. Screen reader users need meaningful link text to understand the destination.

Apply this diff to improve the link text:

-This example shows how to use Paraglide with TanStack Router. The source code can be found [here](https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-js/examples/tanstack-router).
+This example shows how to use Paraglide with TanStack Router. The source code can be found in the [Paraglide JS examples repository](https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-js/examples/tanstack-router).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
This example shows how to use Paraglide with TanStack Router. The source code can be found [here](https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-js/examples/tanstack-router).
This example shows how to use Paraglide with TanStack Router. The source code can be found in the [Paraglide JS examples repository](https://github.com/opral/monorepo/tree/main/inlang/packages/paraglide/paraglide-js/examples/tanstack-router).
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

3-3: Link text should be descriptive

(MD059, descriptive-link-text)

🤖 Prompt for AI Agents
In examples/react/18n-paraglide/README.md around line 3, the link text "here" is
non-descriptive and not accessible; update the link text to be meaningful (e.g.,
"Paraglide TanStack Router example source" or "Paraglide + TanStack Router
example repository") so screen readers convey the destination, keeping the
existing URL unchanged.

Comment on lines 21 to 29
export default defineConfig({
plugins: [
tanstackRouter({ target: 'react', autoCodeSplitting: true }),
react(),
+ paraglideVitePlugin({
+ project: "./project.inlang",
+ outdir: "./app/paraglide",
+ }),
],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix inconsistent indentation: spaces vs tabs.

The code example mixes tabs and spaces for indentation, which could cause issues when users copy the code.

Apply this diff to use consistent spacing:

 export default defineConfig({
-	plugins: [
+  plugins: [
     tanstackRouter({ target: 'react', autoCodeSplitting: true }),
     react(),
-+		paraglideVitePlugin({
-+			project: "./project.inlang",
-+			outdir: "./app/paraglide",
-+		}),
-	],
++    paraglideVitePlugin({
++      project: "./project.inlang",
++      outdir: "./app/paraglide",
++    }),
+  ],
 });

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

22-22: Hard tabs
Column: 1

(MD010, no-hard-tabs)


25-25: Hard tabs
Column: 2

(MD010, no-hard-tabs)


26-26: Hard tabs
Column: 2

(MD010, no-hard-tabs)


27-27: Hard tabs
Column: 2

(MD010, no-hard-tabs)


28-28: Hard tabs
Column: 2

(MD010, no-hard-tabs)


29-29: Hard tabs
Column: 1

(MD010, no-hard-tabs)

🤖 Prompt for AI Agents
In examples/react/18n-paraglide/README.md around lines 21 to 29, the code sample
mixes tabs and spaces for indentation; replace tabs with consistent spaces (use
2 spaces to match surrounding file style) so the plugins array lines
(tanstackRouter, react, paraglideVitePlugin block and its options) are indented
uniformly, and ensure the closing brackets align with the same space-based
indentation.

});
```

And import into the Paraglide Vite plguin.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo: "plguin" should be "plugin".

There's a typo in the sentence about importing into the Paraglide Vite plugin.

Apply this diff:

-And import into the Paraglide Vite plguin.
+And import into the Paraglide Vite plugin.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
And import into the Paraglide Vite plguin.
And import into the Paraglide Vite plugin.
🤖 Prompt for AI Agents
In examples/react/18n-paraglide/README.md around line 137, there's a typo:
"plguin" should be corrected to "plugin"; update the sentence to replace
"plguin" with "plugin" so it reads "And import into the Paraglide Vite plugin."


## Server side rendering

For server side rerdering, check out the [TanStack Start guide](https://inlang.com/m/gerre34r/library-inlang-paraglideJs/tanstack-start).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo: "rerending" should be "rendering".

There's a typo in the SSR section.

Apply this diff:

-For server side rerending, check out the [TanStack Start guide](https://inlang.com/m/gerre34r/library-inlang-paraglideJs/tanstack-start).
+For server side rendering, check out the [TanStack Start guide](https://inlang.com/m/gerre34r/library-inlang-paraglideJs/tanstack-start).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
For server side rerdering, check out the [TanStack Start guide](https://inlang.com/m/gerre34r/library-inlang-paraglideJs/tanstack-start).
For server side rendering, check out the [TanStack Start guide](https://inlang.com/m/gerre34r/library-inlang-paraglideJs/tanstack-start).
🤖 Prompt for AI Agents
In examples/react/18n-paraglide/README.md around line 141, there's a typo in the
SSR sentence: "rerdering" should be "rendering"; update the word to "rendering"
so the sentence reads "For server side rendering, check out the [TanStack Start
guide](https://inlang.com/m/gerre34r/library-inlang-paraglideJs/tanstack-start)."

Comment on lines 24 to 25
const { serverFunctionMessage, messageFromLoader, localeFromLoader } =
Route.useLoaderData();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify proper async handling for server function.

The loader directly calls getServerMessage({ data: "📩" }) without awaiting. If this returns a Promise, it should be awaited.

Let me check the return type of server functions:


🏁 Script executed:

#!/bin/bash
# Check how server functions are used in TanStack Start examples
rg -n "createServerFn" -A 10 -B 2 --type=ts --type=tsx

Length of output: 27


🏁 Script executed:

#!/bin/bash
echo "Listing src directory:"
ls -R examples/react/start-i18n-paraglide/src
echo
echo "Searching for getServerMessage definition:"
rg -n "export const getServerMessage" -C3 examples/react/start-i18n-paraglide/src
echo
echo "Searching for createServerFn usage:"
rg -n "createServerFn" -C3 examples/react/start-i18n-paraglide/src

Length of output: 1288


🏁 Script executed:

#!/bin/bash
rg -n "loader" -C5 examples/react/start-i18n-paraglide/src/routes/index.tsx

Length of output: 750


Await the server function in the loader
Make the loader async and await getServerMessage so you don’t pass a Promise to the component:

 loader: () => {
-  return {
+  return (async () => ({
     localeFromLoader: getLocale(),
     messageFromLoader: m.example_message({ username: "John Doe" }),
-    serverFunctionMessage: getServerMessage({ data: "📩" }),
+    serverFunctionMessage: await getServerMessage({ data: "📩" }),
  }))();
 },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { serverFunctionMessage, messageFromLoader, localeFromLoader } =
Route.useLoaderData();
loader: () => {
return (async () => ({
localeFromLoader: getLocale(),
messageFromLoader: m.example_message({ username: "John Doe" }),
serverFunctionMessage: await getServerMessage({ data: "📩" }),
}))();
},
🤖 Prompt for AI Agents
In examples/react/start-i18n-paraglide/src/routes/index.tsx around lines 24-25,
the loader currently returns a Promise for serverFunctionMessage which causes
the component to receive a Promise; update the loader function to be async and
await getServerMessage before returning so serverFunctionMessage is a resolved
value (not a Promise), and ensure the returned object uses the awaited value for
serverFunctionMessage.

Comment on lines 13 to 30
{ title },
{ name: "description", content: description },
{ name: "keywords", content: keywords },
{ name: "twitter:title", content: title },
{ name: "twitter:description", content: description },
{ name: "twitter:creator", content: "@tannerlinsley" },
{ name: "twitter:site", content: "@tannerlinsley" },
{ name: "og:type", content: "website" },
{ name: "og:title", content: title },
{ name: "og:description", content: description },
...(image
? [
{ name: "twitter:image", content: image },
{ name: "twitter:card", content: "summary_large_image" },
{ name: "og:image", content: image },
]
: []),
];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid emitting meta tags with undefined content

description and keywords are optional, yet we still emit the matching meta descriptors with content: undefined. The downstream head manager will serialize these to content="undefined" (or at best an empty attribute), which is undesirable for SEO/preview cards and clutters the head. Please gate those descriptors on the presence of data (same for the derived Twitter/OG descriptions).

Update the block to conditionally spread only when the value exists:

-  const tags = [
-    { title },
-    { name: "description", content: description },
-    { name: "keywords", content: keywords },
-    { name: "twitter:title", content: title },
-    { name: "twitter:description", content: description },
-    { name: "twitter:creator", content: "@tannerlinsley" },
-    { name: "twitter:site", content: "@tannerlinsley" },
-    { name: "og:type", content: "website" },
-    { name: "og:title", content: title },
-    { name: "og:description", content: description },
+  const tags = [
+    { title },
+    ...(description
+      ? [
+          { name: "description", content: description },
+          { name: "twitter:description", content: description },
+          { name: "og:description", content: description },
+        ]
+      : []),
+    ...(keywords ? [{ name: "keywords", content: keywords }] : []),
+    { name: "twitter:title", content: title },
+    { name: "twitter:creator", content: "@tannerlinsley" },
+    { name: "twitter:site", content: "@tannerlinsley" },
+    { name: "og:type", content: "website" },
+    { name: "og:title", content: title },
     ...(image
       ? [
           { name: "twitter:image", content: image },
           { name: "twitter:card", content: "summary_large_image" },
           { name: "og:image", content: image },
         ]
       : []),
   ];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{ title },
{ name: "description", content: description },
{ name: "keywords", content: keywords },
{ name: "twitter:title", content: title },
{ name: "twitter:description", content: description },
{ name: "twitter:creator", content: "@tannerlinsley" },
{ name: "twitter:site", content: "@tannerlinsley" },
{ name: "og:type", content: "website" },
{ name: "og:title", content: title },
{ name: "og:description", content: description },
...(image
? [
{ name: "twitter:image", content: image },
{ name: "twitter:card", content: "summary_large_image" },
{ name: "og:image", content: image },
]
: []),
];
const tags = [
{ title },
...(description
? [
{ name: "description", content: description },
{ name: "twitter:description", content: description },
{ name: "og:description", content: description },
]
: []),
...(keywords ? [{ name: "keywords", content: keywords }] : []),
{ name: "twitter:title", content: title },
{ name: "twitter:creator", content: "@tannerlinsley" },
{ name: "twitter:site", content: "@tannerlinsley" },
{ name: "og:type", content: "website" },
{ name: "og:title", content: title },
...(image
? [
{ name: "twitter:image", content: image },
{ name: "twitter:card", content: "summary_large_image" },
{ name: "og:image", content: image },
]
: []),
];
🤖 Prompt for AI Agents
In examples/react/start-i18n-paraglide/src/utils/seo.ts around lines 13 to 30,
optional fields like description, keywords, and derived twitter/og values are
currently emitted even when undefined; change the array construction to only
include meta objects when their source values exist by conditionally spreading
small arrays (e.g. ...(description ? [{ name: "description", content:
description }, { name: "twitter:description", content: description }, { name:
"og:description", content: description }] : [])) and do the same for keywords
and image so no meta tag with content: undefined is produced.

Comment on lines 18 to 30
function toUrlPattern(path: string) {
return (
path
// catch-all
.replace(/\/\$$/, "/:path(.*)?")
// optional parameters: {-$param}
.replace(/\{-\$([a-zA-Z0-9_]+)\}/g, ":$1?")
// named parameters: $param
.replace(/\$([a-zA-Z0-9_]+)/g, ":$1")
// remove trailing slash
.replace(/\/+$/, "")
);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Bug: toUrlPattern('/') returns empty string

Trailing-slash removal turns "/" into "", causing pattern "" and localized paths like "/en" vs expected "/" or "/en/". This can break matching in Vite plugin/url rewrites.

Apply:

 function toUrlPattern(path: string) {
   return (
     path
       // catch-all
       .replace(/\/\$$/, "/:path(.*)?")
       // optional parameters: {-$param}
       .replace(/\{-\$([a-zA-Z0-9_]+)\}/g, ":$1?")
       // named parameters: $param
       .replace(/\$([a-zA-Z0-9_]+)/g, ":$1")
       // remove trailing slash
-      .replace(/\/+$/, "")
+      .replace(/\/+$/, "") || "/"
   );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function toUrlPattern(path: string) {
return (
path
// catch-all
.replace(/\/\$$/, "/:path(.*)?")
// optional parameters: {-$param}
.replace(/\{-\$([a-zA-Z0-9_]+)\}/g, ":$1?")
// named parameters: $param
.replace(/\$([a-zA-Z0-9_]+)/g, ":$1")
// remove trailing slash
.replace(/\/+$/, "")
);
}
function toUrlPattern(path: string) {
return (
path
// catch-all
.replace(/\/\$$/, "/:path(.*)?")
// optional parameters: {-$param}
.replace(/\{-\$([a-zA-Z0-9_]+)\}/g, ":$1?")
// named parameters: $param
.replace(/\$([a-zA-Z0-9_]+)/g, ":$1")
// remove trailing slash
.replace(/\/+$/, "") || "/"
);
}
🤖 Prompt for AI Agents
In examples/react/start-i18n-paraglide/src/utils/translated-pathnames.ts around
lines 18 to 30, the trailing-slash removal can turn "/" into "" causing empty
URL patterns; update the function so after the .replace(/\/+$/, "") step you
normalize an empty result back to "/" (or if you prefer, ensure the final
returned string is "/" when the computed value is empty) so root paths remain
"/" and localized variants become "/en" or "/en/" as expected; implement this by
checking the final value and returning "/" when it's an empty string.

Comment on lines 35 to 44
return Object.entries(input).map(([pattern, locales]) => ({
pattern: toUrlPattern(pattern),
localized: Object.entries(locales).map(
([locale, path]) =>
[locale as Locale, `/${locale}${toUrlPattern(path)}`] satisfies [
Locale,
string,
]
),
}));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Ensure root localized paths don’t end with a double slash

When the base pattern is “/”, emit “/en” instead of “/en/”.

Apply:

-    localized: Object.entries(locales).map(
-      ([locale, path]) =>
-        [locale as Locale, `/${locale}${toUrlPattern(path)}`] satisfies [
-          Locale,
-          string,
-        ]
-    ),
+    localized: Object.entries(locales).map(([locale, path]) => {
+      const p = toUrlPattern(path)
+      const suffix = p === "/" ? "" : p
+      return [locale as Locale, `/${locale}${suffix}`] as [Locale, string]
+    }),
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return Object.entries(input).map(([pattern, locales]) => ({
pattern: toUrlPattern(pattern),
localized: Object.entries(locales).map(
([locale, path]) =>
[locale as Locale, `/${locale}${toUrlPattern(path)}`] satisfies [
Locale,
string,
]
),
}));
return Object.entries(input).map(([pattern, locales]) => ({
pattern: toUrlPattern(pattern),
localized: Object.entries(locales).map(([locale, path]) => {
const p = toUrlPattern(path)
const suffix = p === "/" ? "" : p
return [locale as Locale, `/${locale}${suffix}`] as [Locale, string]
}),
}));
🤖 Prompt for AI Agents
In examples/react/start-i18n-paraglide/src/utils/translated-pathnames.ts around
lines 35–44, the code concatenates `/${locale}` with `toUrlPattern(path)` which
causes a double slash when `toUrlPattern(path)` returns '/' (root) and yields
'/en/' instead of '/en'; change the join so that when `toUrlPattern(path)` ===
'/' you append an empty string (or strip the leading slash) — e.g. compute a
suffix = toUrlPattern(path) === '/' ? '' : toUrlPattern(path) and return
`/${locale}${suffix}` to ensure root localized paths produce '/en' not '/en/'.

Comment on lines 14 to 15
"verbatimModuleSyntax": false,
"noEmit": true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Enable verbatimModuleSyntax for ESM/bundler consistency

This example should use verbatimModuleSyntax: true (matches the other example tsconfig and avoids import elision surprises in ESM).

As a minimal fix, apply:

-    "verbatimModuleSyntax": false,
+    "verbatimModuleSyntax": true,

As per coding guidelines

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"verbatimModuleSyntax": false,
"noEmit": true,
"verbatimModuleSyntax": true,
"noEmit": true,
🤖 Prompt for AI Agents
In examples/react/start-i18n-paraglide/tsconfig.json around lines 14-15,
verbatimModuleSyntax is currently false which can cause import elision issues
for ESM; update the tsconfig to set "verbatimModuleSyntax": true (matching the
other example) so the compiler preserves import/export syntax for bundlers and
ESM, leaving "noEmit": true as-is unless other changes are required.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant