Skip to content

SSR Compatibility

The flag packages render inline SVG and do not need browser APIs. Named flag imports and DynamicFlag can therefore render in the first server response with Next.js and Nuxt.

Named imports

Recommended for SSR and CSR. They are synchronous, tree-shakeable, and require no client-only boundary.

DynamicFlag

SSR-safe and synchronous, but it imports the complete flag registry. Use it only when the code cannot be bounded at build time.

CircleFlag

Deprecated. It fetches SVG after mounting, so the server can only render its loading state. Do not use it when the flag must appear in the initial HTML.

Rendering Stack Verification
CSR React + Vite 8 TypeScript and production bundle build
SSR Next.js App Router + React Production build, server startup, first-response SVG assertion
CSR Vue 3 + Vite 8 Vue TypeScript and production bundle build
SSR Nuxt 4 + Vue 3 Nuxt typecheck/build, Nitro startup, first-response SVG assertion
CSR Svelte 5 + Vite 8 Svelte compiler and production bundle build
CSR Solid.js + Vite 8 TypeScript and production bundle build

App Router files are Server Components by default. Consumers do not need to add a use client directive: the React package entry declares its own boundary because it also exposes the deprecated, hook-based CircleFlag. Next.js can still prerender named flags and DynamicFlag into the first HTML response.

import { DynamicFlag, FlagJp } from '@sankyu/react-circle-flags'
export default function Page() {
return (
<main>
<FlagJp width={64} height={64} title="Japan" />
<DynamicFlag code="de" width={64} height={64} title="Germany" />
</main>
)
}

Keep the import at the public package entry. Importing generated files or internal source paths bypasses the package export map and can fail when Next.js resolves the server graph.

Import Vue components directly in <script setup>. Do not wrap named flags or DynamicFlag in <ClientOnly>; doing so removes the flag markup from the initial HTML.

<script setup lang="ts">
import { DynamicFlag, FlagJp } from '@sankyu/vue-circle-flags'
</script>
<template>
<main>
<FlagJp :width="64" :height="64" title="Japan" />
<DynamicFlag code="de" :width="64" :height="64" title="Germany" />
</main>
</template>

Vite 8 uses a newer Node.js baseline. This affects the example toolchain, not the browser runtime of the published flag packages. Use a Node.js version accepted by your chosen framework; the monorepo uses the stricter Nuxt-compatible range so every example can share one environment.

Use @vitejs/plugin-react and strict subpaths such as @sankyu/react-circle-flags/flags/us.

The server HTML contains a placeholder instead of the flag

Section titled “The server HTML contains a placeholder instead of the flag”

Replace deprecated CircleFlag with a named import or DynamicFlag. CircleFlag performs a client-side network request after mount and cannot embed the fetched SVG during SSR.

The client bundle becomes unexpectedly large

Section titled “The client bundle becomes unexpectedly large”

DynamicFlag intentionally includes all flags for arbitrary runtime codes. Prefer per-flag subpaths, or create a finite map of those imports when runtime values come from a known set. The main entry remains convenient, but strict flags/* subpaths provide deterministic bundle isolation.

Build the package before the framework example. From this repository, pnpm run test:examples builds packages first, then every compatibility app, and finally verifies the production SSR responses.