diff --git a/src/PUBLIC_URL.ts b/src/PUBLIC_URL.ts
index 050fb499..c21f1f05 100644
--- a/src/PUBLIC_URL.ts
+++ b/src/PUBLIC_URL.ts
@@ -5,7 +5,7 @@ import {
 import { assert } from "tsafe/assert";
 
 /**
- * This is an equivalent of process.env.PUBLIC_URL thay you can use in Webpack projects.
+ * This is an equivalent of process.env.PUBLIC_URL that you can use in Webpack projects.
  * This works both in your main app and in your Keycloak theme.
  */
 export const PUBLIC_URL = (() => {
diff --git a/src/account/index.ts b/src/account/index.ts
index ddcab7f7..3bb53c64 100644
--- a/src/account/index.ts
+++ b/src/account/index.ts
@@ -2,9 +2,9 @@ import Fallback from "keycloakify/account/Fallback";
 
 export default Fallback;
 
-export { getKcContext } from "keycloakify/account/kcContext/getKcContext";
-export { createGetKcContext } from "keycloakify/account/kcContext/createGetKcContext";
 export type { AccountThemePageId as PageId } from "keycloakify/bin/shared/constants";
 export { createUseI18n } from "keycloakify/account/i18n/i18n";
+export type { ExtendKcContext } from "keycloakify/account/kcContext";
+export { createGetKcContextMock } from "keycloakify/account/kcContext";
 
 export type { PageProps } from "keycloakify/account/pages/PageProps";
diff --git a/src/account/kcContext/KcContext.ts b/src/account/kcContext/KcContext.ts
index 09242a17..2ab09cff 100644
--- a/src/account/kcContext/KcContext.ts
+++ b/src/account/kcContext/KcContext.ts
@@ -1,6 +1,24 @@
+import type { ThemeType, AccountThemePageId } from "keycloakify/bin/shared/constants";
+import type { ValueOf } from "keycloakify/tools/ValueOf";
 import { assert } from "tsafe/assert";
 import type { Equals } from "tsafe";
-import type { ThemeType, AccountThemePageId } from "keycloakify/bin/shared/constants";
+
+export type ExtendKcContext<
+    KcContextExtraProperties extends { properties?: Record<string, string | undefined> },
+    KcContextExtraPropertiesPerPage extends Record<string, Record<string, unknown>>
+> = ValueOf<{
+    [PageId in keyof KcContextExtraPropertiesPerPage | KcContext["pageId"]]: Extract<
+        KcContext,
+        { pageId: PageId }
+    > extends never
+        ? KcContext.Common &
+              KcContextExtraProperties & {
+                  pageId: PageId;
+              } & KcContextExtraPropertiesPerPage[PageId]
+        : Extract<KcContext, { pageId: PageId }> &
+              KcContextExtraProperties &
+              KcContextExtraPropertiesPerPage[PageId];
+}>;
 
 export type KcContext =
     | KcContext.Password
diff --git a/src/account/kcContext/createGetKcContext.ts b/src/account/kcContext/createGetKcContext.ts
deleted file mode 100644
index f93feab0..00000000
--- a/src/account/kcContext/createGetKcContext.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-import type { DeepPartial } from "keycloakify/tools/DeepPartial";
-import { deepAssign } from "keycloakify/tools/deepAssign";
-import { isStorybook } from "keycloakify/lib/isStorybook";
-import type { ExtendKcContext } from "./getKcContextFromWindow";
-import { getKcContextFromWindow } from "./getKcContextFromWindow";
-import { symToStr } from "tsafe/symToStr";
-import {
-    kcContextMocks,
-    kcContextCommonMock
-} from "keycloakify/account/kcContext/kcContextMocks";
-
-export function createGetKcContext<
-    KcContextExtension extends { pageId: string } = never
->(params?: {
-    mockData?: readonly DeepPartial<ExtendKcContext<KcContextExtension>>[];
-    mockProperties?: Record<string, string>;
-}) {
-    const { mockData, mockProperties } = params ?? {};
-
-    function getKcContext<
-        PageId extends
-            | ExtendKcContext<KcContextExtension>["pageId"]
-            | undefined = undefined
-    >(params?: {
-        mockPageId?: PageId;
-        storyPartialKcContext?: DeepPartial<
-            Extract<ExtendKcContext<KcContextExtension>, { pageId: PageId }>
-        >;
-    }): {
-        kcContext: PageId extends undefined
-            ? ExtendKcContext<KcContextExtension> | undefined
-            : Extract<ExtendKcContext<KcContextExtension>, { pageId: PageId }>;
-    } {
-        const { mockPageId, storyPartialKcContext } = params ?? {};
-
-        const realKcContext = getKcContextFromWindow<KcContextExtension>();
-
-        if (mockPageId !== undefined && realKcContext === undefined) {
-            //TODO maybe trow if no mock fo custom page
-
-            warn_that_mock_is_enbaled: {
-                if (isStorybook) {
-                    break warn_that_mock_is_enbaled;
-                }
-
-                console.log(
-                    `%cKeycloakify: ${symToStr({
-                        mockPageId
-                    })} set to ${mockPageId}.`,
-                    "background: red; color: yellow; font-size: medium"
-                );
-            }
-
-            const kcContextDefaultMock = kcContextMocks.find(
-                ({ pageId }) => pageId === mockPageId
-            );
-
-            const partialKcContextCustomMock = (() => {
-                const out: DeepPartial<ExtendKcContext<KcContextExtension>> = {};
-
-                const mockDataPick = mockData?.find(
-                    ({ pageId }) => pageId === mockPageId
-                );
-
-                if (mockDataPick !== undefined) {
-                    deepAssign({
-                        target: out,
-                        source: mockDataPick
-                    });
-                }
-
-                if (storyPartialKcContext !== undefined) {
-                    deepAssign({
-                        target: out,
-                        source: storyPartialKcContext
-                    });
-                }
-
-                return Object.keys(out).length === 0 ? undefined : out;
-            })();
-
-            if (
-                kcContextDefaultMock === undefined &&
-                partialKcContextCustomMock === undefined
-            ) {
-                console.warn(
-                    [
-                        `WARNING: You declared the non build in page ${mockPageId} but you didn't `,
-                        `provide mock data needed to debug the page outside of Keycloak as you are trying to do now.`,
-                        `Please check the documentation of the getKcContext function`
-                    ].join("\n")
-                );
-            }
-
-            const kcContext: any = {};
-
-            deepAssign({
-                target: kcContext,
-                source:
-                    kcContextDefaultMock !== undefined
-                        ? kcContextDefaultMock
-                        : { pageId: mockPageId, ...kcContextCommonMock }
-            });
-
-            if (partialKcContextCustomMock !== undefined) {
-                deepAssign({
-                    target: kcContext,
-                    source: partialKcContextCustomMock
-                });
-            }
-
-            if (mockProperties !== undefined) {
-                deepAssign({
-                    target: kcContext.properties,
-                    source: mockProperties
-                });
-            }
-
-            return { kcContext };
-        }
-
-        if (realKcContext === undefined) {
-            return { kcContext: undefined as any };
-        }
-
-        if (realKcContext.themeType !== "account") {
-            return { kcContext: undefined as any };
-        }
-
-        return { kcContext: realKcContext as any };
-    }
-
-    return { getKcContext };
-}
diff --git a/src/account/kcContext/getKcContext.ts b/src/account/kcContext/getKcContext.ts
deleted file mode 100644
index bd6039e8..00000000
--- a/src/account/kcContext/getKcContext.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import type { DeepPartial } from "keycloakify/tools/DeepPartial";
-import type { ExtendKcContext } from "./getKcContextFromWindow";
-import { createGetKcContext } from "./createGetKcContext";
-
-/** NOTE: We now recommend using createGetKcContext instead of this function to make storybook integration easier
- *  See: https://github.com/keycloakify/keycloakify-starter/blob/main/src/keycloak-theme/account/kcContext.ts
- */
-export function getKcContext<
-    KcContextExtension extends { pageId: string } = never
->(params?: {
-    mockPageId?: ExtendKcContext<KcContextExtension>["pageId"];
-    mockData?: readonly DeepPartial<ExtendKcContext<KcContextExtension>>[];
-}): { kcContext: ExtendKcContext<KcContextExtension> | undefined } {
-    const { mockPageId, mockData } = params ?? {};
-
-    const { getKcContext } = createGetKcContext({
-        mockData
-    });
-
-    const { kcContext } = getKcContext({ mockPageId });
-
-    return { kcContext };
-}
diff --git a/src/account/kcContext/getKcContextFromWindow.ts b/src/account/kcContext/getKcContextFromWindow.ts
deleted file mode 100644
index f29ea9bf..00000000
--- a/src/account/kcContext/getKcContextFromWindow.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { AndByDiscriminatingKey } from "keycloakify/tools/AndByDiscriminatingKey";
-import { nameOfTheGlobal } from "keycloakify/bin/shared/constants";
-import type { KcContext } from "./KcContext";
-
-export type ExtendKcContext<KcContextExtension extends { pageId: string }> = [
-    KcContextExtension
-] extends [never]
-    ? KcContext
-    : AndByDiscriminatingKey<"pageId", KcContextExtension & KcContext.Common, KcContext>;
-
-export function getKcContextFromWindow<
-    KcContextExtension extends { pageId: string } = never
->(): ExtendKcContext<KcContextExtension> | undefined {
-    return typeof window === "undefined" ? undefined : (window as any)[nameOfTheGlobal];
-}
diff --git a/src/account/kcContext/getKcContextMock.ts b/src/account/kcContext/getKcContextMock.ts
new file mode 100644
index 00000000..23b32d03
--- /dev/null
+++ b/src/account/kcContext/getKcContextMock.ts
@@ -0,0 +1,80 @@
+import type { ExtendKcContext, KcContext as KcContextBase } from "./KcContext";
+import type { LoginThemePageId } from "keycloakify/bin/shared/constants";
+import type { DeepPartial } from "keycloakify/tools/DeepPartial";
+import { deepAssign } from "keycloakify/tools/deepAssign";
+import { structuredCloneButFunctions } from "keycloakify/tools/structuredCloneButFunctions";
+import { kcContextMocks, kcContextCommonMock } from "./kcContextMocks";
+import { exclude } from "tsafe/exclude";
+
+export function createGetKcContextMock<
+    KcContextExtraProperties extends { properties?: Record<string, string | undefined> },
+    KcContextExtraPropertiesPerPage extends Record<
+        `${string}.ftl`,
+        Record<string, unknown>
+    >
+>(params: {
+    kcContextExtraProperties: KcContextExtraProperties;
+    kcContextExtraPropertiesPerPage: KcContextExtraPropertiesPerPage;
+    overrides?: DeepPartial<KcContextExtraProperties & KcContextBase.Common>;
+    overridesPerPage?: {
+        [PageId in
+            | LoginThemePageId
+            | keyof KcContextExtraPropertiesPerPage]?: DeepPartial<
+            Extract<
+                ExtendKcContext<
+                    KcContextExtraProperties,
+                    KcContextExtraPropertiesPerPage
+                >,
+                { pageId: PageId }
+            >
+        >;
+    };
+}) {
+    const {
+        kcContextExtraProperties,
+        kcContextExtraPropertiesPerPage,
+        overrides: overrides_global,
+        overridesPerPage: overridesPerPage_global
+    } = params;
+
+    type KcContext = ExtendKcContext<
+        KcContextExtraProperties,
+        KcContextExtraPropertiesPerPage
+    >;
+
+    function getKcContextMock<
+        PageId extends LoginThemePageId | keyof KcContextExtraPropertiesPerPage
+    >(params: {
+        pageId: PageId;
+        overrides?: DeepPartial<Extract<KcContext, { pageId: PageId }>>;
+    }): Extract<KcContext, { pageId: PageId }> {
+        const { pageId, overrides } = params;
+
+        const kcContextMock = structuredCloneButFunctions(
+            kcContextMocks.find(kcContextMock => kcContextMock.pageId === pageId) ?? {
+                ...kcContextCommonMock,
+                pageId
+            }
+        );
+
+        [
+            kcContextExtraProperties,
+            kcContextExtraPropertiesPerPage[pageId],
+            overrides_global,
+            overridesPerPage_global?.[pageId],
+            overrides
+        ]
+            .filter(exclude(undefined))
+            .forEach(overrides =>
+                deepAssign({
+                    target: kcContextMock,
+                    source: overrides
+                })
+            );
+
+        // @ts-expect-error
+        return kcContextMock;
+    }
+
+    return { getKcContextMock };
+}
diff --git a/src/account/kcContext/index.ts b/src/account/kcContext/index.ts
index 7ecbb2f3..5990af8d 100644
--- a/src/account/kcContext/index.ts
+++ b/src/account/kcContext/index.ts
@@ -1 +1,2 @@
-export type { KcContext } from "./KcContext";
+export type { ExtendKcContext, KcContext } from "./KcContext";
+export { createGetKcContextMock } from "./getKcContextMock";
diff --git a/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl b/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl
index 8ddf8afe..ef4a1276 100644
--- a/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl
+++ b/src/bin/keycloakify/generateFtl/ftl_object_to_js_code_declaring_an_object.ftl
@@ -288,13 +288,11 @@ function decodeHtmlEntities(htmlStr){
                         are_same_path(path, [])
                     ) || (
                         <#-- attributesByName adds a lot of noise to the output and is not needed -->
-                        key == "attributesByName" &&
-                        (
-                            are_same_path(path, ["profile"]) || 
-                            are_same_path(path, ["register"])
-                        )
-                    ) || (
                         key == "attributes" &&
+                        are_same_path(path, ["profile"]) 
+                    ) || (
+                        <#-- We already have the attributes in profile speedup the rendering by filtering it out from the register object -->
+                        (key == "attributes" || key == "attributesByName") &&
                         are_same_path(path, ["register"])
                     )
                 >
diff --git a/src/login/index.ts b/src/login/index.ts
index a0610265..356132ea 100644
--- a/src/login/index.ts
+++ b/src/login/index.ts
@@ -3,9 +3,12 @@ import Fallback from "keycloakify/login/Fallback";
 export default Fallback;
 
 export { useDownloadTerms } from "keycloakify/login/lib/useDownloadTerms";
-export { getKcContext } from "keycloakify/login/kcContext/getKcContext";
-export { createGetKcContext } from "keycloakify/login/kcContext/createGetKcContext";
-export type { LoginThemePageId as PageId } from "keycloakify/bin/shared/constants";
 export { createUseI18n } from "keycloakify/login/i18n/i18n";
+export type {
+    ExtendKcContext,
+    Attribute,
+    PasswordPolicies
+} from "keycloakify/login/kcContext";
+export { createGetKcContextMock } from "keycloakify/login/kcContext";
 
 export type { PageProps } from "keycloakify/login/pages/PageProps";
diff --git a/src/login/kcContext/KcContext.ts b/src/login/kcContext/KcContext.ts
index 834faf1b..c633b271 100644
--- a/src/login/kcContext/KcContext.ts
+++ b/src/login/kcContext/KcContext.ts
@@ -3,14 +3,28 @@ import type {
     LoginThemePageId,
     nameOfTheLocalizationRealmOverridesUserProfileProperty
 } from "keycloakify/bin/shared/constants";
+import type { ExtractAfterStartingWith } from "keycloakify/tools/ExtractAfterStartingWith";
+import type { ValueOf } from "keycloakify/tools/ValueOf";
 import { assert } from "tsafe/assert";
 import type { Equals } from "tsafe";
 import type { MessageKey } from "../i18n/i18n";
 
-type ExtractAfterStartingWith<
-    Prefix extends string,
-    StrEnum
-> = StrEnum extends `${Prefix}${infer U}` ? U : never;
+export type ExtendKcContext<
+    KcContextExtraProperties extends { properties?: Record<string, string | undefined> },
+    KcContextExtraPropertiesPerPage extends Record<string, Record<string, unknown>>
+> = ValueOf<{
+    [PageId in keyof KcContextExtraPropertiesPerPage | KcContext["pageId"]]: Extract<
+        KcContext,
+        { pageId: PageId }
+    > extends never
+        ? KcContext.Common &
+              KcContextExtraProperties & {
+                  pageId: PageId;
+              } & KcContextExtraPropertiesPerPage[PageId]
+        : Extract<KcContext, { pageId: PageId }> &
+              KcContextExtraProperties &
+              KcContextExtraPropertiesPerPage[PageId];
+}>;
 
 /** Take theses type definition with a grain of salt.
  * Some values might be undefined on some pages.
@@ -138,12 +152,12 @@ export declare namespace KcContext {
 
             getFirstError: (...fieldNames: string[]) => string;
         };
-        properties: Record<string, string | undefined>;
         authenticationSession?: {
             authSessionId: string;
             tabId: string;
             ssoLoginInOtherTabsUrl: string;
         };
+        properties: {};
         __localizationRealmOverridesUserProfile?: Record<string, string>;
     };
 
@@ -585,7 +599,7 @@ export declare namespace KcContext {
 }
 
 export type UserProfile = {
-    attributes: Attribute[];
+    attributesByName: Record<string, Attribute>;
     html5DataAnnotations?: Record<string, string>;
 };
 
@@ -683,31 +697,31 @@ export type Attribute = {
         | "photo";
 };
 
-export type Validators = Partial<{
-    length: Validators.DoIgnoreEmpty & Validators.Range;
-    integer: Validators.DoIgnoreEmpty & Validators.Range;
-    email: Validators.DoIgnoreEmpty;
-    pattern: Validators.DoIgnoreEmpty & Validators.ErrorMessage & { pattern: string };
-    options: Validators.Options;
-    multivalued: Validators.DoIgnoreEmpty & Validators.Range;
+export type Validators = {
+    length?: Validators.DoIgnoreEmpty & Validators.Range;
+    integer?: Validators.DoIgnoreEmpty & Validators.Range;
+    email?: Validators.DoIgnoreEmpty;
+    pattern?: Validators.DoIgnoreEmpty & Validators.ErrorMessage & { pattern: string };
+    options?: Validators.Options;
+    multivalued?: Validators.DoIgnoreEmpty & Validators.Range;
     // NOTE: Following are the validators for which we don't implement client side validation yet
     // or for which the validation can't be performed on the client side.
     /*
-    double: Validators.DoIgnoreEmpty & Validators.Range;
-    "up-immutable-attribute": {};
-    "up-attribute-required-by-metadata-value": {};
-    "up-username-has-value": {};
-    "up-duplicate-username": {};
-    "up-username-mutation": {};
-    "up-email-exists-as-username": {};
-    "up-blank-attribute-value": Validators.ErrorMessage & { "fail-on-null": boolean; };
-    "up-duplicate-email": {};
-    "local-date": Validators.DoIgnoreEmpty;
-    "person-name-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage;
-    uri: Validators.DoIgnoreEmpty;
-    "username-prohibited-characters": Validators.DoIgnoreEmpty & Validators.ErrorMessage;
+    double?: Validators.DoIgnoreEmpty & Validators.Range;
+    "up-immutable-attribute"?: {};
+    "up-attribute-required-by-metadata-value"?: {};
+    "up-username-has-value"?: {};
+    "up-duplicate-username"?: {};
+    "up-username-mutation"?: {};
+    "up-email-exists-as-username"?: {};
+    "up-blank-attribute-value"?: Validators.ErrorMessage & { "fail-on-null": boolean; };
+    "up-duplicate-email"?: {};
+    "local-date"?: Validators.DoIgnoreEmpty;
+    "person-name-prohibited-characters"?: Validators.DoIgnoreEmpty & Validators.ErrorMessage;
+    uri?: Validators.DoIgnoreEmpty;
+    "username-prohibited-characters"?: Validators.DoIgnoreEmpty & Validators.ErrorMessage;
     */
-}>;
+};
 
 export declare namespace Validators {
     export type DoIgnoreEmpty = {
diff --git a/src/login/kcContext/createGetKcContext.ts b/src/login/kcContext/createGetKcContext.ts
deleted file mode 100644
index b051d652..00000000
--- a/src/login/kcContext/createGetKcContext.ts
+++ /dev/null
@@ -1,199 +0,0 @@
-import type { KcContext, Attribute } from "./KcContext";
-import { kcContextMocks, kcContextCommonMock } from "./kcContextMocks";
-import type { DeepPartial } from "keycloakify/tools/DeepPartial";
-import { deepAssign } from "keycloakify/tools/deepAssign";
-import { isStorybook } from "keycloakify/lib/isStorybook";
-import { id } from "tsafe/id";
-import { exclude } from "tsafe/exclude";
-import { assert } from "tsafe/assert";
-import type { ExtendKcContext } from "./getKcContextFromWindow";
-import { getKcContextFromWindow } from "./getKcContextFromWindow";
-import { symToStr } from "tsafe/symToStr";
-
-export function createGetKcContext<
-    KcContextExtension extends { pageId: string } = never
->(params?: {
-    mockData?: readonly DeepPartial<ExtendKcContext<KcContextExtension>>[];
-    mockProperties?: Record<string, string>;
-}) {
-    const { mockData, mockProperties } = params ?? {};
-
-    function getKcContext<
-        PageId extends
-            | ExtendKcContext<KcContextExtension>["pageId"]
-            | undefined = undefined
-    >(params?: {
-        mockPageId?: PageId;
-        storyPartialKcContext?: DeepPartial<
-            Extract<ExtendKcContext<KcContextExtension>, { pageId: PageId }>
-        >;
-    }): {
-        kcContext: PageId extends undefined
-            ? ExtendKcContext<KcContextExtension> | undefined
-            : Extract<ExtendKcContext<KcContextExtension>, { pageId: PageId }>;
-    } {
-        const { mockPageId, storyPartialKcContext } = params ?? {};
-
-        const realKcContext = getKcContextFromWindow<KcContextExtension>();
-
-        if (mockPageId !== undefined && realKcContext === undefined) {
-            //TODO maybe trow if no mock fo custom page
-
-            warn_that_mock_is_enabled: {
-                if (isStorybook) {
-                    break warn_that_mock_is_enabled;
-                }
-
-                console.log(
-                    `%cKeycloakify: ${symToStr({
-                        mockPageId
-                    })} set to ${mockPageId}.`,
-                    "background: red; color: yellow; font-size: medium"
-                );
-            }
-
-            const kcContextDefaultMock = kcContextMocks.find(
-                ({ pageId }) => pageId === mockPageId
-            );
-
-            const partialKcContextCustomMock = (() => {
-                const out: DeepPartial<ExtendKcContext<KcContextExtension>> = {};
-
-                const mockDataPick = mockData?.find(
-                    ({ pageId }) => pageId === mockPageId
-                );
-
-                if (mockDataPick !== undefined) {
-                    deepAssign({
-                        target: out,
-                        source: mockDataPick
-                    });
-                }
-
-                if (storyPartialKcContext !== undefined) {
-                    deepAssign({
-                        target: out,
-                        source: storyPartialKcContext
-                    });
-                }
-
-                return Object.keys(out).length === 0 ? undefined : out;
-            })();
-
-            if (
-                kcContextDefaultMock === undefined &&
-                partialKcContextCustomMock === undefined
-            ) {
-                console.warn(
-                    [
-                        `WARNING: You declared the non build in page ${mockPageId} but you didn't `,
-                        `provide mock data needed to debug the page outside of Keycloak as you are trying to do now.`,
-                        `Please check the documentation of the getKcContext function`
-                    ].join("\n")
-                );
-            }
-
-            const kcContext: any = {};
-
-            deepAssign({
-                target: kcContext,
-                source:
-                    kcContextDefaultMock !== undefined
-                        ? kcContextDefaultMock
-                        : { pageId: mockPageId, ...kcContextCommonMock }
-            });
-
-            if (partialKcContextCustomMock !== undefined) {
-                deepAssign({
-                    target: kcContext,
-                    source: partialKcContextCustomMock
-                });
-
-                if ("profile" in partialKcContextCustomMock) {
-                    assert(
-                        kcContextDefaultMock !== undefined &&
-                            "profile" in kcContextDefaultMock
-                    );
-
-                    const { attributes } = kcContextDefaultMock.profile;
-
-                    id<KcContext.Register>(kcContext).profile.attributes = [];
-
-                    const partialAttributes = [
-                        ...((
-                            partialKcContextCustomMock as DeepPartial<KcContext.Register>
-                        ).profile?.attributes ?? [])
-                    ].filter(exclude(undefined));
-
-                    attributes.forEach(attribute => {
-                        const partialAttribute = partialAttributes.find(
-                            ({ name }) => name === attribute.name
-                        );
-
-                        const augmentedAttribute: Attribute = {} as any;
-
-                        deepAssign({
-                            target: augmentedAttribute,
-                            source: attribute
-                        });
-
-                        if (partialAttribute !== undefined) {
-                            partialAttributes.splice(
-                                partialAttributes.indexOf(partialAttribute),
-                                1
-                            );
-
-                            deepAssign({
-                                target: augmentedAttribute,
-                                source: partialAttribute
-                            });
-                        }
-
-                        id<KcContext.Register>(kcContext).profile.attributes.push(
-                            augmentedAttribute
-                        );
-                    });
-
-                    partialAttributes
-                        .map(partialAttribute => ({
-                            validators: {},
-                            ...partialAttribute
-                        }))
-                        .forEach(partialAttribute => {
-                            const { name } = partialAttribute;
-
-                            assert(
-                                name !== undefined,
-                                "If you define a mock attribute it must have at least a name"
-                            );
-
-                            id<KcContext.Register>(kcContext).profile.attributes.push(
-                                partialAttribute as any
-                            );
-                        });
-                }
-            }
-
-            if (mockProperties !== undefined) {
-                deepAssign({
-                    target: kcContext.properties,
-                    source: mockProperties
-                });
-            }
-
-            return { kcContext };
-        }
-
-        if (realKcContext === undefined) {
-            return { kcContext: undefined as any };
-        }
-
-        if (realKcContext.themeType !== "login") {
-            return { kcContext: undefined as any };
-        }
-
-        return { kcContext: realKcContext as any };
-    }
-
-    return { getKcContext };
-}
diff --git a/src/login/kcContext/getKcContext.ts b/src/login/kcContext/getKcContext.ts
deleted file mode 100644
index 1e062586..00000000
--- a/src/login/kcContext/getKcContext.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import type { DeepPartial } from "keycloakify/tools/DeepPartial";
-import type { ExtendKcContext } from "./getKcContextFromWindow";
-import { createGetKcContext } from "./createGetKcContext";
-
-/** NOTE: We now recommend using createGetKcContext instead of this function to make storybook integration easier
- *  See: https://github.com/keycloakify/keycloakify-starter/blob/main/src/keycloak-theme/account/kcContext.ts
- */
-export function getKcContext<
-    KcContextExtension extends { pageId: string } = never
->(params?: {
-    mockPageId?: ExtendKcContext<KcContextExtension>["pageId"];
-    mockData?: readonly DeepPartial<ExtendKcContext<KcContextExtension>>[];
-}): { kcContext: ExtendKcContext<KcContextExtension> | undefined } {
-    const { mockPageId, mockData } = params ?? {};
-
-    const { getKcContext } = createGetKcContext<KcContextExtension>({
-        mockData
-    });
-
-    const { kcContext } = getKcContext({ mockPageId });
-
-    return { kcContext };
-}
diff --git a/src/login/kcContext/getKcContextFromWindow.ts b/src/login/kcContext/getKcContextFromWindow.ts
deleted file mode 100644
index ab5f31c4..00000000
--- a/src/login/kcContext/getKcContextFromWindow.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import type { KcContext } from "./KcContext";
-import type { AndByDiscriminatingKey } from "keycloakify/tools/AndByDiscriminatingKey";
-import { nameOfTheGlobal } from "keycloakify/bin/shared/constants";
-
-export type ExtendKcContext<KcContextExtension extends { pageId: string }> = [
-    KcContextExtension
-] extends [never]
-    ? KcContext
-    : AndByDiscriminatingKey<"pageId", KcContextExtension & KcContext.Common, KcContext>;
-
-export function getKcContextFromWindow<
-    KcContextExtension extends { pageId: string } = never
->(): ExtendKcContext<KcContextExtension> | undefined {
-    return typeof window === "undefined" ? undefined : (window as any)[nameOfTheGlobal];
-}
diff --git a/src/login/kcContext/getKcContextMock.ts b/src/login/kcContext/getKcContextMock.ts
new file mode 100644
index 00000000..23b32d03
--- /dev/null
+++ b/src/login/kcContext/getKcContextMock.ts
@@ -0,0 +1,80 @@
+import type { ExtendKcContext, KcContext as KcContextBase } from "./KcContext";
+import type { LoginThemePageId } from "keycloakify/bin/shared/constants";
+import type { DeepPartial } from "keycloakify/tools/DeepPartial";
+import { deepAssign } from "keycloakify/tools/deepAssign";
+import { structuredCloneButFunctions } from "keycloakify/tools/structuredCloneButFunctions";
+import { kcContextMocks, kcContextCommonMock } from "./kcContextMocks";
+import { exclude } from "tsafe/exclude";
+
+export function createGetKcContextMock<
+    KcContextExtraProperties extends { properties?: Record<string, string | undefined> },
+    KcContextExtraPropertiesPerPage extends Record<
+        `${string}.ftl`,
+        Record<string, unknown>
+    >
+>(params: {
+    kcContextExtraProperties: KcContextExtraProperties;
+    kcContextExtraPropertiesPerPage: KcContextExtraPropertiesPerPage;
+    overrides?: DeepPartial<KcContextExtraProperties & KcContextBase.Common>;
+    overridesPerPage?: {
+        [PageId in
+            | LoginThemePageId
+            | keyof KcContextExtraPropertiesPerPage]?: DeepPartial<
+            Extract<
+                ExtendKcContext<
+                    KcContextExtraProperties,
+                    KcContextExtraPropertiesPerPage
+                >,
+                { pageId: PageId }
+            >
+        >;
+    };
+}) {
+    const {
+        kcContextExtraProperties,
+        kcContextExtraPropertiesPerPage,
+        overrides: overrides_global,
+        overridesPerPage: overridesPerPage_global
+    } = params;
+
+    type KcContext = ExtendKcContext<
+        KcContextExtraProperties,
+        KcContextExtraPropertiesPerPage
+    >;
+
+    function getKcContextMock<
+        PageId extends LoginThemePageId | keyof KcContextExtraPropertiesPerPage
+    >(params: {
+        pageId: PageId;
+        overrides?: DeepPartial<Extract<KcContext, { pageId: PageId }>>;
+    }): Extract<KcContext, { pageId: PageId }> {
+        const { pageId, overrides } = params;
+
+        const kcContextMock = structuredCloneButFunctions(
+            kcContextMocks.find(kcContextMock => kcContextMock.pageId === pageId) ?? {
+                ...kcContextCommonMock,
+                pageId
+            }
+        );
+
+        [
+            kcContextExtraProperties,
+            kcContextExtraPropertiesPerPage[pageId],
+            overrides_global,
+            overridesPerPage_global?.[pageId],
+            overrides
+        ]
+            .filter(exclude(undefined))
+            .forEach(overrides =>
+                deepAssign({
+                    target: kcContextMock,
+                    source: overrides
+                })
+            );
+
+        // @ts-expect-error
+        return kcContextMock;
+    }
+
+    return { getKcContextMock };
+}
diff --git a/src/login/kcContext/index.ts b/src/login/kcContext/index.ts
index 7ecbb2f3..18737f02 100644
--- a/src/login/kcContext/index.ts
+++ b/src/login/kcContext/index.ts
@@ -1 +1,7 @@
-export type { KcContext } from "./KcContext";
+export type {
+    ExtendKcContext,
+    KcContext,
+    Attribute,
+    PasswordPolicies
+} from "./KcContext";
+export { createGetKcContextMock } from "./getKcContextMock";
diff --git a/src/login/kcContext/kcContextMocks.ts b/src/login/kcContext/kcContextMocks.ts
index 9d81ecc9..7d74c96a 100644
--- a/src/login/kcContext/kcContextMocks.ts
+++ b/src/login/kcContext/kcContextMocks.ts
@@ -9,71 +9,73 @@ import { id } from "tsafe/id";
 import { assert, type Equals } from "tsafe/assert";
 import { BASE_URL } from "keycloakify/lib/BASE_URL";
 
-const attributes: Attribute[] = [
-    {
-        validators: {
-            length: {
-                "ignore.empty.value": true,
-                min: "3",
-                max: "255"
-            }
-        },
-        displayName: "${username}",
-        annotations: {},
-        required: true,
-        autocomplete: "username",
-        readOnly: false,
-        name: "username",
-        value: "xxxx"
-    },
-    {
-        validators: {
-            length: {
-                max: "255",
-                "ignore.empty.value": true
+const attributesByName = Object.fromEntries(
+    id<Attribute[]>([
+        {
+            validators: {
+                length: {
+                    "ignore.empty.value": true,
+                    min: "3",
+                    max: "255"
+                }
             },
-            email: {
-                "ignore.empty.value": true
+            displayName: "${username}",
+            annotations: {},
+            required: true,
+            autocomplete: "username",
+            readOnly: false,
+            name: "username",
+            value: "xxxx"
+        },
+        {
+            validators: {
+                length: {
+                    max: "255",
+                    "ignore.empty.value": true
+                },
+                email: {
+                    "ignore.empty.value": true
+                },
+                pattern: {
+                    "ignore.empty.value": true,
+                    pattern: "gmail\\.com$"
+                }
             },
-            pattern: {
-                "ignore.empty.value": true,
-                pattern: "gmail\\.com$"
-            }
+            displayName: "${email}",
+            annotations: {},
+            required: true,
+            autocomplete: "email",
+            readOnly: false,
+            name: "email"
         },
-        displayName: "${email}",
-        annotations: {},
-        required: true,
-        autocomplete: "email",
-        readOnly: false,
-        name: "email"
-    },
-    {
-        validators: {
-            length: {
-                max: "255",
-                "ignore.empty.value": true
-            }
+        {
+            validators: {
+                length: {
+                    max: "255",
+                    "ignore.empty.value": true
+                }
+            },
+            displayName: "${firstName}",
+            annotations: {},
+            required: true,
+            readOnly: false,
+            name: "firstName"
         },
-        displayName: "${firstName}",
-        annotations: {},
-        required: true,
-        readOnly: false,
-        name: "firstName"
-    },
-    {
-        validators: {
-            length: {
-                max: "255",
-                "ignore.empty.value": true
-            }
-        },
-        displayName: "${lastName}",
-        annotations: {},
-        required: true,
-        readOnly: false,
-        name: "lastName"
-    }
-];
+        {
+            validators: {
+                length: {
+                    max: "255",
+                    "ignore.empty.value": true
+                }
+            },
+            displayName: "${lastName}",
+            annotations: {},
+            required: true,
+            readOnly: false,
+            name: "lastName"
+        }
+    ]).map(attribute => [attribute.name, attribute])
+);
 
 const resourcesPath = `${BASE_URL}${keycloak_resources}/login/resources`;
 
@@ -265,7 +267,7 @@ export const kcContextMocks = [
         recaptchaRequired: false,
         pageId: "register.ftl",
         profile: {
-            attributes
+            attributesByName
         },
         scripts: [
             //"https://www.google.com/recaptcha/api.js"
@@ -416,7 +418,7 @@ export const kcContextMocks = [
         ...kcContextCommonMock,
         pageId: "login-update-profile.ftl",
         profile: {
-            attributes
+            attributesByName
         }
     }),
     id<KcContext.LoginIdpLinkConfirm>({
@@ -472,14 +474,16 @@ export const kcContextMocks = [
         ...kcContextCommonMock,
         pageId: "idp-review-user-profile.ftl",
         profile: {
-            attributes
+            attributesByName
         }
     }),
     id<KcContext.UpdateEmail>({
         ...kcContextCommonMock,
         pageId: "update-email.ftl",
         profile: {
-            attributes: attributes.filter(attribute => attribute.name === "email")
+            attributesByName: {
+                email: attributesByName["email"]
+            }
         }
     }),
     id<KcContext.SelectAuthenticator>({
diff --git a/src/login/lib/useUserProfileForm.tsx b/src/login/lib/useUserProfileForm.tsx
index c265a470..309d7a93 100644
--- a/src/login/lib/useUserProfileForm.tsx
+++ b/src/login/lib/useUserProfileForm.tsx
@@ -9,7 +9,7 @@ import type { KcContext, PasswordPolicies } from "keycloakify/login/kcContext/Kc
 import { assert, type Equals } from "tsafe/assert";
 import { formatNumber } from "keycloakify/tools/formatNumber";
 import { createUseInsertScriptTags } from "keycloakify/tools/useInsertScriptTags";
-import { structuredCloneButFunctions } from "tools/structuredCloneButFunctions";
+import { structuredCloneButFunctions } from "keycloakify/tools/structuredCloneButFunctions";
 import type { I18n } from "../i18n";
 
 export type FormFieldError = {
@@ -68,7 +68,7 @@ export type FormAction =
 export type KcContextLike = {
     messagesPerField: Pick<KcContext.Common["messagesPerField"], "existsError" | "get">;
     profile: {
-        attributes: Attribute[];
+        attributesByName: Record<string, Attribute>;
         html5DataAnnotations?: Record<string, string>;
     };
     passwordRequired?: boolean;
@@ -137,7 +137,7 @@ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTy
 
             const attributes = (() => {
                 retrocompat_patch: {
-                    if ("profile" in kcContext && "attributes" in kcContext.profile && kcContext.profile.attributes.length !== 0) {
+                    if ("profile" in kcContext && "attributes" in kcContext.profile && Object.keys(kcContext.profile.attributesByName).length !== 0) {
                         break retrocompat_patch;
                     }
 
@@ -217,7 +217,7 @@ export function useUserProfileForm(params: ParamsOfUseUserProfileForm): ReturnTy
                     assert(false, "Unable to mock user profile from the current kcContext");
                 }
 
-                return kcContext.profile.attributes.map(attribute_pre_group_patch => {
+                return Object.values(kcContext.profile.attributesByName).map(attribute_pre_group_patch => {
                     if (typeof attribute_pre_group_patch.group === "string" && attribute_pre_group_patch.group !== "") {
                         const { group, groupDisplayHeader, groupDisplayDescription, groupAnnotations, ...rest } =
                             attribute_pre_group_patch as Attribute & {
diff --git a/src/tools/AndByDiscriminatingKey.ts b/src/tools/AndByDiscriminatingKey.ts
deleted file mode 100644
index 79563580..00000000
--- a/src/tools/AndByDiscriminatingKey.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-export type AndByDiscriminatingKey<
-    DiscriminatingKey extends string,
-    U1 extends Record<DiscriminatingKey, string>,
-    U2 extends Record<DiscriminatingKey, string>
-> = AndByDiscriminatingKey.Tf1<DiscriminatingKey, U1, U1, U2>;
-
-export declare namespace AndByDiscriminatingKey {
-    export type Tf1<
-        DiscriminatingKey extends string,
-        U1,
-        U1Again extends Record<DiscriminatingKey, string>,
-        U2 extends Record<DiscriminatingKey, string>
-    > =
-        U1 extends Pick<U2, DiscriminatingKey>
-            ? Tf2<DiscriminatingKey, U1, U2, U1Again>
-            : U1Again[DiscriminatingKey] & U2[DiscriminatingKey] extends never
-              ? U1 | U2
-              : U1;
-
-    export type Tf2<
-        DiscriminatingKey extends string,
-        SingletonU1 extends Record<DiscriminatingKey, string>,
-        U2,
-        U1 extends Record<DiscriminatingKey, string>
-    > =
-        U2 extends Pick<SingletonU1, DiscriminatingKey>
-            ? U2 & SingletonU1
-            : U2 extends Pick<U1, DiscriminatingKey>
-              ? never
-              : U2;
-}
diff --git a/src/tools/ExtractAfterStartingWith.ts b/src/tools/ExtractAfterStartingWith.ts
new file mode 100644
index 00000000..9674b22e
--- /dev/null
+++ b/src/tools/ExtractAfterStartingWith.ts
@@ -0,0 +1,4 @@
+export type ExtractAfterStartingWith<
+    Prefix extends string,
+    StrEnum
+> = StrEnum extends `${Prefix}${infer U}` ? U : never;
diff --git a/src/tools/ValueOf.ts b/src/tools/ValueOf.ts
new file mode 100644
index 00000000..031db534
--- /dev/null
+++ b/src/tools/ValueOf.ts
@@ -0,0 +1,2 @@
+/** Pendant of `keyof T` */
+export type ValueOf<T> = T[keyof T];
diff --git a/src/tools/deepAssign.ts b/src/tools/deepAssign.ts
index 6c7c693c..04fa75b9 100644
--- a/src/tools/deepAssign.ts
+++ b/src/tools/deepAssign.ts
@@ -2,44 +2,60 @@ import { assert } from "tsafe/assert";
 import { is } from "tsafe/is";
 import { structuredCloneButFunctions } from "./structuredCloneButFunctions";
 
-//Warning: Be mindful that because of array this is not idempotent.
+/** NOTE: Array a copied over, not merged. */
 export function deepAssign(params: {
     target: Record<string, unknown>;
     source: Record<string, unknown>;
-}) {
-    const { target } = params;
-
-    const source = structuredCloneButFunctions(params.source);
+}): void {
+    const { target, source } = params;
 
     Object.keys(source).forEach(key => {
         var dereferencedSource = source[key];
 
+        if (dereferencedSource === undefined) {
+            delete target[key];
+            return;
+        }
+
+        if (dereferencedSource instanceof Date) {
+            assign({
+                target,
+                key,
+                value: new Date(dereferencedSource.getTime())
+            });
+
+            return;
+        }
+
+        if (dereferencedSource instanceof Array) {
+            assign({
+                target,
+                key,
+                value: structuredCloneButFunctions(dereferencedSource)
+            });
+
+            return;
+        }
+
         if (
-            target[key] === undefined ||
             dereferencedSource instanceof Function ||
             !(dereferencedSource instanceof Object)
         ) {
-            Object.defineProperty(target, key, {
-                enumerable: true,
-                writable: true,
-                configurable: true,
+            assign({
+                target,
+                key,
                 value: dereferencedSource
             });
 
             return;
         }
 
-        const dereferencedTarget = target[key];
-
-        if (dereferencedSource instanceof Array) {
-            assert(is<unknown[]>(dereferencedTarget));
-            assert(is<unknown[]>(dereferencedSource));
-
-            dereferencedSource.forEach(entry => dereferencedTarget.push(entry));
-
-            return;
+        if (!(target[key] instanceof Object)) {
+            target[key] = {};
         }
 
+        const dereferencedTarget = target[key];
+
         assert(is<Record<string, unknown>>(dereferencedTarget));
         assert(is<Record<string, unknown>>(dereferencedSource));
 
@@ -49,3 +65,18 @@ export function deepAssign(params: {
         });
     });
 }
+
+function assign(params: {
+    target: Record<string, unknown>;
+    key: string;
+    value: unknown;
+}): void {
+    const { target, key, value } = params;
+
+    Object.defineProperty(target, key, {
+        enumerable: true,
+        writable: true,
+        configurable: true,
+        value
+    });
+}
diff --git a/stories/account/createPageStory.tsx b/stories/account/createPageStory.tsx
index d768e803..add3e5f6 100644
--- a/stories/account/createPageStory.tsx
+++ b/stories/account/createPageStory.tsx
@@ -1,19 +1,31 @@
 import React from "react";
-import { getKcContext, type KcContext } from "./kcContext";
+import type { KcContext } from "./kcContext";
+import { getKcContextMock } from "./kcContextMock";
 import KcApp from "./KcApp";
 import type { DeepPartial } from "../../dist/tools/DeepPartial";
 
 export function createPageStory<PageId extends KcContext["pageId"]>(params: { pageId: PageId }) {
     const { pageId } = params;
 
-    function PageStory(params: { kcContext?: DeepPartial<Extract<KcContext, { pageId: PageId }>> }) {
-        const { kcContext } = getKcContext({
-            mockPageId: pageId,
-            storyPartialKcContext: params.kcContext
+    function PageStory(props: { kcContext?: DeepPartial<Extract<KcContext, { pageId: PageId }>> }) {
+        const { kcContext: overrides } = props;
+
+        const kcContextMock = getKcContextMock({
+            pageId,
+            overrides
         });
 
-        return <KcApp kcContext={kcContext} />;
+        return <KcApp kcContext={kcContextMock} />;
     }
 
     return { PageStory };
 }
+
+export const parameters = {
+    viewMode: "story",
+    previewTabs: {
+        "storybook/docs/panel": {
+            hidden: true
+        }
+    }
+};
diff --git a/stories/account/kcContext.ts b/stories/account/kcContext.ts
index 392dcd08..e8144305 100644
--- a/stories/account/kcContext.ts
+++ b/stories/account/kcContext.ts
@@ -1,7 +1,10 @@
-import { createGetKcContext } from "../../dist/account";
+import type { ExtendKcContext } from "../../dist/account";
 
-export const { getKcContext } = createGetKcContext();
+export type KcContextExtraProperties = {};
 
-const { kcContext } = getKcContext();
+export type KcContextExtraPropertiesPerPage = {};
 
-export type KcContext = NonNullable<typeof kcContext>;
+export type KcContext = ExtendKcContext<
+    KcContextExtraProperties,
+    KcContextExtraPropertiesPerPage
+>;
diff --git a/stories/account/kcContextMock.ts b/stories/account/kcContextMock.ts
new file mode 100644
index 00000000..88069124
--- /dev/null
+++ b/stories/account/kcContextMock.ts
@@ -0,0 +1,13 @@
+import { createGetKcContextMock } from "../../dist/account";
+import type {
+    KcContextExtraProperties,
+    KcContextExtraPropertiesPerPage
+} from "./kcContext";
+
+const kcContextExtraProperties: KcContextExtraProperties = {};
+const kcContextExtraPropertiesPerPage: KcContextExtraPropertiesPerPage = {};
+
+export const { getKcContextMock } = createGetKcContextMock({
+    kcContextExtraProperties,
+    kcContextExtraPropertiesPerPage
+});
diff --git a/stories/login/kcContext.ts b/stories/login/kcContext.ts
index fca17d6c..03dec7b8 100644
--- a/stories/login/kcContext.ts
+++ b/stories/login/kcContext.ts
@@ -1,4 +1,4 @@
-import { ExtendKcContext } from "../../dist/login";
+import type { ExtendKcContext } from "../../dist/login";
 
 export type KcContextExtraProperties = {};
 
diff --git a/stories/login/kcContextMock.ts b/stories/login/kcContextMock.ts
index 53efb9c6..d248db14 100644
--- a/stories/login/kcContextMock.ts
+++ b/stories/login/kcContextMock.ts
@@ -1,5 +1,8 @@
 import { createGetKcContextMock } from "../../dist/login";
-import { KcContextExtraProperties, KcContextExtraPropertiesPerPage } from "./kcContext";
+import type {
+    KcContextExtraProperties,
+    KcContextExtraPropertiesPerPage
+} from "./kcContext";
 
 const kcContextExtraProperties: KcContextExtraProperties = {};
 const kcContextExtraPropertiesPerPage: KcContextExtraPropertiesPerPage = {};
diff --git a/test/bin/replacers.spec.ts b/test/bin/replacers.spec.ts
index da8d11fd..b33251ea 100644
--- a/test/bin/replacers.spec.ts
+++ b/test/bin/replacers.spec.ts
@@ -7,7 +7,6 @@ import {
 import { replaceImportsInInlineCssCode } from "keycloakify/bin/keycloakify/replacers/replaceImportsInInlineCssCode";
 import { same } from "evt/tools/inDepth/same";
 import { expect, it, describe } from "vitest";
-import { isSameCode } from "../tools/isSameCode";
 import {
     basenameOfTheKeycloakifyResourcesDir,
     nameOfTheGlobal
@@ -664,3 +663,10 @@ describe("inline css replacer", () => {
         });
     });
 });
+
+export function isSameCode(code1: string, code2: string): boolean {
+    const removeSpacesAndNewLines = (code: string) =>
+        code.replace(/\s/g, "").replace(/\n/g, "");
+
+    return removeSpacesAndNewLines(code1) === removeSpacesAndNewLines(code2);
+}
diff --git a/test/lib/createGetKcContext.spec.ts b/test/lib/createGetKcContext.spec.ts
deleted file mode 100644
index 368191fd..00000000
--- a/test/lib/createGetKcContext.spec.ts
+++ /dev/null
@@ -1,303 +0,0 @@
-import { createGetKcContext } from "keycloakify/login/kcContext/createGetKcContext";
-import type { ExtendKcContext } from "keycloakify/login/kcContext/getKcContextFromWindow";
-import type { KcContext } from "keycloakify/login/kcContext";
-import { same } from "evt/tools/inDepth";
-import { assert } from "tsafe/assert";
-import type { Equals } from "tsafe";
-import {
-    kcContextMocks,
-    kcContextCommonMock
-} from "keycloakify/login/kcContext/kcContextMocks";
-import { deepClone } from "keycloakify/tools/deepClone";
-import { expect, it, describe } from "vitest";
-
-describe("createGetKcContext", () => {
-    const authorizedMailDomains = [
-        "example.com",
-        "another-example.com",
-        "*.yet-another-example.com",
-        "*.example.com",
-        "hello-world.com"
-    ];
-
-    const displayName = "this is an overwritten common value";
-
-    const aNonStandardValue1 = "a non standard value 1";
-    const aNonStandardValue2 = "a non standard value 2";
-
-    type KcContextExtension =
-        | {
-              pageId: "register.ftl";
-              authorizedMailDomains: string[];
-          }
-        | {
-              pageId: "info.ftl";
-              aNonStandardValue1: string;
-          }
-        | {
-              pageId: "my-extra-page-1.ftl";
-          }
-        | {
-              pageId: "my-extra-page-2.ftl";
-              aNonStandardValue2: string;
-          };
-
-    const getKcContextProxy = (params: {
-        mockPageId: ExtendKcContext<KcContextExtension>["pageId"];
-    }) => {
-        const { mockPageId } = params;
-
-        const { getKcContext } = createGetKcContext<KcContextExtension>({
-            mockData: [
-                {
-                    pageId: "login.ftl",
-                    realm: { displayName }
-                },
-                {
-                    pageId: "info.ftl",
-                    aNonStandardValue1
-                },
-                {
-                    pageId: "register.ftl",
-                    authorizedMailDomains
-                },
-                {
-                    pageId: "my-extra-page-2.ftl",
-                    aNonStandardValue2
-                }
-            ]
-        });
-
-        const { kcContext } = getKcContext({
-            mockPageId
-        });
-
-        return { kcContext };
-    };
-    it("has proper API for login.ftl", () => {
-        const pageId = "login.ftl";
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        assert<Equals<typeof kcContext, KcContext.Login>>();
-
-        expect(
-            same(
-                //NOTE: deepClone for printIfExists or other functions...
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(
-                        kcContextMocks.find(
-                            ({ pageId: pageId_i }) => pageId_i === pageId
-                        )!
-                    );
-
-                    mock.realm.displayName = displayName;
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-
-    it("has a proper API for info.ftl", () => {
-        const pageId = "info.ftl";
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        //NOTE: I don't understand the need to add: pageId: typeof pageId; ...
-        assert<
-            Equals<
-                typeof kcContext,
-                KcContext.Info & {
-                    pageId: typeof pageId;
-                    aNonStandardValue1: string;
-                }
-            >
-        >();
-
-        expect(
-            same(
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(
-                        kcContextMocks.find(
-                            ({ pageId: pageId_i }) => pageId_i === pageId
-                        )!
-                    );
-
-                    Object.assign(mock, { aNonStandardValue1 });
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-    it("has a proper API for register.ftl", () => {
-        const pageId = "register.ftl";
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        //NOTE: I don't understand the need to add: pageId: typeof pageId; ...
-        assert<
-            Equals<
-                typeof kcContext,
-                KcContext.Register & {
-                    pageId: typeof pageId;
-                    authorizedMailDomains: string[];
-                }
-            >
-        >();
-
-        expect(
-            same(
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(
-                        kcContextMocks.find(
-                            ({ pageId: pageId_i }) => pageId_i === pageId
-                        )!
-                    );
-
-                    Object.assign(mock, { authorizedMailDomains });
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-    it("has a proper API for my-extra-page-2.ftl", () => {
-        const pageId = "my-extra-page-2.ftl";
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        assert<
-            Equals<
-                typeof kcContext,
-                KcContext.Common & {
-                    pageId: typeof pageId;
-                    aNonStandardValue2: string;
-                }
-            >
-        >();
-
-        kcContext.aNonStandardValue2;
-
-        expect(
-            same(
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(kcContextCommonMock);
-
-                    Object.assign(mock, { pageId, aNonStandardValue2 });
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-    it("has a proper API for my-extra-page-1.ftl", () => {
-        const pageId = "my-extra-page-1.ftl";
-
-        console.log("We expect a warning here =>");
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        assert<Equals<typeof kcContext, KcContext.Common & { pageId: typeof pageId }>>();
-
-        expect(
-            same(
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(kcContextCommonMock);
-
-                    Object.assign(mock, { pageId });
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-    it("returns the proper mock for login.ftl", () => {
-        const pageId = "login.ftl";
-
-        const { getKcContext } = createGetKcContext();
-
-        const { kcContext } = getKcContext({
-            mockPageId: pageId
-        });
-
-        assert<Equals<typeof kcContext, KcContext.Login>>();
-
-        assert(
-            same(
-                deepClone(kcContext),
-                deepClone(
-                    kcContextMocks.find(({ pageId: pageId_i }) => pageId_i === pageId)!
-                )
-            )
-        );
-    });
-    it("returns undefined when no mock is specified", () => {
-        const { getKcContext } = createGetKcContext();
-
-        const { kcContext } = getKcContext();
-
-        assert<Equals<typeof kcContext, KcContext | undefined>>();
-
-        assert(kcContext === undefined);
-    });
-
-    it("mock are properly overwritten", () => {
-        const { getKcContext } = createGetKcContext();
-
-        const displayName = "myDisplayName";
-
-        const { kcContext } = getKcContext({
-            mockPageId: "login.ftl",
-            storyPartialKcContext: {
-                realm: {
-                    displayName
-                }
-            }
-        });
-
-        assert<Equals<typeof kcContext, KcContext.Login>>();
-
-        assert(kcContext?.realm.displayName === displayName);
-    });
-
-    it("mockPageId doesn't have to be a singleton", () => {
-        const { getKcContext } = createGetKcContext();
-
-        const mockPageId: "login.ftl" | "register.ftl" = "login.ftl" as any;
-
-        const { kcContext } = getKcContext({
-            mockPageId
-        });
-
-        assert<Equals<typeof kcContext, KcContext.Login | KcContext.Register>>();
-    });
-
-    it("no undefined as long as we provide a mock pageId", () => {
-        const { getKcContext } = createGetKcContext();
-
-        const mockPageId: KcContext["pageId"] = "login.ftl" as any;
-
-        const { kcContext } = getKcContext({
-            mockPageId
-        });
-
-        assert<Equals<typeof kcContext, KcContext>>();
-    });
-});
diff --git a/test/lib/getKcContext.spec.ts b/test/lib/getKcContext.spec.ts
deleted file mode 100644
index 09f13d57..00000000
--- a/test/lib/getKcContext.spec.ts
+++ /dev/null
@@ -1,253 +0,0 @@
-import { getKcContext } from "keycloakify/login/kcContext/getKcContext";
-import type { ExtendKcContext } from "keycloakify/login/kcContext/getKcContextFromWindow";
-import type { KcContext } from "keycloakify/login/kcContext";
-import { same } from "evt/tools/inDepth";
-import { assert } from "tsafe/assert";
-import type { Equals } from "tsafe";
-import {
-    kcContextMocks,
-    kcContextCommonMock
-} from "keycloakify/login/kcContext/kcContextMocks";
-import { deepClone } from "keycloakify/tools/deepClone";
-import { expect, it, describe } from "vitest";
-
-describe("getKcContext", () => {
-    const authorizedMailDomains = [
-        "example.com",
-        "another-example.com",
-        "*.yet-another-example.com",
-        "*.example.com",
-        "hello-world.com"
-    ];
-
-    const displayName = "this is an overwritten common value";
-
-    const aNonStandardValue1 = "a non standard value 1";
-    const aNonStandardValue2 = "a non standard value 2";
-
-    type KcContextExtension =
-        | {
-              pageId: "register.ftl";
-              authorizedMailDomains: string[];
-          }
-        | {
-              pageId: "info.ftl";
-              aNonStandardValue1: string;
-          }
-        | {
-              pageId: "my-extra-page-1.ftl";
-          }
-        | {
-              pageId: "my-extra-page-2.ftl";
-              aNonStandardValue2: string;
-          };
-
-    const getKcContextProxy = (params: {
-        mockPageId: ExtendKcContext<KcContextExtension>["pageId"];
-    }) => {
-        const { mockPageId } = params;
-
-        const { kcContext } = getKcContext<KcContextExtension>({
-            mockPageId,
-            mockData: [
-                {
-                    pageId: "login.ftl",
-                    realm: { displayName }
-                },
-                {
-                    pageId: "info.ftl",
-                    aNonStandardValue1
-                },
-                {
-                    pageId: "register.ftl",
-                    authorizedMailDomains
-                },
-                {
-                    pageId: "my-extra-page-2.ftl",
-                    aNonStandardValue2
-                }
-            ]
-        });
-
-        return { kcContext };
-    };
-    it("has proper API for login.ftl", () => {
-        const pageId = "login.ftl";
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        assert<Equals<typeof kcContext, KcContext.Login>>();
-
-        expect(
-            same(
-                //NOTE: deepClone for printIfExists or other functions...
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(
-                        kcContextMocks.find(
-                            ({ pageId: pageId_i }) => pageId_i === pageId
-                        )!
-                    );
-
-                    mock.realm.displayName = displayName;
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-
-    it("has a proper API for info.ftl", () => {
-        const pageId = "info.ftl";
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        //NOTE: I don't understand the need to add: pageId: typeof pageId; ...
-        assert<
-            Equals<
-                typeof kcContext,
-                KcContext.Info & {
-                    pageId: typeof pageId;
-                    aNonStandardValue1: string;
-                }
-            >
-        >();
-
-        expect(
-            same(
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(
-                        kcContextMocks.find(
-                            ({ pageId: pageId_i }) => pageId_i === pageId
-                        )!
-                    );
-
-                    Object.assign(mock, { aNonStandardValue1 });
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-    it("has a proper API for register.ftl", () => {
-        const pageId = "register.ftl";
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        //NOTE: I don't understand the need to add: pageId: typeof pageId; ...
-        assert<
-            Equals<
-                typeof kcContext,
-                KcContext.Register & {
-                    pageId: typeof pageId;
-                    authorizedMailDomains: string[];
-                }
-            >
-        >();
-
-        expect(
-            same(
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(
-                        kcContextMocks.find(
-                            ({ pageId: pageId_i }) => pageId_i === pageId
-                        )!
-                    );
-
-                    Object.assign(mock, { authorizedMailDomains });
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-    it("has a proper API for my-extra-page-2.ftl", () => {
-        const pageId = "my-extra-page-2.ftl";
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        assert<
-            Equals<
-                typeof kcContext,
-                KcContext.Common & {
-                    pageId: typeof pageId;
-                    aNonStandardValue2: string;
-                }
-            >
-        >();
-
-        kcContext.aNonStandardValue2;
-
-        expect(
-            same(
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(kcContextCommonMock);
-
-                    Object.assign(mock, { pageId, aNonStandardValue2 });
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-    it("has a proper API for my-extra-page-1.ftl", () => {
-        const pageId = "my-extra-page-1.ftl";
-
-        console.log("We expect a warning here =>");
-
-        const { kcContext } = getKcContextProxy({ mockPageId: pageId });
-
-        assert(kcContext?.pageId === pageId);
-
-        assert<Equals<typeof kcContext, KcContext.Common & { pageId: typeof pageId }>>();
-
-        expect(
-            same(
-                deepClone(kcContext),
-                (() => {
-                    const mock = deepClone(kcContextCommonMock);
-
-                    Object.assign(mock, { pageId });
-
-                    return mock;
-                })()
-            )
-        ).toBe(true);
-    });
-    it("returns the proper mock for login.ftl", () => {
-        const pageId = "login.ftl";
-
-        const { kcContext } = getKcContext({
-            mockPageId: pageId
-        });
-
-        assert<Equals<typeof kcContext, KcContext | undefined>>();
-
-        assert(
-            same(
-                deepClone(kcContext),
-                deepClone(
-                    kcContextMocks.find(({ pageId: pageId_i }) => pageId_i === pageId)!
-                )
-            )
-        );
-    });
-    it("returns undefined when no mock is specified", () => {
-        const { kcContext } = getKcContext();
-
-        assert<Equals<typeof kcContext, KcContext | undefined>>();
-
-        assert(kcContext === undefined);
-    });
-});
diff --git a/test/lib/tools/AndByDiscriminatingKey.ts b/test/lib/tools/AndByDiscriminatingKey.ts
deleted file mode 100644
index 61fee1aa..00000000
--- a/test/lib/tools/AndByDiscriminatingKey.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-import { AndByDiscriminatingKey } from "keycloakify/tools/AndByDiscriminatingKey";
-import { assert } from "tsafe/assert";
-import type { Equals } from "tsafe";
-
-{
-    type Base =
-        | { pageId: "a"; onlyA: string }
-        | { pageId: "b"; onlyB: string }
-        | { pageId: "only base"; onlyBase: string };
-
-    type Extension =
-        | { pageId: "a"; onlyExtA: string }
-        | { pageId: "b"; onlyExtB: string }
-        | { pageId: "only ext"; onlyExt: string };
-
-    type Got = AndByDiscriminatingKey<"pageId", Extension, Base>;
-
-    type Expected =
-        | { pageId: "a"; onlyA: string; onlyExtA: string }
-        | { pageId: "b"; onlyB: string; onlyExtB: string }
-        | { pageId: "only base"; onlyBase: string }
-        | { pageId: "only ext"; onlyExt: string };
-
-    assert<Equals<Got, Expected>>();
-
-    const x: Got = null as any;
-
-    if (x.pageId === "a") {
-        x.onlyA;
-        x.onlyExtA;
-
-        //@ts-expect-error
-        x.onlyB;
-
-        //@ts-expect-error
-        x.onlyBase;
-
-        //@ts-expect-error
-        x.onlyExt;
-    }
-
-    if (x.pageId === "b") {
-        x.onlyB;
-        x.onlyExtB;
-
-        //@ts-expect-error
-        x.onlyA;
-
-        //@ts-expect-error
-        x.onlyBase;
-
-        //@ts-expect-error
-        x.onlyExt;
-    }
-
-    if (x.pageId === "only base") {
-        x.onlyBase;
-
-        //@ts-expect-error
-        x.onlyA;
-
-        //@ts-expect-error
-        x.onlyB;
-
-        //@ts-expect-error
-        x.onlyExt;
-    }
-
-    if (x.pageId === "only ext") {
-        x.onlyExt;
-
-        //@ts-expect-error
-        x.onlyA;
-
-        //@ts-expect-error
-        x.onlyB;
-
-        //@ts-expect-error
-        x.onlyBase;
-    }
-}
-
-{
-    type Base =
-        | { pageId: "a"; onlyA: string }
-        | { pageId: "b"; onlyB: string }
-        | { pageId: "only base"; onlyBase: string };
-
-    type Extension = { pageId: "only ext"; onlyExt: string };
-
-    type Got = AndByDiscriminatingKey<"pageId", Extension, Base>;
-
-    type Expected =
-        | { pageId: "a"; onlyA: string }
-        | { pageId: "b"; onlyB: string }
-        | { pageId: "only base"; onlyBase: string }
-        | { pageId: "only ext"; onlyExt: string };
-
-    assert<Equals<Got, Expected>>();
-}
diff --git a/test/login/kcContext.typelevel-spec.ts b/test/login/kcContext.typelevel-spec.ts
new file mode 100644
index 00000000..0cb2fbb8
--- /dev/null
+++ b/test/login/kcContext.typelevel-spec.ts
@@ -0,0 +1,211 @@
+import { type ExtendKcContext, createGetKcContextMock } from "keycloakify/login";
+import { KcContext as KcContextBase } from "keycloakify/login/kcContext/KcContext";
+import { assert, type Equals } from "tsafe/assert";
+import { Reflect } from "tsafe/Reflect";
+
+{
+    type KcContextExtraProperties = {
+        properties: {
+            myCustomProperty: string | undefined;
+        };
+    };
+
+    type KcContextExtraPropertiesPerPage = {
+        "login.ftl": {
+            foo: string;
+        };
+        "my-custom-page.ftl": {
+            bar: number;
+        };
+    };
+
+    type KcContext = ExtendKcContext<
+        KcContextExtraProperties,
+        KcContextExtraPropertiesPerPage
+    >;
+
+    {
+        type Got = Extract<KcContext, { pageId: "login.ftl" }>;
+        type Expected = KcContextBase.Login & {
+            properties: { myCustomProperty: string | undefined };
+        } & { foo: string };
+
+        assert<Equals<Got, Expected>>();
+    }
+
+    {
+        type Got = Extract<KcContext, { pageId: "register.ftl" }>;
+        type Expected = KcContextBase.Register & {
+            properties: { myCustomProperty: string | undefined };
+        };
+
+        assert<Equals<Got, Expected>>();
+    }
+
+    {
+        type Got = Extract<KcContext, { pageId: "my-custom-page.ftl" }>;
+
+        type Expected = KcContextBase.Common &
+            KcContextExtraProperties & { pageId: "my-custom-page.ftl" } & {
+                properties: { myCustomProperty: string | undefined };
+            } & { bar: number };
+
+        assert<Got extends Expected ? true : false>();
+        assert<Expected extends Got ? true : false>();
+    }
+
+    const { getKcContextMock } = createGetKcContextMock({
+        kcContextExtraProperties: Reflect<KcContextExtraProperties>(),
+        kcContextExtraPropertiesPerPage: Reflect<KcContextExtraPropertiesPerPage>()
+    });
+
+    {
+        const got = getKcContextMock({
+            pageId: "login.ftl"
+        });
+
+        type Expected = Extract<KcContext, { pageId: "login.ftl" }>;
+
+        assert<Equals<typeof got, Expected>>();
+    }
+
+    {
+        const got = getKcContextMock({
+            pageId: "register.ftl"
+        });
+
+        type Expected = Extract<KcContext, { pageId: "register.ftl" }>;
+
+        assert<Equals<typeof got, Expected>>();
+    }
+
+    {
+        const got = getKcContextMock({
+            pageId: "my-custom-page.ftl"
+        });
+
+        type Expected = Extract<KcContext, { pageId: "my-custom-page.ftl" }>;
+
+        assert<Equals<typeof got, Expected>>();
+    }
+
+    getKcContextMock({
+        // @ts-expect-error
+        pageId: "non-existing-page.ftl"
+    });
+
+    getKcContextMock({
+        pageId: "login.ftl",
+        overrides: {
+            // @ts-expect-error
+            bar: 42
+        }
+    });
+
+    createGetKcContextMock({
+        kcContextExtraProperties: Reflect<KcContextExtraProperties>(),
+        kcContextExtraPropertiesPerPage: Reflect<KcContextExtraPropertiesPerPage>(),
+        overrides: {
+            locale: {
+                currentLanguageTag: "fr"
+            },
+            // @ts-expect-error
+            profile: {}
+        },
+        overridesPerPage: {
+            "register.ftl": {
+                profile: {
+                    attributesByName: {
+                        username: {
+                            validators: {
+                                pattern: {
+                                    pattern: "^[a-zA-Z0-9]+$",
+                                    "ignore.empty.value": true,
+                                    "error-message": "${alphanumericalCharsOnly}"
+                                }
+                            },
+                            value: undefined,
+                            name: "username"
+                        }
+                    }
+                }
+            },
+            // @ts-expect-error
+            "non-existing-page.ftl": {}
+        }
+    });
+
+    createGetKcContextMock({
+        kcContextExtraProperties: Reflect<KcContextExtraProperties>(),
+        kcContextExtraPropertiesPerPage: Reflect<KcContextExtraPropertiesPerPage>(),
+        overridesPerPage: {
+            "register.ftl": {
+                // @ts-expect-error
+                nonExistingProperty: 42
+            }
+        }
+    });
+}
+
+{
+    type KcContextExtraProperties = {};
+
+    type KcContextExtraPropertiesPerPage = {};
+
+    type KcContext = ExtendKcContext<
+        KcContextExtraProperties,
+        KcContextExtraPropertiesPerPage
+    >;
+
+    {
+        type Got = Extract<KcContext, { pageId: "login.ftl" }>;
+        type Expected = KcContextBase.Login;
+
+        assert<Equals<Got, Expected>>();
+    }
+
+    {
+        type Got = Extract<KcContext, { pageId: "register.ftl" }>;
+        type Expected = KcContextBase.Register;
+
+        assert<Equals<Got, Expected>>();
+    }
+
+    const { getKcContextMock } = createGetKcContextMock({
+        kcContextExtraProperties: Reflect<KcContextExtraProperties>(),
+        kcContextExtraPropertiesPerPage: Reflect<KcContextExtraPropertiesPerPage>()
+    });
+
+    {
+        const got = getKcContextMock({
+            pageId: "login.ftl"
+        });
+
+        type Expected = Extract<KcContext, { pageId: "login.ftl" }>;
+
+        assert<Equals<typeof got, Expected>>();
+    }
+
+    {
+        const got = getKcContextMock({
+            pageId: "register.ftl"
+        });
+
+        type Expected = Extract<KcContext, { pageId: "register.ftl" }>;
+
+        assert<Equals<typeof got, Expected>>();
+    }
+
+    getKcContextMock({
+        // @ts-expect-error
+        pageId: "non-existing-page.ftl"
+    });
+
+    getKcContextMock({
+        pageId: "login.ftl",
+        overrides: {
+            // @ts-expect-error
+            bar: 42
+        }
+    });
+}
diff --git a/test/login/kcContextMock.spec.ts b/test/login/kcContextMock.spec.ts
new file mode 100644
index 00000000..3e259ffd
--- /dev/null
+++ b/test/login/kcContextMock.spec.ts
@@ -0,0 +1,202 @@
+import { createGetKcContextMock, type Attribute } from "keycloakify/login";
+import { id } from "tsafe/id";
+import {
+    kcContextMocks,
+    kcContextCommonMock
+} from "keycloakify/login/kcContext/kcContextMocks";
+import { structuredCloneButFunctions } from "keycloakify/tools/structuredCloneButFunctions";
+import { expect, it, describe } from "vitest";
+
+describe("createGetKcContextMock", () => {
+    type KcContextExtraProperties = {
+        properties: {
+            MY_ENV_VAR?: string;
+        };
+    };
+
+    type KcContextExtraPropertiesPerPage = {
+        "register.ftl": {
+            authorizedMailDomains: string[];
+        };
+        "my-plugin-page.ftl": {
+            aCustomValue: string;
+        };
+    };
+
+    const { getKcContextMock } = createGetKcContextMock({
+        kcContextExtraProperties: id<KcContextExtraProperties>({
+            properties: {
+                MY_ENV_VAR: "my env var value"
+            }
+        }),
+        kcContextExtraPropertiesPerPage: id<KcContextExtraPropertiesPerPage>({
+            "register.ftl": {
+                authorizedMailDomains: ["gmail.com", "hotmail.com"]
+            },
+            "my-plugin-page.ftl": {
+                aCustomValue: "some value"
+            }
+        }),
+        overrides: {
+            locale: {
+                currentLanguageTag: "fr"
+            }
+        },
+        overridesPerPage: {
+            "register.ftl": {
+                profile: {
+                    attributesByName: {
+                        username: {
+                            validators: {
+                                pattern: {
+                                    pattern: "^[a-zA-Z0-9]+$",
+                                    "ignore.empty.value": true,
+                                    "error-message": "${alphanumericalCharsOnly}"
+                                }
+                            },
+                            value: undefined,
+                            name: "username"
+                        }
+                    }
+                },
+                passwordPolicies: {
+                    length: 66
+                }
+            }
+        }
+    });
+
+    it("returns the proper mock for register.frl", () => {
+        const got = getKcContextMock({
+            pageId: "register.ftl",
+            overrides: {
+                profile: {
+                    attributesByName: {
+                        gender: id<Attribute>({
+                            validators: {
+                                options: {
+                                    options: [
+                                        "male",
+                                        "female",
+                                        "non-binary",
+                                        "prefer-not-to-say"
+                                    ]
+                                }
+                            },
+                            displayName: "${gender}",
+                            annotations: {},
+                            required: true,
+                            readOnly: false,
+                            name: "gender"
+                        }),
+                        email: undefined
+                    }
+                }
+            }
+        });
+
+        const expected = (() => {
+            const out: any = structuredCloneButFunctions(
+                kcContextMocks.find(({ pageId }) => pageId === "register.ftl")
+            );
+
+            out.properties = {
+                MY_ENV_VAR: "my env var value"
+            };
+
+            out.authorizedMailDomains = ["gmail.com", "hotmail.com"];
+
+            out.locale.currentLanguageTag = "fr";
+
+            delete out.profile.attributesByName.email;
+
+            {
+                const usernameAttribute = out.profile.attributesByName.username;
+
+                delete usernameAttribute.value;
+                usernameAttribute.validators.pattern = {
+                    pattern: "^[a-zA-Z0-9]+$",
+                    "ignore.empty.value": true,
+                    "error-message": "${alphanumericalCharsOnly}"
+                };
+            }
+
+            out.profile.attributesByName.gender = {
+                validators: {
+                    options: {
+                        options: ["male", "female", "non-binary", "prefer-not-to-say"]
+                    }
+                },
+                displayName: "${gender}",
+                annotations: {},
+                required: true,
+                readOnly: false,
+                name: "gender"
+            };
+
+            (out.passwordPolicies ??= {}).length = 66;
+
+            return out;
+        })();
+
+        expect(got).toEqual(expected);
+    });
+
+    it("returns the proper mock plugin pages", () => {
+        const got = getKcContextMock({
+            pageId: "my-plugin-page.ftl",
+            overrides: {
+                locale: {
+                    currentLanguageTag: "en"
+                }
+            }
+        });
+
+        const expected = (() => {
+            const out: any = structuredCloneButFunctions(kcContextCommonMock);
+
+            out.pageId = "my-plugin-page.ftl";
+
+            out.aCustomValue = "some value";
+
+            out.properties = {
+                MY_ENV_VAR: "my env var value"
+            };
+
+            out.locale.currentLanguageTag = "en";
+
+            return out;
+        })();
+
+        expect(got).toEqual(expected);
+    });
+
+    it("returns the proper mock for other pages", () => {
+        const got = getKcContextMock({
+            pageId: "login.ftl",
+            overrides: {
+                realm: {
+                    registrationAllowed: false
+                }
+            }
+        });
+
+        const expected = (() => {
+            const out: any = structuredCloneButFunctions(
+                kcContextMocks.find(({ pageId }) => pageId === "login.ftl")
+            );
+
+            out.properties = {
+                MY_ENV_VAR: "my env var value"
+            };
+
+            out.locale.currentLanguageTag = "fr";
+
+            out.realm.registrationAllowed = false;
+
+            return out;
+        })();
+
+        expect(got).toEqual(expected);
+    });
+});
diff --git a/test/tools/isSameCode.ts b/test/tools/isSameCode.ts
deleted file mode 100644
index d9252c12..00000000
--- a/test/tools/isSameCode.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export function isSameCode(code1: string, code2: string): boolean {
-    const removeSpacesAndNewLines = (code: string) =>
-        code.replace(/\s/g, "").replace(/\n/g, "");
-
-    return removeSpacesAndNewLines(code1) === removeSpacesAndNewLines(code2);
-}