From 55ff88e6f272a7fc18ee9921fef1887dbde54797 Mon Sep 17 00:00:00 2001 From: Sven Reiser Date: Sun, 21 Jun 2026 15:56:18 +0200 Subject: [PATCH 1/2] chore(deps): bump @mind-studio/ui to 0.7.0 (brand-refresh typography) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Picks up the serif heading typography (Fraunces h1–h3), kbd mono, and the semantic state tokens from the design-system brand refresh. Refs #29 Co-Authored-By: Claude Opus 4.8 (1M context) --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 819a829..4655b7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "@inrupt/solid-client-authn-node": "^3.1.1", "@inrupt/solid-client-notifications": "^4.0.0", "@mind-studio/core": "^0.7.0", - "@mind-studio/ui": "^0.4.0", + "@mind-studio/ui": "^0.7.0", "better-sqlite3": "^11.8.1", "dotenv": "^17.4.2", "next": "16.2.6", @@ -1613,9 +1613,9 @@ } }, "node_modules/@mind-studio/ui": { - "version": "0.4.0", - "resolved": "https://npm.pkg.github.com/download/@mind-studio/ui/0.4.0/4d57829589aba38f8123b53c858598ed84db4910", - "integrity": "sha512-GOMaHU1tR8z0JIOnOHMJBLcYDItcUuYVuxgBmsBXGoipoSxrknzVnarqiR/7Wm26AWkQ7ISyzDkDcFot6jTgyQ==", + "version": "0.7.0", + "resolved": "https://npm.pkg.github.com/download/@mind-studio/ui/0.7.0/70071acee41c5d7bcc3bed636a6473e35dac9f6a", + "integrity": "sha512-PvkztbjfiFM7W8Zk0/rWYlMn26DiIakuhBQfxphi5les6J6eo9W7zZzLhbGpEp7ytB1+SaKev95ZFOxVhKx6cw==", "license": "MIT", "dependencies": { "@base-ui/react": "^1.5.0", diff --git a/package.json b/package.json index a5f80b3..d0a143a 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "@inrupt/solid-client-authn-node": "^3.1.1", "@inrupt/solid-client-notifications": "^4.0.0", "@mind-studio/core": "^0.7.0", - "@mind-studio/ui": "^0.4.0", + "@mind-studio/ui": "^0.7.0", "better-sqlite3": "^11.8.1", "dotenv": "^17.4.2", "next": "16.2.6", From eaaf886f1307969ef98844970674ae3f040b9b25 Mon Sep 17 00:00:00 2001 From: Sven Reiser Date: Sun, 21 Jun 2026 17:41:49 +0200 Subject: [PATCH 2/2] feat: adopt brand lockup + canonical icons (ui#29 wave 2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wave 2 brand-refresh fan-out for the builder repo, basing on the open @mind-studio/ui 0.7.0 bump branch so the new `label` prop and the React-free `./brand` subpath are available. Pattern from drive#17. Tier 3 — in-app logo lockup: - The landing TopBar now renders instead of a bare "✦ Mind Builder" glyph+text wordmark: shared weave mark + "Builder" in the brand serif. Tier 4 — canonical static brand assets (mark-only, from @mind-studio/ui/brand): - scripts/gen-icons.mjs generates src/app/icon.svg (favicon), src/app/apple-icon.png (180), public/icon-{192,512}.png (maskable) from MIND_MARK_SVG / monoMarkSvg / MIND_GREEN — single source of truth. Mirrors drive's script; mkdir -p the output dirs since builder ships no pre-existing public/. - src/app/icon.svg replaces the hand-rolled amber "M" placeholder. - src/app/manifest.ts (name/short_name/description, Mind Green theme). - src/app/opengraph-image.tsx: dark green-glow card, MIND_MARK_SVG mark + "Builder" wordmark, Builder-appropriate copy. Deterministic (default font). - package.json: + "gen:icons" script and sharp devDependency. - .gitignore: negate the broad *.png rule for the three committed brand icons so the generated binaries ship with the app. Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitignore | 5 +++ package-lock.json | 30 ++++++++++++- package.json | 4 +- public/icon-192.png | Bin 0 -> 5777 bytes public/icon-512.png | Bin 0 -> 20569 bytes scripts/gen-icons.mjs | 83 ++++++++++++++++++++++++++++++++++++ src/app/apple-icon.png | Bin 0 -> 6158 bytes src/app/icon.svg | 69 ++++++++++++++++++++++++++++-- src/app/manifest.ts | 42 ++++++++++++++++++ src/app/opengraph-image.tsx | 74 ++++++++++++++++++++++++++++++++ src/app/page.tsx | 9 +--- 11 files changed, 302 insertions(+), 14 deletions(-) create mode 100644 public/icon-192.png create mode 100644 public/icon-512.png create mode 100644 scripts/gen-icons.mjs create mode 100644 src/app/apple-icon.png create mode 100644 src/app/manifest.ts create mode 100644 src/app/opengraph-image.tsx diff --git a/.gitignore b/.gitignore index 5fbe012..fec3bb6 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,9 @@ next-env.d.ts *.log *.png +# Canonical brand icons are generated from @mind-studio/ui/brand (npm run gen:icons) +# and committed so the favicon/PWA/apple-touch assets ship with the app. +!src/app/apple-icon.png +!public/icon-192.png +!public/icon-512.png .playwright-mcp/ diff --git a/package-lock.json b/package-lock.json index 4655b7f..966b50f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,6 +31,7 @@ "husky": "^9.1.7", "lint-staged": "^17.0.7", "playwright": "^1.60.0", + "sharp": "^0.34.5", "tailwindcss": "^4", "tsx": "^4.22.3", "typescript": "^5", @@ -383,6 +384,7 @@ "version": "1.10.0", "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -896,8 +898,8 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": ">=18" } @@ -909,6 +911,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -931,6 +934,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -953,6 +957,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -969,6 +974,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -985,6 +991,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1001,6 +1008,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1017,6 +1025,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1033,6 +1042,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1049,6 +1059,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1065,6 +1076,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1081,6 +1093,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1097,6 +1110,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -1113,6 +1127,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1135,6 +1150,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1157,6 +1173,7 @@ "cpu": [ "ppc64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1179,6 +1196,7 @@ "cpu": [ "riscv64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1201,6 +1219,7 @@ "cpu": [ "s390x" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1223,6 +1242,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1245,6 +1265,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1267,6 +1288,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0", "optional": true, "os": [ @@ -1289,6 +1311,7 @@ "cpu": [ "wasm32" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", "optional": true, "dependencies": { @@ -1308,6 +1331,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1327,6 +1351,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -1346,6 +1371,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "Apache-2.0 AND LGPL-3.0-or-later", "optional": true, "os": [ @@ -6618,9 +6644,9 @@ "version": "0.34.5", "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "devOptional": true, "hasInstallScript": true, "license": "Apache-2.0", - "optional": true, "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", diff --git a/package.json b/package.json index d0a143a..3350ad9 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,8 @@ "test": "vitest run --passWithNoTests", "prepare": "husky", "seed:demo": "tsx scripts/seed-demo.ts", - "smoke:wish": "tsx scripts/smoke-wish.ts" + "smoke:wish": "tsx scripts/smoke-wish.ts", + "gen:icons": "node scripts/gen-icons.mjs" }, "dependencies": { "@inrupt/solid-client": "^3.0.0", @@ -39,6 +40,7 @@ "husky": "^9.1.7", "lint-staged": "^17.0.7", "playwright": "^1.60.0", + "sharp": "^0.34.5", "tailwindcss": "^4", "tsx": "^4.22.3", "typescript": "^5", diff --git a/public/icon-192.png b/public/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..6ef4ebec39333ccfa12702de0afa07660526e8be GIT binary patch literal 5777 zcmchb^;?tQ|Hrqn;TRyb2?|Jes&tN#(k&?^;hP#FqU0#0L6MT~lF=!hA|ecFkb$6d zmw>|$@ckdYKb-qq*Zqp~yw7#+bI$7#p{uP*4!Z*b0086<)s*xv`;MyyCBA&>&$-;V z>`2gRrk(%*(dtzL*7@o?0|2)aA1WyrzD(b;JWa6dH#)Y$sbj2bIIUqQXjl&Fiwm(P zGm;kqhFJs|f)HIv03fRC=42Xm-pja_hp}4{)k{+oPFAYtVt2OKV)Adth_F3%5P9(K zvQ?DqB=yV4x6c-Ra>q~Z%%5bG9z-1$?)dr-Oa53%-%0mOFiUm1e}eQ{y*md#Cyj5q z5eY-GWV5Kf1nEMZpzsPL9CRl*R1Oe^d5y%86jF{*vPXmTu1ww8*QQqh7?3>3mNgoM zRE!s<(Yy@S4MklAQ`-h{gGIoR))JQ<3Mdios~l7}wXV{eP+X0o%O9R|mGL7q@3P}g zQqsQ)n*bYJb|!EgmXVCM8=Ej3u~1ODE|42+2=1l9Tn)1eQ@V;iynH7DCdshARsavb zRzRkHW%^2Vt$?%ZT0!cShXRTle64`=Dp(Er`g+V<1)i%MizAmG1M2m`{6V1y*Uyi* zP69RLAE1#;jn5P)EVD-P9!wsNZANEiW{p2uaa*mTpFBF4fhf!}T3j`7UV8!OQX(Az$mGIcoQezc+7_jQ#Oh(0R)L3(wtjO5FV+v zhRx@b^>YcW#clh@HIEd-?je{*ROV+V%U7I5f51LuWKCL0REst57Q=)Q%qzqf`X>o% zjB><`sV$$&aO%8Bkqw}usMyfg;kCFOU!GqDouCHyxe_$p*j8z zeZwgbdh<4pC@RjamL3GSZP57q+9h#s2ibg|LKUd@7y{l5J*)fs8R%Ev!1oB`+P{jt z1M*_Y1d||`YYRGzdXunoDHGmXmQ;tQWh!UsaGRxq@3`_ZUf=<^awbAh4WP{>R0srlh(p6C5OnM2Ri@4RjThaLDx`nG;?@sN{0z!XPjBycA&U2%g z0~e-Qch3MAN-pK^_4UgDA<lM37IQ~A4?>AvosE}ef8 zm!-qT12vdYvb8=9tn2M+@7R6dq79N*YNhG+=`IK$4CQp69WBzF<$cPG67<{ZU@QYP zxSN(XSjZ*N_f=l}Ay*cs{g~`#TUut8R?cJ zxlXi%m{ub$zL|9b+*-N(8-kfU%Hogeex11cnPjCj&+X%drR6LBtuJig@GOW9 zI~vNUK-WKwu@7}y&UM@dk3j8y&&&tc$*Nb^f{1XCI&SPT2_Wj#tKT2oXhClH8{V}? z`=&nx#{#_!d+sH^Dz<^dZvhr*b>0)v|Z^> zR=drD%t>()lB~?bSsS7OFLq}TviD_waUjuMcma6B(qV9R6Lo+%!;`gT-xrmt@*Xd& z?kImK8}e0-45&IESPiC+cw~ll% zG%U9-V8sw4)e<{cx6=35qEvWDY-FqttnJD+;)&X)R$J-oLc=lbk zqRllUYx-}>-VWx!p=PO@mRV@n2?)z*jxj3A0#Gs}^9?izF+9LJR(Jf7Pxv1BwOU}@ z+_rKMkG(DV)a8S{6p06U0_KHh64zSQfCdg9*w2TYL}wi_P7~LJNW0xyj1?freynz# zw_)-8tD`z$=6@Hz)h(SAh3^FKAYH7^&S%ABKbXCwKl?JUg$rx6)4@=1pf%*63v2^HzXDs)n#e8DKTq z!S1w%RnXLhdZwF(?Hl@6OQ^w5qBJH72RauWz!CA%a;@HI*s95NV=WBB9Uj5_Sx&WP zZ9SMTXu}6XwahZc(sU?l(K`b!cte}Fdw8y&do6WMzVD!#E zu93FSFPl!eQ5*BX^6$S~OKtsmQs*%;8>3MIpk}ADk8X2Lv)voo2Z%-UMf0&DsF<=O z&V9vYoGfT>R`1Mf!fvl`QKXCQrQN~^qj z@A0CK(!7tGY(3ZDfMAoD!Yltjp&tIo zM!P|^0z}7?AU{@yA(Jk|X+82(bg(C52cB|%)*Q3()BD$tv=f-zYv*|mv1E0iT;nh2 zzM≧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 Ily&g`07FBWp8x;= literal 0 HcmV?d00001 diff --git a/public/icon-512.png b/public/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..0b247e723601f861ec92b867759e1dee48429af8 GIT binary patch literal 20569 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 e833`z9 { + const abs = resolve(root, p); + mkdirSync(dirname(abs), { recursive: true }); + return abs; +}; + +// Brand green backplate (the solid surface behind the white mono mark). +const GREEN = MIND_GREEN.base; // #16B88A + +/* ---------------------------------------------------------------- favicon.svg */ +// Nest the full-colour mark inside a square canvas, centred with a little +// breathing room (meet → preserves the mark's aspect, no distortion). +const nested = MIND_MARK_SVG.replace( + ' +${nested} + +`; +writeFileSync(out("src/app/icon.svg"), faviconSvg, "utf8"); + +/* ------------------------------------------------------------------ raster ops */ +// Rasterise the monochrome mark to a transparent square of the given size. +async function rasterMark(px, color = "#ffffff") { + return sharp(Buffer.from(monoMarkSvg(color))) + .resize(px, px, { fit: "contain", background: { r: 0, g: 0, b: 0, alpha: 0 } }) + .png() + .toBuffer(); +} + +// Maskable: white mark on a full-bleed green square; mark kept in the safe zone. +async function maskable(size, file) { + const mark = await rasterMark(Math.round(size * 0.66)); + await sharp({ create: { width: size, height: size, channels: 4, background: GREEN } }) + .composite([{ input: mark, gravity: "center" }]) + .png() + .toFile(out(file)); +} + +// Apple touch: white mark on a green backplate with a 22% corner radius. +async function appleIcon(size, file) { + const r = Math.round(size * 0.22); + const backplate = Buffer.from( + ``, + ); + const mark = await rasterMark(Math.round(size * 0.62)); + await sharp(backplate).composite([{ input: mark, gravity: "center" }]).png().toFile(out(file)); +} + +await Promise.all([ + maskable(192, "public/icon-192.png"), + maskable(512, "public/icon-512.png"), + appleIcon(180, "src/app/apple-icon.png"), +]); + +console.log("[gen:icons] wrote icon.svg, apple-icon.png, icon-192.png, icon-512.png"); diff --git a/src/app/apple-icon.png b/src/app/apple-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..76f3c175424a3bf644236cc00a6e8050d6459d71 GIT binary patch literal 6158 zcmV+p81d(cP)I?mxvleWXQQ^y2Is-kSAmT&8_E8B`C%LFJ=)-CG3DA78ogQ6&j zI!IBHB~l_EIzNa{rk>s|b^*M%0N(e_e52v$VX^r3hsC$wX&4%*y19;-PVHS)PTeES zwP%>F-D$2UE08kIs5 z7S()|Iran0wHhG|=2$u13q)+kD+9;MnXa|nbnR)(vF@KZzu_ZBrl_XogJx6h=S|0+ z$y{rI090u&k%cv%Roz^7pD};_&lqW?Ny}DV*NerUX@<;UYp*KX7O@WdIFfn%+n=r-I~7BG)nV%_9BMRY$jai(QpI(EkmZv8E# z1+!cKDbukI>wZ|`%8-HS*j?is>ysq`^Nnvc+-$nmA>9v2Txl|}j*MSiHz|Id*|9tH zKOAu-%D{B3U9suZIC0VeQ2(Mc<5% zasWw?^fIv&$-r!~AL3_cQ$nlu1tPZ90PR|xhUb0YIy_gq))z^b1Spn58B{gb-EkeD znPb18dt$^S0~SICrfWZY4VYp6Ag>^SiKSKs*1$C;yes9obWe(yWMGGuL6uYYmG=Qn z$*u$@H{CKY9lQR0a~Xm}J1>kbz@OH%40u5U5B7Ug~AwSk1^x zY1cjxVv>OyT?S}{fgPHP$IuJqWkCiAuEP#}TK7bVNd_#Q9r`4kD%3iS0Oe&t2BvEb z8cCQ)R`_chUh(F2@9^3Oj(h!=E_#@J@_=`D+idNCU@2z;bV$L?I=sz0e|gA@ zo6cSy^rr1^(+&)lQYJtv3hZyUzUiwHr6%0tj@2({2M9|U6QC7@wfEd9ubc$^dur!e z?I2+(Vgj^;kbd=@8Q#U=@H%o->bh{oyJbm(cCfG%FabJ1K=-uG_N^1DglnK<_gp;d z9el6P>m5AjT^PP}jnzZ-;P{zkKhX{tmT)FO3xqRe-5e#*0l7v}+T<`5ZcQO#vcdmX> zJAhcixS|358_WOKdt&cO@9pDzyo|KtI2Xi)U_NuZcX-qH zuk&rzrTA*3i7N`w6PoM1rw*+5O=w}vXV960EEsX}l(soOXjLhf%lW}k&v$M1suLjh za&kog`g5zE^H!be3T*=}B!CR&x$$mY$zHm1F~*5>Ul{QIXw6I7*P$GoX+VEz?aSVw z_xin35nhm=9(^~Kxnd`M_Ryx1dL)kzp7TEa&Qsdgg#aBw2y0Fs_R2-@;(cS|{Ll;a z7n|SkqwLB>3o>jW$=nW&9q90dGoB7wa-vgtzAqo%re&_1`;TVQL6a#!Bm3jM;Y*%Q zg1#yM{?qaBbHy+dQ?gefYBuv1~D<&DGJ$@+#aaIg7MN2?T2Uhmm;^_uxT zI|F|Yv)x167IE*(bF^SCjC0NBS3NH!CwNPBuW3aC`qd-tfs1tX;@QA)c(EG?itMms z`S#^cOMM-nqe5+vnd@z>jlz5K%zJnS7Vz?~ICUs+4p3`!uWLmD`ipB`3JfAzd-`zT zI8Z@&gxVQF*Z*Scv_Q)WRGKrFE((8xU?g}6gYGBNznO&GUhCPF=_CRps|l;?`nsjY z`GuBg+%XUwBs0b@FMU$_09K5ST|6fRX7DLNmJ5@V9Rix7ZUjkXBdsBxK>$%1FRD#B zpL-aFpfjtuqj_J0AeDm^s2|960 zWzBZj>6zkO=X7u9j)xZqi3YmYJM(~kv1^OamKtWvgMx@W6kt>t>-SeZC!O$$gRRQg z_P*7zs7Gv+0oak4HwWFEIzWp~`B?BUW5RRDqcGv2&Apw0V20YHIxavP=R8?JRHEt^ zBng}HX=;@yC8Z@F*F4jJ z{_8CZV%_ob3_V$7cKfT%3zWu#3t8lF!Dn99Oqb``0s3wfxeg2BV36&jd)+e&Xwe~N z=AliI#@=@3SR`*_AtUlFPJLJO!XZW_%Cq+h+~WWC?o#dRo>@S{l*FSy-Sk?dv61{5 zr+IDpse|0Hww^f_Yn_m=>INI-r260oB5LD!k!^Vr) zX;Gdb%!E;&yJq)0LYKVmbG1viq`baLnTQe$($-ci>e5Tb|!e_kaHKNaJdLHa7BlS>-d{3KjmJB(9Jlr z)`v!hJ*Rh{U-pc5Pk2Ll1jmc+bxm?Z<8!cA*PUKR@i>Z6vGYe?AVtMr9;jP#F7R6M`McAzi8))(lTEzmMzQ5B| z&Mc3zV}G~61SvYeqCTGPbi zO^OwnL+@OZu9Cf}0<;+0wuB}>F*4kbVf zgb?Sa8D=lkvv7O&`R2Qacf9T0w{EWYyDOjd7aE^t^y9{XQib3~ujV8o{N2_!{SZ^t zlr6-Dz{vsk{|`G_eb46o>*x8&x3FeF<=WKWqx^Le$rDYDbOSWgJ2ZIbS-u`EyMU;` zj{~F1ePJn)sj8nR*tU6Nsgx^2qkEB6q!{1bHrsdJM1A?wraz|=&|g^fd?@o9R1p+L zjM~5wRYqlYK~d}n;v<3xrNX|x;nhfUy{)y;TX<}DXme#6i#eta(BK^d$CVZa(QR=j zeb(+>#f`B57{l7s;q-~SOTZngUyv#^6V}b2BsQ|%5VO>FRK!vs%X}>Tfke~!v2i0% zL7<|PvJz-@Km=eR-PJZr`#M()pusrI1rfq7%QYXUGIjgbcry-cP|9pU97Q?h_J)MI z180=(^{qHS%an~BYZopDqcnhux`6Im2;ID?jM>$0@4i5}Avr{Z2sT+HnnpF-eRJC)DGy)G?q%FD zU?Y~XKYw}ctjK1&MIp_0FmtA{UUcdJEy^pD^$x-|tJ+rhdplhvFC5Hoys_R@aL_=X zRdoVQSvSXz)rcA{yZHDX?dzR+K#TJ0!uD8!H3aTsgrK6m1w3=maS^cxx3{XB8fi

VBin4nISxa$}#r0xK_6DQB=z1a@PeNwFok0Q1?$aNHe=buNT-+Q6{YL z_b}DrnmBU_3&AnB;6=(a^l={L+q4z32v~8@?sF%LdM06!DMg7j0(5{7L@m)oNwUal z#-S-n+lWGf{wp$T!AlvYOzm&4d`6fI9Ok8KA2=?I6Tv~al!a`{$*J0*ap2;S%=I{k zAt(qnIHI&rmgy9Q^0qvBp=*oqT2xUL6`!0_~<+#G6BZ&^L zc|u7A)p60koJZ65uM73;q8fm()aYLC%mZ4~I0(^WVaDWTo`6)-qEH!0hG2q3>0Fhu z|9RIE?sy1;Ws1)Yv!E!3J)Db7{Y zDh}$6YU{ZqaOwaJ-XmyUkA)~!16jmz^%n_p%*4_Cmbas-&h>KvEu2weSNA$s44_37 z=fjxr!lY3ZG7e>7!c_sP+Z77TAXq4l!|Qp0SrKz8Wzm~baw-80MoN;1@Hv$k=a*U= zxntl^p&1dNWls43b5Pwl zxTkSo6%lN~GQG;t)iz2eumk7CrGc^2s~%R9#Hj@|7&VcDNTw4ik9q=HBE#t*vXJC~ zhC-1t)(?0CgY!69i~c!5H+wmPr^u zA@%$<_>>0`#zaV~Y5)~p1}3N_BGcI*YWP4BIQ4*rDNCka1`cd+W)w3;i5hwqHuyn3 z581jJ#ViFfPM5qx2WpjU+%nW2R&X!u_Fa-)z;M`1V?F510UC@7L$Vfzq0vG!W9vnW z0)O)D;!rkMr9ceAE~`22dr@tXLPGjfK3`JQx_Ru&^T7Ifeur7velwU)9O1V~;7kBI zAJZFj@G7<|ZRk594D|%qRdW%M`zSi#A)sCb)F8}3^d;IpaNK9r)H2w$qlTX*i8BM} zd><55pu|mx*_LTX48Y4A(n?8vLl;sPO;=HX&g;~o?C??%?7)p7k_-@op@Vh|9FJVM zGKriyK&x03;v#qyQL;AdT%n)GSz;lGP_0S#`VgQ)2muEjnBGc7&}mg;F?c-Qt@C@J zl(Hz!?sF$oTgaSM`VKvoQJ*a+ds>Cy+>kA2pvo|vp#(x)JND&~5x>L%4x+l(p&VQh zfX*{)(D>ZKauH@H#Ey(Iw&j{{SXJcm$dy7f=-;AS=H=#!0(2px&KnML$f|zzNV`;_ znU$vwm2G}O)stY+L68x+%N}^Q)S2UoD@n3F!BX9=<&}2+=QNAP{XHN*{ z07nwKZt0d6OBfTN73+WG36=ekJrnnWz=J8H@5|P$V->~(XpUfH;zQt>l!@k(WvD(f zF8rVm?E8BJrfX_k@5hFnBX(1;Y;FBkWv%@7WX+)yzrv4tk48!ELFB34`7i~A>cHI*pCK<4JcIfTcp<4)01SpmT88}um%yu)hPlT9c;Kl;z z=|+`P_Xq)s0L3yO1Jkh|HcY4XF5MF$CK<3;c4&LDF}~?>lQ~w7Kt-Tp>6XFBO)Wnj zXMjxC-jRR_5t9tOure@RYl{!&Q9w^4VbTl5QY-`0vFon_nmN|}x+g?TGGGy8P}O8j zxeDls^BX?G9QzD`ia^EEC0BzLNe9(04{kkVdOfq09GH9~*8J_on>j8bm+VL#{6ak8*Ne0c4a{-@?H>+Z>-z*K0u)Pu3=oH81kr>=H6Jxy`=IX05|a#= zKnA93bxvAV^I=1Vs+#NWAwUtJSb}9x<Wc z71}(fO3-KMph$pbrIW$Rk1c-U2BWOBtmbE#W7m?Mnt;vXl7U}N!)lDpnh}PWV?O}z z4XGdmY!*od)`02Q4;o3J@r&ywQS1i+nuXVw7nDt3R&|x5MlbEw1a2m0#n`VLHCJx( zOCq@Tqs+CA5U>f@thfxinPYuNI-WTR1edwlWIu#JYyvg`n?VLm_CDkQYCZJDK~>H5 zx8w9`I`%07cZGr5@e3Hu@+*V#va{1l_{2bGLevyK zD^+SmRGP4;zKXfEUqYd3=Gae~P4*H5LE*4~?p)MzE_pAU>Doj7+MtFD0@fU>* - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/manifest.ts b/src/app/manifest.ts new file mode 100644 index 0000000..c644de9 --- /dev/null +++ b/src/app/manifest.ts @@ -0,0 +1,42 @@ +import type { MetadataRoute } from "next"; + +// Web app manifest — lets mobile users add Mind Builder to the homescreen with +// the brand mark and Mind Green chrome. Maskable icons (generated by +// scripts/gen-icons.mjs from the canonical mark) bleed green to the edges so the +// platform mask can crop the corners without clipping the weave. +export default function manifest(): MetadataRoute.Manifest { + return { + name: "Mind Builder — wish it, we build it", + short_name: "Builder", + description: + "Describe the website or app you wish you had, in your own words. We build it and give you a link to share. No coding, no setup. Everything we make stays yours.", + start_url: "/", + display: "standalone", + background_color: "#07080b", + theme_color: "#16B88A", + // Both PNGs live in public/ (served at the root) and carry the green to the + // edges; the 512 doubles as the "any" icon (a little safe-zone padding is + // fine there). Separate entries per purpose — Next's manifest type rejects + // the space-separated "any maskable" form the spec allows. + icons: [ + { + src: "/icon-192.png", + sizes: "192x192", + type: "image/png", + purpose: "maskable", + }, + { + src: "/icon-512.png", + sizes: "512x512", + type: "image/png", + purpose: "maskable", + }, + { + src: "/icon-512.png", + sizes: "512x512", + type: "image/png", + purpose: "any", + }, + ], + }; +} diff --git a/src/app/opengraph-image.tsx b/src/app/opengraph-image.tsx new file mode 100644 index 0000000..6dd536d --- /dev/null +++ b/src/app/opengraph-image.tsx @@ -0,0 +1,74 @@ +import { MIND_MARK_SVG } from "@mind-studio/ui/brand"; +import { ImageResponse } from "next/og"; + +export const alt = "Mind Builder — wish it, we build it"; +export const size = { width: 1200, height: 630 }; +export const contentType = "image/png"; + +// The canonical Mind mark as a data URI, so the share card carries the real +// brand artwork (sourced from the design system, never a vendored copy). +const MARK_DATA_URI = `data:image/svg+xml;base64,${Buffer.from(MIND_MARK_SVG).toString("base64")}`; + +// Social share card. Uses the default font (no remote fetch) so it renders +// deterministically at build time. Mind Green on dark to match the brand +// (green is the single UI accent; cyan/teal only as atmospheric glow). +export default function OpengraphImage() { + return new ImageResponse( +

+
+ {/* biome-ignore lint/performance/noImgElement: Satori (next/og) only supports . */} + + Builder +
+
+
+ Just describe it · we build it +
+
+ Wish it.  + We build it. +
+
+ Describe the website or app you wish you had — in your own words. No coding, no setup, and + everything we make stays yours. +
+
+ mindpods.org +
+
, + { ...size }, + ); +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 6ca6022..126c065 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,7 +1,7 @@ "use client"; import { MindLoginCard, writeLastIdentity } from "@mind-studio/core"; -import { Badge, Card, CardContent } from "@mind-studio/ui"; +import { Badge, Card, CardContent, Logo } from "@mind-studio/ui"; import { useRouter } from "next/navigation"; import { useEffect } from "react"; import { APP_NAME, oidcIssuer } from "@/lib/config"; @@ -177,12 +177,7 @@ export default function HomePage() { function TopBar() { return (
-
- - ✦ - - Mind Builder -
+