# Build options

### --project or -p CLI option

Introduced in Keycloakify 9.4

This option is for Monorepos. You can run Keycloakify from the root of your project with:

`npx keycloakify --project <path>`

`<path>` would be typically something like `packages/keycloak-theme`

### postBuild hook

*Ony available in Vite, introduced in v9.5*

The postBuild hook is an optional parameter of the Keycloakify Vite plugin that enables you to apply some transformation to your Keycloak theme after it's been built but before the .jar is created.

<pre class="language-typescript" data-title="vite.config.ts"><code class="lang-typescript">import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { keycloakify } from "keycloakify/vite-plugin";

export default defineConfig({
  plugins: [
    react(), 
    keycloakify({
      themeName: "keycloakify-starter",
      extraThemeProperties: [
        "foo=bar"
      ],
<strong>      // In this example, after running `yarn build-keycloak-theme`
</strong><strong>      // there will be a `keycloak_dist/foo.txt` file.  
</strong><strong>      postBuild: async keycloakifyBuildOptions => {
</strong>
<strong>        const fs = await import("fs/promises");
</strong><strong>        const path = await import("path");
</strong>
<strong>        await fs.writeFile(
</strong><strong>          path.join(keycloakifyBuildOptions.keycloakifyBuildDirPath, "foo.txt"),
</strong><strong>          Buffer.from(
</strong><strong>            [
</strong><strong>            "Created by the postBuild hook of the keycloakify vite plugin", 
</strong><strong>            "",
</strong><strong>            "Resolved keycloakifyBuildOptions:",
</strong><strong>            "",
</strong><strong>            JSON.stringify(keycloakifyBuildOptions, null, 2),
</strong><strong>            ""
</strong><strong>            ].join("\n"),
</strong><strong>            "utf8"
</strong><strong>          )
</strong><strong>        );
</strong>
<strong>      }
</strong>    })
  ],
</code></pre>

### extraThemeProperties

This let you add properties to the `build_keycloak/src/main/resources/theme/<your app>/[login|account]/theme.properties` file.

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

<pre class="language-typescript" data-title="vite.config.ts"><code class="lang-typescript">import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { keycloakify } from "keycloakify/vite-plugin";

export default defineConfig({
  plugins: [
    react(), 
    keycloakify({
<strong>      extraThemeProperties: [ 
</strong><strong>        "locales=en,ko",
</strong><strong>        "MY_ENV_VARIABLE=${env.MY_ENV_VARIABLE:default}"
</strong><strong>      ]
</strong>    })
  ],
})
</code></pre>

{% endtab %}

{% tab title="Webpack" %}

<pre class="language-json" data-title="package.json"><code class="lang-json">{
    "keycloakify": {
<strong>        "extraThemeProperties": [ 
</strong><strong>            "locales=en,ko",
</strong><strong>            "MY_ENV_VARIABLE=${env.MY_ENV_VARIABLE:default}"
</strong><strong>        ]
</strong>    }
}
</code></pre>

{% endtab %}
{% endtabs %}

It is mainly useful to get access to the Keycloak server environment variables in your theme. See:

{% content-ref url="environment-variables" %}
[environment-variables](https://docs.keycloakify.dev/keycloakify/v9/environment-variables)
{% endcontent-ref %}

### doCreateJar

default: true

*Introduced in 9.0*

Tell wether or not you want Keycloakify to bundle your theme within a .jar file.

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

<pre class="language-typescript" data-title="vite.config.ts"><code class="lang-typescript">import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { keycloakify } from "keycloakify/vite-plugin";

export default defineConfig({
  plugins: [
    react(), 
    keycloakify({
<strong>      doCreateJar: false
</strong>    })
  ],
})
</code></pre>

{% endtab %}

{% tab title="Webpack" %}

<pre class="language-json" data-title="package.json"><code class="lang-json">{
    "keycloakify": {
<strong>        "doCreateJar": false
</strong>    }
}
</code></pre>

{% endtab %}
{% endtabs %}

### groupId

*Introduced in 6.11*

Configure the `groupId` that will appear in the `pom.xml` file.

<figure><img src="https://4187774434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrU7aqfyZ5vYuUDxKeHBj%2Fuploads%2Fgit-blob-6603cc6ca04dce49be41806ce7bd067675566141%2Fimage%20(7).png?alt=media" alt=""><figcaption></figcaption></figure>

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

<pre class="language-typescript" data-title="vite.config.ts"><code class="lang-typescript">import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { keycloakify } from "keycloakify/vite-plugin";

export default defineConfig({
  plugins: [
    react(), 
    keycloakify({
<strong>      groupId: "dev.keycloakify.demo-app-advanced.keycloak"
</strong>    })
  ],
})
</code></pre>

{% endtab %}

{% tab title="Webpack" %}
{% code title="package.json" %}

```json
{
    "keycloakify": {
        "groupId": "dev.keycloakify.demo-app-advanced.keycloak"
    }
}
```

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

By default it's the package.json homepage field at reverse with .keycloak at the end.

You can overwrite this using an environment variable:

```bash
KEYCLOAKIFY_GROUP_ID="com.your-company.your-project.keycloak" npx keycloakify
```

### artifactId

*Introduced in 6.11*

Configure the `artifactId` that will appear in the `pom.xml` file.

<figure><img src="https://4187774434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrU7aqfyZ5vYuUDxKeHBj%2Fuploads%2Fgit-blob-03f27fa4795fe4499c9cd082849c928f01b6bdb1%2Fimage%20(8).png?alt=media" alt=""><figcaption></figcaption></figure>

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

<pre class="language-typescript" data-title="vite.config.ts"><code class="lang-typescript">import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { keycloakify } from "keycloakify/vite-plugin";

export default defineConfig({
  plugins: [
    react(), 
    keycloakify({
<strong>      artifactId: "keycloakify-advanced-starter-keycloak-theme"
</strong>    })
  ],
})
</code></pre>

{% endtab %}

{% tab title="Webpack" %}
{% code title="package.json" %}

```json
{
    "keycloakify": {
        "artifactId": "keycloakify-advanced-starter-keycloak-theme"
    }
}
```

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

By default it's `<themeName>-keycloak-theme` See, [`keycloak.themeName`](#keyclokify.themename) option.

You can overwrite this using an environment variable:

```bash
KEYCLOAKIFY_ARTIFACT_ID="my-cool-theme" npx keycloakify
```

{% hint style="info" %}
The `artifactId` also affects [the name of the `.jar` file](https://github.com/InseeFrLab/keycloakify/blob/9f72024c61b1b36d71a42b242c05d7ac793e049b/src/bin/keycloakify/generateJavaStackFiles.ts#L85).
{% endhint %}

### loginThemeResourcesFromKeycloakVersion

Default: 11.0.3

This replaces `keycloakVersionDefaultAssets`.

The default login `Template.tsx` imports CSS resources that are copied from the Keycloak version specified by this parameter.\
This is not something you should worry about too much. These imports are mostly there so that the pages that Keycloakify provides by default match the ones of the default theme. You should, however, strive to use your own assets; after all, this is the point of creating a theme.\
\
Example where Keycloak resources are imported in the login theme:

* [In Template.tsx, css imports](https://github.com/keycloakify/keycloakify-starter/blob/92b20fe74154ef8cf037f4b156eb3b2e5264a074/src/keycloak-theme/login/Template.tsx#L37-L40)
* [In LoginOtp, js import](https://github.com/keycloakify/keycloakify/blob/402c6fc64a26268b6f2f7222e4f11ff07de452f8/src/login/pages/LoginOtp.tsx#L26)

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

<pre class="language-typescript" data-title="vite.config.ts"><code class="lang-typescript">import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { keycloakify } from "keycloakify/vite-plugin";

export default defineConfig({
  plugins: [
    react(), 
    keycloakify({
<strong>      loginThemeResourcesFromKeycloakVersion: "21.0.1"
</strong>    })
  ],
})
</code></pre>

{% endtab %}

{% tab title="Webpack" %}
{% code title="package.json" %}

```json
{
    "keycloakify": {
        "loginThemeResourcesFromKeycloakVersion": "21.0.1"
    }
}
```

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

Note that for account theme we do not enable to specify the version, the assets used are fixed to Keycloak 21.1.2.

### version

Configure the version that will appear in the `pom.xml` file.

<figure><img src="https://4187774434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrU7aqfyZ5vYuUDxKeHBj%2Fuploads%2Fgit-blob-84586a98a9d1c4040d6be6939d272f65efbf2a62%2Fimage%20(1)%20(1)%20(1)%20(1).png?alt=media" alt=""><figcaption></figcaption></figure>

By default the version that is used is the one in the package.json of your project

{% code title="package.json" %}

```json
{
    "version": "1.3.4"
}
```

{% endcode %}

But you can overwrite this value using an environment variable (*Introduced in 6.11)*:

```bash
KEYCLOAKIFY_THEME_VERSION="4.5.6" npx keycloakify
```

{% hint style="info" %}
The version also affects [the name of the `.jar` file](https://github.com/InseeFrLab/keycloakify/blob/9f72024c61b1b36d71a42b242c05d7ac793e049b/src/bin/keycloakify/generateJavaStackFiles.ts#L85).
{% endhint %}

### **customUserAttributes**

*Deprecated.*

*Introduced in 7.4.0 removed in 7.13.0*

Keycloakify now analyzes your code and see what field name are actually used.\
Just make sure your fieldNames aren't generated at runtime. Eg:

```tsx
// OK ✅
messagesPerField.exists("foo-bar")

// Not OK 🛑
const bar= "bar";
messagesPerField.exists(`foo-${bar}`);
```

[See issue for more context](https://github.com/keycloakify/keycloakify/issues/40).

### themeName

*Introduced in 7.5.0*

This is the name of the theme in the Keycloak admin select:

<figure><img src="https://4187774434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrU7aqfyZ5vYuUDxKeHBj%2Fuploads%2Fgit-blob-baa56436a638e815191492bb2de4c77cb8847c89%2Fimage%20(13).png?alt=media" alt=""><figcaption></figcaption></figure>

By default it's `package.json["name"]`

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

<pre class="language-typescript" data-title="vite.config.ts"><code class="lang-typescript">import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { keycloakify } from "keycloakify/vite-plugin";

export default defineConfig({
  plugins: [
    react(), 
    keycloakify({
<strong>      themeName: "my-custom-name"
</strong>    })
  ],
})
</code></pre>

{% endtab %}

{% tab title="Webpack" %}
{% code title="package.json" %}

```json
{
    "keycloakify": {
        "themeName": "my-custom-name"
    }
}
```

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

You can also provide an array if you want to Keycloakify to create multiple theme variant:

{% tabs %}
{% tab title="Vite" %}
{% code title="vite.config.ts" %}

```typescript
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
import { keycloakify } from "keycloakify/vite-plugin";

export default defineConfig({
  plugins: [
    react(), 
    keycloakify({
      themeName: [ "keycloakify-starter", "keycloakify-starter-variant-1" ]
    })
  ],
})
```

{% endcode %}
{% endtab %}

{% tab title="Webpack" %}
{% code title="package.json" %}

```json
{
    "keycloakify": {
        "themeName": [ "keycloakify-starter", "keycloakify-starter-variant-1" ]
    }
}
```

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

This option deprecates `extraThemeNames`and let you pack multiple themes variant in a single `.jar` bundle. In vanilla Keycloak themes you have the ability to extend a base theme. There is now an idiomatic way of achieving the same result by using this option.

This will make the theme variant appear in the Keycloak admin select input:

<figure><img src="https://4187774434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrU7aqfyZ5vYuUDxKeHBj%2Fuploads%2Fgit-blob-47f88d0b97cd077d690e2ea60719e6f0b2006914%2Fimage%20(4).png?alt=media" alt=""><figcaption></figcaption></figure>

The theme name will be available on the `kcContext`:

<figure><img src="https://4187774434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrU7aqfyZ5vYuUDxKeHBj%2Fuploads%2Fgit-blob-99deac49468d4d13cc3394ff188ec1c5f4a1ac6c%2Fimage%20(3).png?alt=media" alt=""><figcaption></figcaption></figure>

You'll be able to implement different behaviour based on which theme variant is the current one:

<figure><img src="https://4187774434-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FrU7aqfyZ5vYuUDxKeHBj%2Fuploads%2Fgit-blob-8bae30368ab8451e00d7bcda1ff8ad809fb5b83b%2Fimage%20(2).png?alt=media" alt=""><figcaption></figcaption></figure>

To load different global css file based on the theme name you can implement this strategy:

```typescript
// src/keycloak-theme/login/useGlobalStylesheet.ts
import { useMemo } from "react";

export function useGlobalStylesheet(themeName: string){
    useMemo(() => {
        switch(themeName){
            case "keycloakify-starter":
                // @ts-expect-error
                import("./keycloakify-starter.css");
                break;
            case "keycloakify-starter-variant-1":
                // @ts-expect-error
                import("./keycloakify-starter-variant-1.css");
                break;
        }
    }, [themeName]);
}
```

```tsx
// src/keycloak-theme/login/KcApp.tsx

import { useGlobalStylesheet } from "./useGlobalStylesheet";
// ...

export default function KcApp(props: { kcContext: KcContext; }) {
  const { kcContext }= props;
  // ...
  
  useGlogalStylesheet(kcContext.themeName);

  // ...
```

### silent

Options that can be passed to the `npx keycloakify` command. With `npx keycloakify --silent` no output is printed to the console.

### XDG\_CACHE\_HOME

> This option is not as important to implement as it use to be, Keycloakify is much more optimized in the latest releases.

Keycloakify needs to download resources from the Keycloak project to build your theme. To prevent these resources from being downloaded repeatedly, Keycloakify caches them by default in `node_modules/.cache`. However, you can specify a different location by setting the `XDG_CACHE_HOME` environment variable.\
Example: `XDG_CACHE_HOME=/home/runner/.cache/yarn npx keycloakify`

This is particularly useful [in your CI workflow](https://github.com/keycloakify/keycloakify-starter/blob/92b20fe74154ef8cf037f4b156eb3b2e5264a074/.github/workflows/ci.yaml#L19-L21) to ensure that the cache persists across runs (see the documentation for the bahmutov/npm-install GitHub Action).

### PUBLIC\_DIR\_PATH

> Only relevant in webpack project, in Vite, it's read from your vite.config.ts file!

Default: `~/public`

Example: `npx PUBLIC_DIR_PATH=./web/public npx copy-keycloak-resources-to-public`

{% embed url="<https://cloud-iam.com/?mtm_campaign=keycloakify-deal&mtm_source=keycloakify-doc-build-options>" %}
Feeling overwhelmed? Check out our exclusive sponsor's Cloud-IAM consulting services to simplify your experience.
{% endembed %}
