Indeed in the default mode your users have to download again the whole app just
to access the login page. You probably have [long-term asset caching](https://create-react-app.dev/docs/production-build/#static-file-caching)
enabled in the server that host your app ([example](https://github.com/garronej/keycloakify-demo-app/blob/224c43383548635a463fa68e8909c147ac189f0e/nginx.conf#L14))
so it's better if only the html is served by the Keycloak server and everything
else, your JS bundles, your CSS ect point to your app.
To enable this behavior you car run:
```bash
npx build-keycloak-theme --external-assets
```
(instead of `npx build-keycloak-theme`)
This is something you probably want to do in your CI pipeline. [Example](https://github.com/garronej/keycloakify-demo-app/blob/224c43383548635a463fa68e8909c147ac189f0e/.github/workflows/ci.yaml#L112)
Also note that there is [a same-origin policy exception for fonts](https://en.wikipedia.org/wiki/Same-origin_policy#cite_note-3) so you must enabled
CORS for fonts on the server hosting your app. Concretely this mean that your server should add a `Access-Control-Allow-Origin: *` response header to
GET request on *.woff2?. [Example with Nginx](https://github.com/garronej/keycloakify-demo-app/blob/224c43383548635a463fa68e8909c147ac189f0e/nginx.conf#L18-L20)
If you want to really re-implement the pages the best approach is to
create you own version of the [`<KcApp />`](https://github.com/garronej/keycloakify/blob/develop/src/lib/components/KcApp.tsx).
Copy/past some of [the components](https://github.com/garronej/keycloakify/tree/develop/src/lib/components) provided by this module and start hacking around.
In the standalone mode (when you run `npx build-keycloak-theme` without `--external-assets`) the fonts won't work if you are self
hosting them. This, for example, won’t work: [`src: url("/assets/worksans-bold-webfont.woff2") format("woff2")`](https://github.com/InseeFrLab/onyxia-ui/blob/b24df3a9b34b505ce00619bb8ec0174223ecfaca/src/app/theme/fonts.scss#L5-L6)
you will have to [host them externally](https://github.com/InseeFrLab/onyxia-ui/blob/43bf4a508419072a4ae202698e59d20b69feb9c0/src/app/theme/fonts.scss#L8-L9)
on a server that has CORS enabled.
Again this apply ony if you are not building your theme with `--external-assets` which is advised against in production.
by providing you a way to tell `keycloak-js` that you would like to inject
some search parameters before redirecting.
The method also works with [`@react-keycloak/web`](https://www.npmjs.com/package/@react-keycloak/web) (use the `initOptions`).
You can implement your own mechanism to pass the states in the URL and
restore it on the other side but we recommend using `powerhooks/useGlobalState`
from the library [`powerhooks`](https://www.powerhooks.dev) that provide an elegant
way to handle states such as `isDarkModeEnabled` or `selectedLanguage`.
Let's modify [the example](https://github.com/keycloak/keycloak-documentation/blob/master/securing_apps/topics/oidc/javascript-adapter.adoc) from the official `keycloak-js` documentation to
enables the states of `useGlobalStates` to be injected in the URL before redirecting.
Note that the states are automatically restored on the other side by `powerhooks`
```typescript
import keycloak_js from "keycloak-js";
import { injectGlobalStatesInSearchParams } from "powerhooks/useGlobalState";
import { createKeycloakAdapter} from "keycloakify";
If you really want to go the extra miles and avoid having the white
flash of the blank html before the js bundle have been evaluated
[here is a snippet](https://github.com/InseeFrLab/onyxia-ui/blob/a77eb502870cfe6878edd0d956c646d28746d053/public/index.html#L5-L54) that you can place in your `public/index.html` if you are using `powerhooks/useGlobalState`.