Langsys with Next.js

The pattern is the same everywhere: the server fetches the catalog once (write key stays server-side), and the client initializes langsys-js-react from that seed with a read-only key — no duplicate fetch. The translating itself happens in the browser: the HTML the server sends is in the base language, which is also what search engines index, and the page switches to the visitor's language as it loads.

1 · Fetch the catalog on the server

A Server Component fetches the catalog with a raw fetch — the SDK is not needed on the server. The write key stays on the server; the client gets a read-only key. Both halves see the same catalog — the client just skips the initial fetch.

// app/layout.tsx (Server Component)
import type { iCategories } from 'langsys-js-react';
import { LangsysClient } from './LangsysClient';

async function getTranslations(locale: string): Promise<iCategories> {
  const res = await fetch(
    `https://api.langsys.dev/api/projects/${process.env.LANGSYS_PROJECT_ID}/translations?locale=${locale}`,
    { headers: { 'x-Authorization': process.env.LANGSYS_API_KEY! } }
  );
  const result = await res.json();
  return result.data as iCategories;
}

export default async function RootLayout({ children }: { children: React.ReactNode }) {
  const locale = 'en-US'; // from cookie / Accept-Language / route segment
  const translations = await getTranslations(locale);

  return (
    <html lang={locale}>
      <body>
        <LangsysClient
          locale={locale}
          translations={translations}
          projectId={process.env.LANGSYS_PROJECT_ID!}
          apiKey={process.env.NEXT_PUBLIC_LANGSYS_API_KEY!} // read-only
        >
          {children}
        </LangsysClient>
      </body>
    </html>
  );
}

2 · Initialize on the client

A small 'use client' wrapper initializes the SDK in the browser with the seeded catalog, so it starts without fetching anything. The text switches from the base language to the visitor's language when this effect runs.

// app/LangsysClient.tsx
'use client';

import { useEffect, type ReactNode } from 'react';
import { LangsysApp, useLocaleStore, type iCategories } from 'langsys-js-react';

export function LangsysClient(props: {
  locale: string;
  translations: iCategories;
  projectId: string;
  apiKey: string;
  children: ReactNode;
}) {
  const [, , localeStore] = useLocaleStore(props.locale);

  useEffect(() => {
    LangsysApp.init({
      projectid: props.projectId,
      key: props.apiKey,
      UserLocaleStore: localeStore,
      initialTranslations: props.translations,
      initialTranslationsLocale: props.locale,
      ssrTokenStrategy: 'client',
    });
  }, [localeStore, props.projectId, props.apiKey, props.translations, props.locale]);

  return <>{props.children}</>;
}

3 · Use it anywhere below

From here it is the plain React SDK: useT() in any Client Component, locale switching through the same store. Keep one locale store for the app (created where you call init) and thread setLocale down, rather than creating fresh stores in unrelated trees.

'use client';
import { useT } from 'langsys-js-react';

export function Hero() {
  const t = useT();
  return <h1>{t('Welcome to our store', 'Home')}</h1>;
}
Search the docs & Learning Center