}>{markdownContent}\n );\n};\n```\n\n \n \n\nAngular does not have a Suspense API. Use Angular's deferrable views (`@defer`) to handle lazy-loaded Markdown content (requires Angular 17+).\n\n```typescript fileName=\"my.component.ts\"\nimport { Component } from \"@angular/core\";\nimport { useIntlayer } from \"angular-intlayer\";\n\n@Component({\n selector: \"app-my\",\n template: `\n @defer {\n
    \n } @loading {\n
    Loading...
    \n }\n `,\n})\nexport class MyComponent {\n content = useIntlayer(\"my-markdown\");\n}\n```\n\n
    \n\n\n---\n\n## Server-Side Rendering (SSR) and Hydration\n\nIn comparison of other Markdown parser such as remark / rehype, the Intlayer Markdown is dependency free and run on client as server side.\n\nBut Intlayer optimized the parsing for Server-Side Rendering (SSR) frameworks (such as Next.js App Router, React Router, Nuxt, SvelteKit, etc.).\n\nInstead of sending raw Markdown strings to the client and parsing them on the browser (which incurs a performance penalty), Intlayer allows you to pre-parse the Markdown into an Abstract Syntax Tree (AST) on the server.\n\nYou can use the `parseMarkdown` function from your framework's Intlayer package on the server side to generate a serializable AST (`ParsedMarkdown` object), and pass it directly to the frontend. All Intlayer rendering utilities (like ``, `useMarkdownRenderer`, etc.) automatically accept this AST object and render it seamlessly.\n\n### Example in a Server/Client Architecture\n\n\n \n\n ```tsx fileName=\"server.ts\"\n import { parseMarkdown } from \"react-intlayer/markdown\";\n\n // 1. On the server: Parse the markdown into a serializable AST\n export const loader = async () => {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // Return the AST as JSON to the client\n return Response.json({ content: ast });\n };\n ```\n\n ```tsx fileName=\"client.tsx\"\n import { useLoaderData } from \"react-router\";\n import { MarkdownRenderer } from \"react-intlayer/markdown\";\n\n // 2. On the client: Render the AST directly without re-parsing\n export default function Page() {\n const { content } = useLoaderData();\n\n // The renderer accepts either a raw string or the parsed AST\n return ;\n }\n ```\n\n \n \n\n ```tsx fileName=\"app/page.tsx\"\n import { parseMarkdown } from \"next-intlayer/markdown\";\n import { MarkdownRenderer } from \"next-intlayer/markdown\";\n\n export default async function Page() {\n // 1. Parse the markdown into a serializable AST on the server\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // 2. Render the AST directly\n // In a Server Component, this works seamlessly and passes the AST\n // directly to the underlying client components if needed.\n return ;\n }\n ```\n\n \n \n\n ```vue fileName=\"pages/index.vue\"\n \n\n \n ```\n\n \n \n\n ```typescript fileName=\"+page.server.ts\"\n import { parseMarkdown } from \"svelte-intlayer/markdown\";\n\n // 1. On the server: Parse the markdown into a serializable AST\n export const load = async () => {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n const ast = parseMarkdown(markdownString);\n\n // Return the AST to the client\n return { content: ast };\n };\n ```\n\n ```svelte fileName=\"+page.svelte\"\n \n\n \n \n ```\n\n \n \n\n Angular SSR typically resolves the data on the server during the initial load and hydrates on the client. You can use resolvers to pass the AST.\n\n ```typescript fileName=\"app.resolver.ts\"\n import { Injectable } from \"@angular/core\";\n import { Resolve } from \"@angular/router\";\n import { parseMarkdown, type ParsedMarkdown } from \"angular-intlayer/markdown\";\n\n @Injectable({ providedIn: \"root\" })\n export class MarkdownResolver implements Resolve {\n resolve(): ParsedMarkdown {\n const markdownString = \"## My title \\n\\nLorem Ipsum\";\n // 1. On the server: Parse the markdown into a serializable AST\n return parseMarkdown(markdownString);\n }\n }\n ```\n\n ```typescript fileName=\"app.component.ts\"\n import { Component } from \"@angular/core\";\n import { ActivatedRoute } from \"@angular/router\";\n import { IntlayerMarkdownService, type ParsedMarkdown } from \"angular-intlayer/markdown\";\n\n @Component({\n selector: \"app-root\",\n template: `
    `,\n })\n export class AppComponent {\n renderedMarkdown: string = \"\";\n\n constructor(\n private route: ActivatedRoute,\n private markdownService: IntlayerMarkdownService\n ) {\n // 2. On the client: Render the AST directly without re-parsing\n this.route.data.subscribe((data) => {\n this.renderedMarkdown = this.markdownService.renderMarkdown(\n data.markdownAst\n ) as string;\n });\n }\n }\n ```\n\n
    \n
    \n\nThis pattern ensures that the Markdown parsing logic is executed entirely on the server, significantly reducing the client-side execution time and improving the initial hydration speed.\n\n## Options Reference\n\nThese options can be passed to `MarkdownProvider`, `MarkdownRenderer`, `useMarkdownRenderer`, and `renderMarkdown`.\n\n| Option | Type | Default | Description |\n| :-------------------- | :---------- | :------ | :------------------------------------------------------------------------------------ |\n| `forceBlock` | `boolean` | `false` | Forces the output to be wrapped in a block-level element (e.g., `
    `). |\n| `forceInline` | `boolean` | `false` | Forces the output to be wrapped in an inline element (e.g., ``). |\n| `tagfilter` | `boolean` | `true` | Enables the GitHub Tag Filter for improved security by stripping dangerous HTML tags. |\n| `preserveFrontmatter` | `boolean` | `false` | If `true`, frontmatter at the beginning of the Markdown string will not be stripped. |\n| `components` | `Overrides` | `{}` | A map of HTML tags to custom components (e.g., `{ h1: MyHeading }`). |\n| `wrapper` | `Component` | `null` | A custom component to wrap the rendered Markdown. |\n| `renderMarkdown` | `Function` | `null` | A custom rendering function to completely replace the default Markdown compiler. |\n","about":"Learn how to declare and use Markdown content in your multilingual website with Intlayer. Follow the steps in this online documentation to integrate Markdown seamlessly into your project.","url":"https://intlayer.org/doc/concept/content/markdown","datePublished":"07-02-2025","dateModified":"19-05-2026","keywords":"Markdown, Internationalization, Documentation, Intlayer, Next.js, JavaScript, React","license":"https://raw.githubusercontent.com/aymericzip/intlayer/refs/heads/main/LICENSE","audience":{"@type":"Audience","audienceType":"Developers, Content Managers"}}
    Creation:2025-02-07Last update:2026-05-19

    Markdown / Rich Text Content

    Intlayer supports rich text content defined using Markdown syntax. This allows you to easily write and maintain content with rich formatting, such as blogs, articles, and more.

    Declaring Markdown Content

    You can declare Markdown content using the md function or simply as a string (if it contains Markdown syntax).

    Since version 8.10.0, you can declare Markdown content directly in .content.md files. Intlayer will automatically detect and parse the Markdown content.

    markdown-file.en.content.md
    ---key: my-markdown-contentdescription: My contentlocale: en---# My contentHere an example of markdown content

    The locale front-matter field is the field that define the locale of the content. It is optional. If not provided, Intlayer will use the default locale, which is also used as fallback locale if no translation is available for a specific locale.

    Example of file structure:

    text
    content├── markdown-file.en.content.md├── markdown-file.fr.content.md└── markdown-file.es.content.md

    You can add in front-matter any properties defined in the Dictionary definition

    Rendering Markdown

    Intlayer provides two independent ways to render Markdown:

    1. Via useIntlayer — Intlayer automatically transforms the md node into the framework's native output (JSX, VNode, HTML string).

      • Frontmatter is parsed and exposed as .metadata. You can override rendering at two levels — globally with MarkdownProvider (or the framework equivalent) and locally per-node with .use(). Both can be combined; .use() takes priority over MarkdownProvider, which takes priority over the default.
    2. Helper utilities<MarkdownRenderer />, useMarkdownRenderer(), and renderMarkdown() are standalone tools that accept raw Markdown strings only. They are independent of useIntlayer and do not work with the decorated nodes it returns.

    Markdown rendering supports MDX — use any JSX/framework component by name directly in your Markdown.

    1. Automatic Rendering (via useIntlayer)

    Markdown nodes can be rendered directly as JSX.

    App.tsx
    import { useIntlayer } from "react-intlayer";import { MarkdownProvider } from "react-intlayer/markdown";const AppContent = () => {  const { myMarkdownContent } = useIntlayer("app");  return <div>{myMarkdownContent}</div>;};const App = () => (  <MarkdownProvider    components={{      h1: ({ children }) => <h1 style={{ color: "red" }}>{children}</h1>,      MyButton: (props) => <button {...props} />, // MDX component    }}  >    <AppContent />  </MarkdownProvider>);
    If MarkdownProvider not present, intlayer will render the markdown using the default Markdown to JSX parser.

    You can also provide local overrides for specific nodes using the .use() method:

    tsx
    {myMarkdownContent.use({  h1: ({ children }) => <h1 style={{ color: "red" }}>{children}</h1>,})}

    You can retrieve the Markdown as string:

    tsx
    {myMarkdownContent.value}{String(myMarkdownContent)}{myMarkdownContent.toString()}

    And you can access your markdown metadata like :

    tsx
    {myMarkdownContent.metadata}{myMarkdownContent.metadata.title}

    2. Helper Utilities (Markdown Strings Only)

    These utilities render raw Markdown strings and are independent of useIntlayer. Use them when you need to render Markdown from sources other than your dictionaries.

    <MarkdownRenderer /> Component

    Render a Markdown string with specific options.

    tsx
    import { MarkdownRenderer } from "react-intlayer/markdown";<MarkdownRenderer forceBlock={true} tagfilter={true}>  {"# My Title"}</MarkdownRenderer>

    useMarkdownRenderer() Hook

    Get a pre-configured renderer function.

    tsx
    import { useMarkdownRenderer } from "react-intlayer/markdown";const renderMarkdown = useMarkdownRenderer({  forceBlock: true,  components: { h1: (props) => <h1 {...props} className="custom" /> }});return renderMarkdown("# My Title");

    renderMarkdown() Utility

    Standalone utility for rendering outside of components.

    tsx
    import { renderMarkdown } from "react-intlayer/markdown";const jsx = renderMarkdown("# My Title", { forceBlock: true });

    Global Configuration with MarkdownProvider

    MarkdownProvider (or its framework equivalent) configures the Markdown rendering pipeline for your entire application. It applies to both the automatic useIntlayer rendering and the helper utilities. Options set here are the defaults — .use() overrides them at the node level.

    AppProvider.tsx
    import { MarkdownProvider } from "react-intlayer/markdown";export const AppProvider = ({ children }) => (  <MarkdownProvider    components={{      h1: (props) => <h1 style={{color: 'green'}} {...props} />,      a: ({ href, ...props }) => <a style={{color: 'red'}} {...props} />,      MyCustomJSXComponent: (props) => <span style={{color: 'red'}} {...props} />,    }}  >    {children}  </MarkdownProvider>);
    MDX is supported — any component name used inside your Markdown (e.g. <MyCustomJSXComponent />) is resolved against the components map.

    You can also use your own markdown renderer:

    AppProvider.tsx
    import { MarkdownProvider } from "react-intlayer/markdown";export const AppProvider = ({ children }) => (  <MarkdownProvider    renderMarkdown={async (md) => {      // Use dynamic import to reduce the bundle size of your application      const { renderMarkdown } = await import('react-intlayer/markdown');      return renderMarkdown(md);    }}  >    {children}  </MarkdownProvider>);
    Importing your Markdown renderer dynamically is a good way to reduce the bundle size of your application.

    Suspense

    The Intlayer Markdown renderer is dynamically loaded. Although optimized, the underlying parser chunk is approximately 55kb. Loading this synchronously delays the initial page rendering and degrades First Contentful Paint (FCP).

    To prevent blocking the UI, Intlayer integrates with React's Suspense API. It fetches the parser in the background and throws a Promise during the download.

    Wrap any component rendering Intlayer Markdown in a <Suspense> boundary. This displays a localized fallback state while the chunk downloads, allowing the rest of your DOM to render immediately.

    Warning: If you do not provide a <Suspense> boundary, React will suspend at the root level or block the entire component tree from rendering until the 55kb chunk is fully loaded.

    In Next.js App Router, you can use either React Suspense for client components or a loading.tsx file for server components.

    Client Component:

    components/MyComponent.tsx
    "use client";import { useIntlayer } from "next-intlayer";import { Suspense } from "react";const MyComponent = () => {const markdownContent = useIntlayer("my-markdown");return (  <Suspense fallback={<div>Loading...</div>}>{markdownContent}</Suspense>);};

    Server Component with loading.tsx:

    app/loading.tsx
    export default function Loading() {return <div>Loading...</div>;}
    app/page.tsx
    import { useIntlayer } from "next-intlayer/server";const MyPage = () => {const markdownContent = useIntlayer("my-markdown");return <div>{markdownContent}</div>;};export default MyPage;

    Server-Side Rendering (SSR) and Hydration

    In comparison of other Markdown parser such as remark / rehype, the Intlayer Markdown is dependency free and run on client as server side.

    But Intlayer optimized the parsing for Server-Side Rendering (SSR) frameworks (such as Next.js App Router, React Router, Nuxt, SvelteKit, etc.).

    Instead of sending raw Markdown strings to the client and parsing them on the browser (which incurs a performance penalty), Intlayer allows you to pre-parse the Markdown into an Abstract Syntax Tree (AST) on the server.

    You can use the parseMarkdown function from your framework's Intlayer package on the server side to generate a serializable AST (ParsedMarkdown object), and pass it directly to the frontend. All Intlayer rendering utilities (like <MarkdownRenderer>, useMarkdownRenderer, etc.) automatically accept this AST object and render it seamlessly.

    Example in a Server/Client Architecture

    server.ts
    import { parseMarkdown } from "react-intlayer/markdown";// 1. On the server: Parse the markdown into a serializable ASTexport const loader = async () => {  const markdownString = "## My title \n\nLorem Ipsum";  const ast = parseMarkdown(markdownString);  // Return the AST as JSON to the client  return Response.json({ content: ast });};
    client.tsx
    import { useLoaderData } from "react-router";import { MarkdownRenderer } from "react-intlayer/markdown";// 2. On the client: Render the AST directly without re-parsingexport default function Page() {  const { content } = useLoaderData();  // The renderer accepts either a raw string or the parsed AST  return <MarkdownRenderer content={content} />;}

    This pattern ensures that the Markdown parsing logic is executed entirely on the server, significantly reducing the client-side execution time and improving the initial hydration speed.

    Options Reference

    These options can be passed to MarkdownProvider, MarkdownRenderer, useMarkdownRenderer, and renderMarkdown.

    Option Type Default Description
    forceBlock boolean false Forces the output to be wrapped in a block-level element (e.g., <div>).
    forceInline boolean false Forces the output to be wrapped in an inline element (e.g., <span>).
    tagfilter boolean true Enables the GitHub Tag Filter for improved security by stripping dangerous HTML tags.
    preserveFrontmatter boolean false If true, frontmatter at the beginning of the Markdown string will not be stripped.
    components Overrides {} A map of HTML tags to custom components (e.g., { h1: MyHeading }).
    wrapper Component null A custom component to wrap the rendered Markdown.
    renderMarkdown Function null A custom rendering function to completely replace the default Markdown compiler.