# Initial setup

{% embed url="<https://youtu.be/5q88JgXUAY4>" %}

{% hint style="warning" %}
If you already had the DSFR installed in your project, let's start from scratch:

* Remove [`@gouvfr/dsfr`](https://www.npmjs.com/package/@gouvfr/dsfr) from your dependencies.
* Remove the import of`dsfr.css, dsfr.module.js the favicon and the fonts.`
* Remove `the data-fr-scheme` (and `data-fr-theme` ) attribude from your `<html/>` tag
  {% endhint %}

{% tabs %}
{% tab title="yarn" %}

```bash
yarn add @codegouvfr/react-dsfr
```

{% endtab %}

{% tab title="npm" %}

```bash
npm install --save @codegouvfr/react-dsfr
```

{% endtab %}

{% tab title="pnpm" %}

```bash
pnpm add @codegouvfr/react-dsfr
```

And add this file to the root of your project, to enable pre & post scripts with pnpm:

{% code title=".npmrc" %}

```properties
enable-pre-post-scripts=true
```

{% endcode %}
{% endtab %}

{% tab title="Yarn Berry (a.k.a Yarn 3 or Yarn modern)" %}
{% hint style="warning" %}
When we say Yarn we usually refer to Yarn 1.x as most dev teams (Including me) havent upgraded to the newest version (for good reasons).
{% endhint %}

If you want to use Yarn Berry you be aware that pre- post- scripts aren't supported.

So you must do something like `"dev": "copy-dsfr-to-public && next dev"` (same thing for `start`)

Also you must configure it so it uses `node_modules` (sorry)
{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Vite" %}
{% embed url="<https://github.com/garronej/react-dsfr-vite-demo>" %}
Demo setup in production here: <https://react-dsfr-vite-demo.vercel.app/>
{% endembed %}

If you want a more complete starter with a Ready yo use stack that includes routing, autentication, internationalisation ect. you can also use this starter instead:&#x20;

{% embed url="<https://github.com/InseeFrLab/vite-insee-starter>" %}
It's live here: <https://vite-insee-starter.demo-domain.ovh/>
{% endembed %}

{% hint style="info" %}
Using Nx monorepo? See [this](https://github.com/codegouvfr/react-dsfr/issues/328#issuecomment-2429157963).
{% endhint %}

Add these three scripts to your `package.json`:

<pre class="language-json" data-title="package.json"><code class="lang-json">"scripts": {
<strong>    "predev": "react-dsfr update-icons",
</strong><strong>    "prebuild": "react-dsfr update-icons"
</strong>}
</code></pre>

Trigger the execution of the postinstall script by running:

```bash
yarn # Or 'npm install' or 'pnpm install'
```

Add the following tags in the `<head />`

{% code title="index.html" %}

```html
<link rel="apple-touch-icon" href="./node_modules/@codegouvfr/react-dsfr/favicon/apple-touch-icon.png" />
<link rel="icon" href="./node_modules/@codegouvfr/react-dsfr/favicon/favicon.svg" type="image/svg+xml" />
<link rel="shortcut icon" href="./node_modules/@codegouvfr/react-dsfr/favicon/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="./node_modules/@codegouvfr/react-dsfr/favicon/manifest.webmanifest" crossorigin="use-credentials" />

<link rel="stylesheet" href="./node_modules/@codegouvfr/react-dsfr/main.css" />
```

{% endcode %}

<pre class="language-tsx" data-title="src/main.tsx"><code class="lang-tsx">import React from "react";
import ReactDOM from "react-dom/client";
import { App } from "./App";
<strong>import { startReactDsfr } from "@codegouvfr/react-dsfr/spa";
</strong><strong>startReactDsfr({ defaultColorScheme: "system" });
</strong>
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
  &#x3C;React.StrictMode>
    &#x3C;App />
  &#x3C;/React.StrictMode>
);
</code></pre>

You're all set! Next step for you is to setup the integration with your routing library (react-router for example).

{% content-ref url="routing" %}
[routing](https://react-dsfr.codegouv.studio/routing)
{% endcontent-ref %}
{% endtab %}

{% tab title="Next.js App Router" %}
{% embed url="<https://github.com/garronej/react-dsfr-next-appdir-demo>" %}
Starter project in prod here: <https://react-dsfr-next-appdir-demo.vercel.app/>
{% endembed %}

```bash
yarn add @codegouvfr/react-dsfr
yarn add --dev sass
npx degit https://github.com/garronej/react-dsfr-next-appdir-demo/src/dsfr-bootstrap src/dsfr-bootstrap
```

<pre class="language-json" data-title="package.json"><code class="lang-json">"scripts": {
<strong>    "predev": "react-dsfr update-icons",
</strong><strong>    "prebuild": "react-dsfr update-icons"
</strong>}
</code></pre>

<pre class="language-tsx" data-title="src/app/layout.tsx"><code class="lang-tsx"><strong>import { getHtmlAttributes, DsfrHead } from "../dsfr-bootstrap/server-only-index";
</strong><strong>import { DsfrProvider } from "../dsfr-bootstrap";
</strong>
export default function RootLayout({ children }: { children: React.JSX.Element; }) {
  const lang = undefined; // Can be "fr" or "en" ...
  return (
<strong>    &#x3C;html {...getHtmlAttributes({ lang })} >
</strong>      &#x3C;head>
<strong>        &#x3C;DsfrHead />
</strong>      &#x3C;/head>
      &#x3C;body>
<strong>        &#x3C;DsfrProvider lang={lang}>
</strong>          {children}
<strong>        &#x3C;/DsfrProvider>
</strong>      &#x3C;/body>
    &#x3C;/html>
  );
}
</code></pre>

<pre class="language-tsx" data-title="src/app/page.tsx"><code class="lang-tsx"><strong>import { StartDsfrOnHydration } from "../dsfr-bootstrap";
</strong>
export default function Page() {
  return (
    &#x3C;>
      {/* Important: You must mount this component on every pages of your App! */}
<strong>      &#x3C;StartDsfrOnHydration />
</strong>      &#x3C;h1>Welcome!&#x3C;/h1>
    &#x3C;/>
  );
}
</code></pre>

{% endtab %}

{% tab title="Next.js Pages Router" %}
{% hint style="info" %}
This documentation is for [Next projects using the Page Router](https://nextjs.org/docs/pages/building-your-application/routing) (aka the legacy next setup).

You are in this case if you have a `pages/` directory at the root of your project.
{% endhint %}

{% embed url="<https://github.com/garronej/react-dsfr-next-demo>" %}
Starter project in prod here: <https://react-dsfr-next-demo.vercel.app/>
{% endembed %}

```bash
# If you plan to use MUI:  
yarn add @mui/material @emotion/react @emotion/server @emotion/styled @mui/material @emotion/react
```

<pre class="language-javascript" data-title="next.config.js"><code class="lang-javascript">/** @type {import('next').NextConfig} */
const nextConfig = {
  reactStrictMode: true,
  swcMinify: true,
<strong>  //This option requires Next 13.1 or newer, if you can't update you can use this plugin instead: https://github.com/martpie/next-transpile-modules
</strong><strong>  transpilePackages: [
</strong><strong>      "@codegouvfr/react-dsfr", 
</strong><strong>      "tss-react" // This is for MUI or if you use htts://tss-react.dev
</strong><strong>  ],
</strong>  output: "export"
};

module.exports = nextConfig
</code></pre>

<pre class="language-json" data-title="package.json"><code class="lang-json">"scripts": {
<strong>    "predev": "react-dsfr update-icons",
</strong><strong>    "prebuild": "react-dsfr update-icons"
</strong>}
</code></pre>

{% code title="pages/\_app.tsx" %}

```tsx
import type { AppProps } from "next/app";
import { createNextDsfrIntegrationApi } from "@codegouvfr/react-dsfr/next-pagesdir";
import Link from "next/link";

// Only in TypeScript projects
declare module "@codegouvfr/react-dsfr/next-pagesdir" {
    interface RegisterLink { 
        Link: typeof Link;
    }
}

const { 
    withDsfr,
    dsfrDocumentApi
} = createNextDsfrIntegrationApi({
    defaultColorScheme: "system",
    Link
});

export { dsfrDocumentApi };

function App({ Component, pageProps }: AppProps) {
    return <Component {...pageProps} />;
}

export default withDsfr(App);
```

{% endcode %}

{% code title="pages/\_document.tsx" %}

```tsx
import { Html, Head, Main, NextScript, DocumentProps } from "next/document";
import { dsfrDocumentApi } from "./_app";

const { 
  getColorSchemeHtmlAttributes, 
  augmentDocumentForDsfr 
} = dsfrDocumentApi;

export default function Document(props: DocumentProps) {
  return (
    <Html {...getColorSchemeHtmlAttributes(props)}>
      <Head />
      <body>
        <Main />
        <NextScript />
      </body>
    </Html>
  );
}

augmentDocumentForDsfr(Document);
```

{% endcode %}
{% endtab %}

{% tab title="Create React App" %}
{% hint style="warning" %}
The create-react-app project is no longer being maintained. If you are starting a new project you'll probably be beter off with Vite.
{% endhint %}

{% embed url="<https://github.com/garronej/react-dsfr-cra-demo>" %}
See demo setup in production here: <https://react-dsfr-cra-demo.vercel.app/>
{% endembed %}

Add these three scripts to your `package.json`:

<pre class="language-json" data-title="package.json"><code class="lang-json">"scripts": {
    ...
    "postinstall": "react-dsfr copy-static-assets",
    "predev": "react-dsfr update-icons",
    "prebuild": "react-dsfr update-icons"
},
...
"jest": {
    "transformIgnorePatterns": [
<strong>      "node_modules/(?!@codegouvfr/react-dsfr)"
</strong>    ]
}
</code></pre>

Trigger the execution of the postinstall script by running:

```bash
yarn # Or 'npm install' or 'pnpm install'
```

Add the following code in the `<head />`

{% code title="public/index.html" %}

```ejs
<link rel="apple-touch-icon" href="%PUBLIC_URL%/dsfr/favicon/apple-touch-icon.png" />
<link rel="icon" href="%PUBLIC_URL%/dsfr/favicon/favicon.svg" type="image/svg+xml" />
<link rel="shortcut icon" href="%PUBLIC_URL%/dsfr/favicon/favicon.ico" type="image/x-icon" />
<link rel="manifest" href="%PUBLIC_URL%/dsfr/favicon/manifest.webmanifest" crossorigin="use-credentials" />

<link rel="stylesheet" href="%PUBLIC_URL%/dsfr/utility/icons/icons.min.css" />
<link rel="stylesheet" href="%PUBLIC_URL%/dsfr/dsfr.min.css" />
```

{% endcode %}

<pre class="language-tsx" data-title="src/index.tsx"><code class="lang-tsx">import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
<strong>import { startReactDsfr } from "@codegouvfr/react-dsfr/spa";
</strong><strong>startReactDsfr({ defaultColorScheme: "system" });
</strong>
const root = ReactDOM.createRoot(
  document.getElementById('root') as HTMLElement
);
root.render(
  &#x3C;React.StrictMode>
    &#x3C;App />
  &#x3C;/React.StrictMode>
);
</code></pre>

You're all set! Next step for you is to setup de integration with your routing library (react-router for example)

{% content-ref url="routing" %}
[routing](https://react-dsfr.codegouv.studio/routing)
{% endcontent-ref %}
{% endtab %}

{% tab title="Other" %}
Your framework isn't supported? Let's [get in touch](https://github.com/codegouvfr/dsfr-react)!  \
\
Note: We don't have a custom integration for it but react-dsfr has been reported working with [Gatsby](https://www.gatsbyjs.com/).  <br>

{% embed url="<https://github.com/codegouvfr/react-dsfr/issues/204>" %}
{% endtab %}
{% endtabs %}

### Avoiding or flash of unstyled text (FOUT)

You can avoid having a flash of unstyled text by preloading the font variant used on your homepage (look in the network tab of your browser dev tools what are the font downloaded initially).

{% tabs %}
{% tab title="Vite" %}
Add the following tags in the `<head />`

{% code title="index.html" %}

```html
<!--<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Light.woff2" as="font" crossorigin="anonymous" />-->
<!--<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Light_Italic.woff2" as="font" crossorigin="anonymous" />-->
<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Regular.woff2" as="font" crossorigin="anonymous" />
<!--<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Regular_Italic.woff2" as="font" crossorigin="anonymous" />-->
<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Medium.woff2" as="font" crossorigin="anonymous" />
<!--<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Medium_Italic.woff2" as="font" crossorigin="anonymous" />-->
<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Bold.woff2" as="font" crossorigin="anonymous" />
<!--<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Marianne-Bold_Italic.woff2" as="font" crossorigin="anonymous" />-->
<!--<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Spectral-Regular.woff2" as="font" crossorigin="anonymous" />-->
<!--<link rel="preload" href="./node_modules/@codegouvfr/react-dsfr/dsfr/fonts/Spectral-ExtraBold.woff2" as="font" crossorigin="anonymous" />-->
```

{% endcode %}
{% endtab %}

{% tab title="Next.js App Router" %}

<pre class="language-tsx" data-title="src/app/layout.tsx"><code class="lang-tsx">import { getHtmlAttributes, DsfrHead } from "../dsfr-bootstrap/server-only-index";
import { DsfrProvider } from "../dsfr-bootstrap";

export default function RootLayout({ children }: { children: React.JSX.Element; }) {
  const lang = undefined; // Can be "fr" or "en" ...
  return (
    &#x3C;html {...getHtmlAttributes({ lang })} >
      &#x3C;head>
        &#x3C;DsfrHead 
<strong>          preloadFonts={[
</strong><strong>	    //"Marianne-Light",
</strong><strong>            //"Marianne-Light_Italic",
</strong><strong>	    "Marianne-Regular",
</strong><strong>	    //"Marianne-Regular_Italic",
</strong><strong>	    "Marianne-Medium",
</strong><strong>	    //"Marianne-Medium_Italic",
</strong><strong>	    "Marianne-Bold"
</strong><strong>	    //"Marianne-Bold_Italic",
</strong><strong>	    //"Spectral-Regular",
</strong><strong>	    //"Spectral-ExtraBold"
</strong><strong>	  ]}
</strong>        />
      &#x3C;/head>
      &#x3C;body>
        &#x3C;DsfrProvider lang={lang}>
          {children}
        &#x3C;/DsfrProvider>
      &#x3C;/body>
    &#x3C;/html>
  );
}
</code></pre>

{% endtab %}

{% tab title="Next.js Pages Router" %}

<pre class="language-tsx" data-title="pages/_app.tsx"><code class="lang-tsx">import type { AppProps } from "next/app";
import { createNextDsfrIntegrationApi } from "@codegouvfr/react-dsfr/next-pagesdir";
import Link from "next/link";

// Only in TypeScript projects
declare module "@codegouvfr/react-dsfr/next-pagesdir" {
    interface RegisterLink { 
        Link: typeof Link;
    }
}

const { 
    withDsfr,
    dsfrDocumentApi
} = createNextDsfrIntegrationApi({
    defaultColorScheme: "system",
    Link,
<strong>    preloadFonts: [
</strong><strong>  	//"Marianne-Light",
</strong><strong>        //"Marianne-Light_Italic",
</strong><strong>	"Marianne-Regular",
</strong><strong>	//"Marianne-Regular_Italic",
</strong><strong>	"Marianne-Medium",
</strong><strong>	//"Marianne-Medium_Italic",
</strong><strong>	"Marianne-Bold",
</strong><strong>	//"Marianne-Bold_Italic",
</strong><strong>	//"Spectral-Regular",
</strong><strong>	//"Spectral-ExtraBold"
</strong><strong>    ]
</strong>});

export { dsfrDocumentApi };

function App({ Component, pageProps }: AppProps) {
    return &#x3C;Component {...pageProps} />;
}

export default withDsfr(App);
</code></pre>

{% endtab %}

{% tab title="Create React App" %}
Add the following code in the `<head />`

{% code title="public/index.html" %}

```ejs
<%
[
  //"Marianne-Light",
  //"Marianne-Light_Italic",
  "Marianne-Regular",
  //"Marianne-Regular_Italic",
  "Marianne-Medium",
  //"Marianne-Medium_Italic",
  "Marianne-Bold",
  //"Marianne-Bold_Italic",
  //"Spectral-Regular",
  //"Spectral-ExtraBold"
].forEach(function(name){ %>
  <link rel="preload" href="%PUBLIC_URL%/dsfr/fonts/<%=name%>.woff2" as="font" crossorigin="anonymous" />
<% }); %>
```

{% endcode %}
{% endtab %}
{% endtabs %}
