+ Pick a theme, fill in your details, and publish permanently onchain. Your profile
+ renders identically on every IQ surface — no link rot, no middleman.
+
+
+ {isMock && (
+
+ Demo mode — set NEXT_PUBLIC_IQ_MOCK=0 and connect a funded wallet to publish for real.
+
+ )}
+
+ {/* Theme picker */}
+
+
Choose a theme
+
+
+
+ {/* Live preview — rendered through our own iqui kit */}
+
+
+
+
+ {/* Form */}
+
+
- Beautiful, pre-built templates you can make yours in minutes. Customize text,
- images, and colors — then publish permanently onchain.{" "}
+ Pre-built templates for tokens, NFTs, DAOs, and more. Customize and publish
+ permanently onchain via IQ Pages.{" "}
{readyCount} live, more shipping weekly.
{/* filters */}
diff --git a/components/iqui/index.tsx b/components/iqui/index.tsx
new file mode 100644
index 0000000..861d22e
--- /dev/null
+++ b/components/iqui/index.tsx
@@ -0,0 +1,122 @@
+"use client";
+
+// iqui — IQForge's own react95-style themeable UI kit.
+//
+// Same contract react95 proves out: a flat named color-token object + a
+// ThemeProvider. A "look" is pure data (a ProfileTheme), so a new theme is zero
+// new component code — the same "templates are data, not code" principle this
+// repo nails, applied to UI chrome. No styled-components: components read tokens
+// from context and render the classic raised/inset bevel with box-shadow.
+
+import { createContext, useContext, type CSSProperties, type ReactNode } from "react";
+import type { ProfileTheme } from "@/lib/profile";
+
+export type IQTheme = ProfileTheme;
+
+const ThemeContext = createContext(null);
+
+export function ThemeProvider({ theme, children }: { theme: IQTheme; children: ReactNode }) {
+ return {children};
+}
+
+export function useTheme(): IQTheme {
+ const t = useContext(ThemeContext);
+ if (!t) throw new Error("iqui components must be inside ");
+ return t;
+}
+
+/** The whole point of the kit: a 3D bevel from four tokens. `raised` pops out
+ * (windows, buttons), `!raised` sinks in (fields, panels). Swapping the light
+ * and dark stops is the entire difference — kept pure so it's trivial to read
+ * and the only branch worth checking. */
+export function bevel(t: IQTheme, raised: boolean): CSSProperties {
+ const [light, lighter, dark, darker] = raised
+ ? [t.borderLight, t.borderLightest, t.borderDark, t.borderDarkest]
+ : [t.borderDark, t.borderDarkest, t.borderLight, t.borderLightest];
+ return {
+ boxShadow: `inset 1px 1px 0 ${lighter}, inset -1px -1px 0 ${darker}, inset 2px 2px 0 ${light}, inset -2px -2px 0 ${dark}`,
+ };
+}
+
+export function Window({
+ title,
+ children,
+ style,
+}: {
+ title?: string;
+ children: ReactNode;
+ style?: CSSProperties;
+}) {
+ const t = useTheme();
+ return (
+
+ );
+}
diff --git a/components/website/website-editor.tsx b/components/website/website-editor.tsx
new file mode 100644
index 0000000..c2d4278
--- /dev/null
+++ b/components/website/website-editor.tsx
@@ -0,0 +1,25 @@
+// components/website/website-editor.tsx
+//
+// Thin wrapper around the Puck editor for the IQForge Website path. Kept in its
+// own module so the page can load it with next/dynamic({ ssr: false }) — Puck is
+// a browser-only editor and must not run during server rendering.
+
+"use client";
+
+import { Puck, type Data } from "@measured/puck";
+import "@measured/puck/puck.css";
+import { iqPuckConfig } from "@/lib/puck-config";
+
+export function WebsiteEditor({
+ data,
+ onPublish,
+}: {
+ data: Data;
+ onPublish: (data: Data) => void;
+}) {
+ return (
+
+
+
+ );
+}
diff --git a/examples/README.md b/examples/README.md
new file mode 100644
index 0000000..7a09014
--- /dev/null
+++ b/examples/README.md
@@ -0,0 +1,96 @@
+# IQForge — Visual Builder Study
+
+Three MIT-licensed open-source builders, studied for how they model blocks, JSON state,
+and HTML export — the three things IQForge's website builder needs.
+
+## The three candidates
+
+| | GrapesJS | Craft.js | Puck |
+|---|---|---|---|
+| **License** | BSD-3-Clause | MIT | MIT |
+| **Model** | HTML/CSS tree | React node tree | Config + Data JSON |
+| **Block definition** | `BlockManager.add(id, content)` | Component + `.craft` static | `config.components[name]` |
+| **Settings panel** | built-in style manager | custom `related.settings` | auto-generated from `fields` |
+| **JSON state** | `getProjectData()` / `loadProjectData()` | `query.serialize()` / `actions.deserialize()` | `data: Data` prop |
+| **HTML export** | `getHtml()` + `getCss()` (native) | `renderToStaticMarkup` (manual) | `renderToString()` |
+| **Framework** | vanilla JS (works anywhere) | React-required | React-required |
+| **No-build option** | Yes (CDN `
+