diff --git a/README.md b/README.md
index 28e7e64..4830f78 100644
--- a/README.md
+++ b/README.md
@@ -360,8 +360,9 @@ src/jwt.ts JWS signature verify via node:crypto, no jose; claims+JWKS
src/cookie.ts Cookie parse + secure Set-Cookie build (session/CSRF cookies, §4)
src/context.ts RequestContext handed to handlers + buildContext()
src/config.ts Env loader — Ory endpoints, cookie/CSRF secrets, JWKS, port; validated at boot
+src/icons.ts Used-icon registry + sprite builder from lucide-static (regenerates partials/icons.ejs)
src/plugin.ts definePlugin() + the host's plugin discovery/router (planned)
-views/ Core EJS templates (index, 403/404/500, partials/)
+views/ Core EJS templates (index, 403/404/500, partials/ incl. the icon sprite)
public/ Static assets under /public/ (css/styles.css + auth.css, favicon, robots.txt)
config/menu.ts Central menu override + branding (planned)
plugins/ Drop-in plugin folders, auto-discovered (planned)
diff --git a/src/icons.test.ts b/src/icons.test.ts
new file mode 100644
index 0000000..30a30af
--- /dev/null
+++ b/src/icons.test.ts
@@ -0,0 +1,33 @@
+import assert from "node:assert/strict";
+import { readFileSync } from "node:fs";
+import { dirname, join } from "node:path";
+import { test } from "node:test";
+import { fileURLToPath } from "node:url";
+import * as ejs from "ejs";
+import { ICON_NAMES, buildIconSprite } from "./icons.ts";
+
+const rootDir = join(dirname(fileURLToPath(import.meta.url)), "..");
+const lucideDir = join(rootDir, "node_modules", "lucide-static", "icons");
+const partial = join(rootDir, "views", "partials", "icons.ejs");
+
+const symbolInner = (sprite: string, id: string): string =>
+ sprite.match(new RegExp(`]*>(.*?)`))?.[1] ?? "";
+
+test("icons partial inlines exactly the used lucide-static icons", async () => {
+ const built = buildIconSprite(lucideDir);
+
+ // The committed partial must be exactly the generator output — proves provenance
+ // and flags drift when the pinned lucide-static is bumped without regenerating.
+ assert.equal(readFileSync(partial, "utf8"), built);
+
+ const html = await ejs.renderFile(partial, {});
+ const ids = [...html.matchAll(/ m[1]);
+ assert.deepEqual(ids, Object.keys(ICON_NAMES)); // only the used icons, complete + ordered
+ assert.match(html.trimStart(), /^