diff --git a/assets/brand-assets-2026-2/README.md b/assets/brand-assets-2026-2/README.md new file mode 100644 index 000000000..70b3b24c4 --- /dev/null +++ b/assets/brand-assets-2026-2/README.md @@ -0,0 +1,42 @@ +# WebBrain brand assets 2026 — v2 + +A non-destructive, typography-led refresh of the existing social card, store promos, +and banner set. The original top-level files remain unchanged. + +Type system: + +- Display headlines — **Instrument Serif** 400 +- Brand and supporting copy — **Instrument Sans** 400–700 +- Metadata, feature labels, and URLs — **Geist Mono** 500–600 + +All fonts are vendored and inlined at render time, so output is independent of locally +installed fonts. The OFL 1.1 license texts live beside the font files. + +Every PNG is rendered at 2× its target dimensions and then downsampled with the browser +canvas's high-quality image smoothing. This keeps the required output dimensions while +giving small wordmarks and supporting text cleaner antialiasing. + +Files: + +- `webbrain-social-card.png` — 1280×640 +- `webbrain-social-card-300x188.png` — 300×188 thumbnail derivative, retypeset rather than downscaled +- `store-promo-1400x560.png` — 1400×560 store marquee +- `store-promo-440x280.png` — 440×280 small store tile +- `banners/webbrain-banner-en.png` — 2560×800 English horizontal banner +- `banners/webbrain-banner-tr.png` — 2560×800 Turkish horizontal banner +- `banners/webbrain-banner-vertical-en.png` — 1280×2560 English vertical banner +- `website/og-image.png` — 1200×630 website social card; mirrored byte-for-byte to + `web/og-image.png` and `web/twitter-image.png` + +The typography direction was first checked with one AI style-transfer concept, then +implemented as deterministic HTML/CSS so the shipped assets preserve exact copy, +dimensions, logo artwork, and language-specific characters. + +Regenerate from the repository root: + +```bash +node assets/brand-assets-2026-2/render.mjs +``` + +The render command also refreshes the two website social-image files so metadata previews +cannot drift away from this source set. diff --git a/assets/brand-assets-2026-2/banners/webbrain-banner-en.png b/assets/brand-assets-2026-2/banners/webbrain-banner-en.png new file mode 100644 index 000000000..8a7ca7443 Binary files /dev/null and b/assets/brand-assets-2026-2/banners/webbrain-banner-en.png differ diff --git a/assets/brand-assets-2026-2/banners/webbrain-banner-tr.png b/assets/brand-assets-2026-2/banners/webbrain-banner-tr.png new file mode 100644 index 000000000..e1051f835 Binary files /dev/null and b/assets/brand-assets-2026-2/banners/webbrain-banner-tr.png differ diff --git a/assets/brand-assets-2026-2/banners/webbrain-banner-vertical-en.png b/assets/brand-assets-2026-2/banners/webbrain-banner-vertical-en.png new file mode 100644 index 000000000..ec8765a13 Binary files /dev/null and b/assets/brand-assets-2026-2/banners/webbrain-banner-vertical-en.png differ diff --git a/assets/brand-assets-2026-2/fonts/OFL-geistmono.txt b/assets/brand-assets-2026-2/fonts/OFL-geistmono.txt new file mode 100644 index 000000000..422d36474 --- /dev/null +++ b/assets/brand-assets-2026-2/fonts/OFL-geistmono.txt @@ -0,0 +1,93 @@ +Copyright 2024 The Geist Project Authors (https://github.com/vercel/geist-font.git) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/brand-assets-2026-2/fonts/OFL-instrumentsans.txt b/assets/brand-assets-2026-2/fonts/OFL-instrumentsans.txt new file mode 100644 index 000000000..d41633cc1 --- /dev/null +++ b/assets/brand-assets-2026-2/fonts/OFL-instrumentsans.txt @@ -0,0 +1,93 @@ +Copyright 2022 The Instrument Sans Project Authors (https://github.com/Instrument/instrument-sans) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/brand-assets-2026-2/fonts/OFL-instrumentserif.txt b/assets/brand-assets-2026-2/fonts/OFL-instrumentserif.txt new file mode 100644 index 000000000..e1801b959 --- /dev/null +++ b/assets/brand-assets-2026-2/fonts/OFL-instrumentserif.txt @@ -0,0 +1,93 @@ +Copyright 2022 The Instrument Serif Project Authors (https://github.com/Instrument/instrument-serif) + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/brand-assets-2026-2/fonts/geist-mono-var.woff2 b/assets/brand-assets-2026-2/fonts/geist-mono-var.woff2 new file mode 100644 index 000000000..cf24126b0 Binary files /dev/null and b/assets/brand-assets-2026-2/fonts/geist-mono-var.woff2 differ diff --git a/assets/brand-assets-2026-2/fonts/instrument-sans-var.woff2 b/assets/brand-assets-2026-2/fonts/instrument-sans-var.woff2 new file mode 100644 index 000000000..665fa65c8 Binary files /dev/null and b/assets/brand-assets-2026-2/fonts/instrument-sans-var.woff2 differ diff --git a/assets/brand-assets-2026-2/fonts/instrument-serif-400.woff2 b/assets/brand-assets-2026-2/fonts/instrument-serif-400.woff2 new file mode 100644 index 000000000..17653042a Binary files /dev/null and b/assets/brand-assets-2026-2/fonts/instrument-serif-400.woff2 differ diff --git a/assets/brand-assets-2026-2/render.mjs b/assets/brand-assets-2026-2/render.mjs new file mode 100644 index 000000000..d0a3c2aa7 --- /dev/null +++ b/assets/brand-assets-2026-2/render.mjs @@ -0,0 +1,771 @@ +import { chromium } from 'playwright'; +import { readFileSync } from 'node:fs'; +import { copyFile, mkdir, writeFile } from 'node:fs/promises'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const DIR = path.dirname(fileURLToPath(import.meta.url)); +const ROOT = path.resolve(DIR, '../..'); + +function dataUri(relativePath, mime) { + const bytes = readFileSync(path.join(ROOT, relativePath)); + return `data:${mime};base64,${bytes.toString('base64')}`; +} + +function fontUri(name) { + const bytes = readFileSync(path.join(DIR, 'fonts', name)); + return `data:font/woff2;base64,${bytes.toString('base64')}`; +} + +const assets = { + logo: dataUri('assets/logo-github.png', 'image/png'), +}; + +const fonts = { + display: fontUri('instrument-serif-400.woff2'), + sans: fontUri('instrument-sans-var.woff2'), + mono: fontUri('geist-mono-var.woff2'), +}; + +const SUPERSAMPLE = 2; + +const copy = { + en: { + headline: 'Open-source AI browser agent', + body: 'Chat with and act on any page — running local models, fully private.', + features: ['Chrome & Firefox', 'llama.cpp', 'OpenRouter', 'OpenAI', 'MIT licensed'], + bannerUrl: 'webbrain.one', + socialUrl: 'github.com/webbrain-one/webbrain', + }, + tr: { + headline: 'Yapay Zeka Chrome/Firefox Yardımcısı', + body: 'Herhangi bir sayfayla sohbet et, işlem yap — yerel modellerle, tamamen özel.', + features: ['Chrome & Firefox', 'llama.cpp', 'OpenRouter', 'OpenAI', 'MIT lisanslı'], + bannerUrl: 'webbrain.one/tr/', + }, +}; + +function featureRow(items, className = 'feature-row') { + return `
${items.map((item) => `${item}`).join('')}
`; +} + +const sharedCss = ` + @font-face { + font-family: 'Instrument Serif'; + src: url(${fonts.display}) format('woff2'); + font-style: normal; + font-weight: 400; + } + @font-face { + font-family: 'Instrument Sans'; + src: url(${fonts.sans}) format('woff2'); + font-style: normal; + font-weight: 400 700; + } + @font-face { + font-family: 'Geist Mono'; + src: url(${fonts.mono}) format('woff2'); + font-style: normal; + font-weight: 400 700; + } + :root { + color-scheme: light; + --display: 'Instrument Serif', ui-serif, Georgia, serif; + --sans: 'Instrument Sans', ui-sans-serif, system-ui, sans-serif; + --mono: 'Geist Mono', ui-monospace, SFMono-Regular, Menlo, monospace; + --ink: #11182c; + --muted: #55627a; + --quiet: #77839a; + --purple: #685cf6; + --cyan: #10b9ce; + --paper: #f8f8ff; + } + * { box-sizing: border-box; } + html, body { + margin: 0; + overflow: hidden; + font-family: var(--sans); + -webkit-font-smoothing: antialiased; + text-rendering: geometricPrecision; + } + .canvas { + position: relative; + overflow: hidden; + isolation: isolate; + } + .canvas::before { + content: ''; + position: absolute; + z-index: 2; + inset: 0 0 auto; + height: var(--rail, 7px); + background: linear-gradient(90deg, var(--purple), #8f59f3 44%, var(--cyan)); + } + .paper { + color: var(--ink); + background: + radial-gradient(circle at 18% 8%, rgba(104, 92, 246, 0.08), transparent 28%), + radial-gradient(circle at 92% 82%, rgba(16, 185, 206, 0.07), transparent 30%), + linear-gradient(145deg, #fbfbff, #f4f5ff); + } + .paper::after { + content: ''; + position: absolute; + z-index: -1; + right: -8%; + bottom: -34%; + width: 58%; + height: 62%; + opacity: 0.45; + transform: rotate(-8deg); + background: + linear-gradient(90deg, transparent 0 44px, rgba(104, 92, 246, 0.055) 44px 46px, transparent 46px 92px), + linear-gradient(0deg, transparent 0 44px, rgba(16, 185, 206, 0.05) 44px 46px, transparent 46px 92px); + } + .dark { + --ink: #f8f7ff; + --muted: #cbc7df; + --quiet: #aaa5c2; + color: var(--ink); + background: + radial-gradient(circle at 20% 54%, rgba(121, 97, 255, 0.34), transparent 29%), + radial-gradient(circle at 88% 105%, rgba(33, 194, 205, 0.12), transparent 34%), + linear-gradient(135deg, #17142f, #2c2458); + } + .logo { + display: block; + object-fit: cover; + border-radius: 24%; + box-shadow: + 0 18px 46px rgba(30, 21, 91, 0.22), + 0 0 0 1px rgba(255, 255, 255, 0.12); + } + .wordmark { + font-family: var(--sans); + font-weight: 700; + letter-spacing: -0.055em; + } + .headline { + margin: 0; + font-family: var(--display); + font-weight: 400; + letter-spacing: -0.025em; + } + .body-copy { + color: var(--muted); + font-weight: 450; + letter-spacing: -0.012em; + } + .accent { + width: 118px; + height: 5px; + border-radius: 99px; + background: linear-gradient(90deg, var(--purple), var(--cyan)); + } + .feature-row { + display: flex; + align-items: center; + justify-content: center; + color: var(--quiet); + font-family: var(--mono); + font-weight: 500; + letter-spacing: -0.025em; + } + .feature-row span { + display: inline-flex; + align-items: center; + white-space: nowrap; + } + .feature-row span + span::before { + content: '·'; + margin: 0 0.75em; + color: #b8bad0; + } + .url { + color: var(--purple); + font-family: var(--mono); + font-weight: 600; + letter-spacing: -0.035em; + } +`; + +function socialCard() { + const c = copy.en; + return { + file: 'webbrain-social-card.png', + width: 1280, + height: 640, + body: ` +
+
+ +

${c.headline}

+
+
${c.body}
+ ${featureRow(c.features)} +
${c.socialUrl}
+
+
`, + css: ` + .social-card { + --rail: 6px; + width: 1280px; + height: 640px; + } + .social-inner { + position: relative; + z-index: 1; + height: 100%; + padding: 62px 72px 45px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + } + .social-brand { + display: flex; + align-items: center; + gap: 24px; + } + .social-brand .logo { width: 112px; height: 112px; border-radius: 27px; } + .social-brand .wordmark { font-size: 61px; } + .social-card .headline { + margin-top: 59px; + font-size: 69px; + line-height: 0.98; + } + .social-card .accent { margin-top: 24px; } + .social-card .body-copy { margin-top: 34px; font-size: 25px; } + .social-card .feature-row { margin-top: 23px; font-size: 15px; } + .social-card .url { margin-top: auto; font-size: 17px; } + `, + }; +} + +function socialCardSmall() { + const c = copy.en; + return { + file: 'webbrain-social-card-300x188.png', + width: 300, + height: 188, + body: ` +
+
+
+ + WebBrain +
+

${c.headline}

+
+
${c.body}
+ ${featureRow(c.features)} +
${c.socialUrl}
+
+
`, + css: ` + .social-small { + --rail: 2px; + width: 300px; + height: 188px; + } + .small-inner { + position: relative; + z-index: 1; + height: 100%; + padding: 18px 17px 12px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + } + .small-brand { display: flex; align-items: center; gap: 7px; } + .small-brand .logo { width: 31px; height: 31px; border-radius: 8px; } + .small-brand .wordmark { font-size: 17px; letter-spacing: -0.045em; } + .social-small .headline { + margin-top: 17px; + font-size: 22px; + line-height: 1; + white-space: nowrap; + } + .social-small .accent { width: 35px; height: 2px; margin-top: 8px; } + .social-small .body-copy { + margin-top: 10px; + font-size: 7.6px; + line-height: 1.2; + white-space: nowrap; + } + .social-small .feature-row { margin-top: 7px; font-size: 5.4px; } + .social-small .feature-row span + span::before { margin: 0 0.56em; } + .social-small .url { margin-top: auto; font-size: 6.2px; } + `, + }; +} + +function websiteSocialCard() { + const c = copy.en; + return { + file: 'website/og-image.png', + width: 1200, + height: 630, + body: ` +
+
+
+ + WebBrain +
+

${c.headline}

+
+
${c.body}
+ ${featureRow(c.features)} +
${c.bannerUrl}
+
+
`, + css: ` + .website-social { + --rail: 6px; + width: 1200px; + height: 630px; + } + .website-social-inner { + position: relative; + z-index: 1; + height: 100%; + padding: 63px 68px 45px; + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + } + .website-social-brand { + display: flex; + align-items: center; + gap: 22px; + } + .website-social-brand .logo { width: 108px; height: 108px; border-radius: 26px; } + .website-social-brand .wordmark { font-size: 58px; } + .website-social .headline { + margin-top: 59px; + font-size: 67px; + line-height: 0.98; + } + .website-social .accent { margin-top: 24px; } + .website-social .body-copy { margin-top: 34px; font-size: 24px; } + .website-social .feature-row { margin-top: 23px; font-size: 14px; } + .website-social .url { margin-top: auto; font-size: 17px; } + `, + }; +} + +function storeMarquee() { + return { + file: 'store-promo-1400x560.png', + width: 1400, + height: 560, + body: ` +
+
+
+ +
+
+
WebBrain
+

Open-Source AI Browser Agent

+
Any LLM. Any Page. Your Data.
+
+ MIT LICENSED + 11+ PROVIDERS + LOCAL OR CLOUD + MV3 & MV2 +
+
+
`, + css: ` + .store-marquee { + --rail: 7px; + width: 1400px; + height: 560px; + display: grid; + grid-template-columns: 470px 1fr; + align-items: center; + padding: 56px 95px 48px 80px; + } + .store-icon-wrap { + position: relative; + width: 350px; + height: 350px; + display: grid; + place-items: center; + } + .store-orbit { + position: absolute; + inset: 0; + border: 1px solid rgba(178, 165, 255, 0.25); + border-radius: 50%; + box-shadow: inset 0 0 80px rgba(104, 92, 246, 0.08); + } + .store-orbit::after { + content: ''; + position: absolute; + width: 11px; + height: 11px; + top: 38px; + right: 61px; + border-radius: 50%; + background: var(--cyan); + box-shadow: 0 0 22px rgba(16, 185, 206, 0.8); + } + .store-icon-wrap .logo { width: 246px; height: 246px; border-radius: 58px; } + .store-copy { align-self: center; padding-top: 2px; } + .store-marquee .wordmark { font-size: 101px; line-height: 0.95; } + .store-marquee .headline { + margin-top: 27px; + color: #e1dff1; + font-size: 47px; + line-height: 1; + letter-spacing: -0.018em; + } + .store-marquee .body-copy { margin-top: 19px; font-size: 27px; } + .store-pills { display: flex; gap: 11px; margin-top: 40px; } + .store-pills span { + padding: 10px 15px 9px; + border: 1px solid rgba(180, 169, 255, 0.34); + border-radius: 999px; + background: rgba(111, 91, 230, 0.14); + color: #e9e7f5; + font-family: var(--mono); + font-size: 13px; + font-weight: 600; + letter-spacing: 0.045em; + } + `, + }; +} + +function storeSmall() { + return { + file: 'store-promo-440x280.png', + width: 440, + height: 280, + body: ` +
+
+ +
+
+
WebBrain
+

Open-Source AI Browser Agent

+
Any LLM. Any Page. Your Data.
+
+
+
`, + css: ` + .store-small { + --rail: 3px; + width: 440px; + height: 280px; + display: grid; + grid-template-columns: 140px 1fr; + align-items: center; + padding: 36px 29px 32px 32px; + } + .small-store-icon { + width: 120px; + height: 120px; + display: grid; + place-items: center; + border: 1px solid rgba(180, 169, 255, 0.22); + border-radius: 50%; + } + .small-store-icon .logo { width: 91px; height: 91px; border-radius: 22px; } + .small-store-copy { padding-left: 9px; } + .store-small .wordmark { font-size: 41px; line-height: 1; } + .store-small .headline { + margin-top: 17px; + color: #e1dff1; + font-size: 19px; + line-height: 1.04; + } + .store-small .body-copy { margin-top: 11px; font-size: 12.5px; } + .mini-rule { + width: 42px; + height: 2px; + margin-top: 23px; + border-radius: 99px; + background: linear-gradient(90deg, #8f79ff, var(--cyan)); + } + `, + }; +} + +function banner(locale) { + const c = copy[locale]; + const isTurkish = locale === 'tr'; + return { + file: `banners/webbrain-banner-${locale}.png`, + width: 2560, + height: 800, + body: ` +
+ + + +
`, + css: ` + .banner-wide { + --rail: 12px; + width: 2560px; + height: 800px; + display: grid; + grid-template-columns: 520px 1px 1fr; + align-items: center; + gap: 0; + padding: 86px 110px 74px; + } + .banner-brand { + display: flex; + flex-direction: column; + align-items: flex-start; + padding-left: 28px; + } + .banner-brand .logo { width: 238px; height: 238px; border-radius: 56px; } + .banner-wordmark { margin-top: 30px; font-size: 67px; line-height: 1; } + .banner-brand .url { margin-top: 24px; font-size: 27px; } + .banner-divider { + width: 1px; + height: 520px; + background: linear-gradient(transparent, rgba(104, 92, 246, 0.2) 12%, rgba(104, 92, 246, 0.2) 88%, transparent); + } + .banner-message { + min-width: 0; + padding-left: 110px; + } + .banner-wide .headline { + font-size: 112px; + line-height: 0.96; + white-space: nowrap; + } + .banner-tr .headline { font-size: 89px; letter-spacing: -0.03em; } + .banner-wide .accent { margin-top: 43px; width: 180px; height: 7px; } + .banner-wide .body-copy { + margin-top: 48px; + font-size: 38px; + line-height: 1.25; + white-space: nowrap; + } + .banner-wide .feature-row { + justify-content: flex-start; + margin-top: 43px; + font-size: 21px; + } + `, + }; +} + +function bannerVertical() { + const c = copy.en; + return { + file: 'banners/webbrain-banner-vertical-en.png', + width: 1280, + height: 2560, + body: ` +
+
+ + WebBrain +
+
+
OPEN SOURCE · ANY LLM
+

Open-source
AI browser
agent

+
+
${c.body}
+
+
+ ${c.features.map((item, index) => ` +
+ ${String(index + 1).padStart(2, '0')} + ${item} +
`).join('')} +
+ +
`, + css: ` + .banner-vertical { + --rail: 12px; + width: 1280px; + height: 2560px; + padding: 112px 105px 98px; + display: flex; + flex-direction: column; + } + .vertical-brand { + display: flex; + align-items: center; + gap: 38px; + } + .vertical-brand .logo { width: 206px; height: 206px; border-radius: 49px; } + .vertical-brand .wordmark { font-size: 91px; } + .vertical-message { margin-top: 275px; } + .vertical-kicker { + color: var(--purple); + font-family: var(--mono); + font-size: 25px; + font-weight: 600; + letter-spacing: 0.15em; + } + .banner-vertical .headline { + margin-top: 48px; + max-width: 990px; + font-size: 151px; + line-height: 0.91; + } + .banner-vertical .accent { width: 210px; height: 8px; margin-top: 62px; } + .banner-vertical .body-copy { + max-width: 970px; + margin-top: 76px; + font-size: 48px; + line-height: 1.34; + } + .vertical-features { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 18px; + margin-top: 140px; + } + .vertical-feature { + min-height: 116px; + padding: 26px 28px; + display: grid; + grid-template-columns: 50px 1fr; + align-items: center; + gap: 17px; + border: 1px solid rgba(104, 92, 246, 0.16); + border-radius: 20px; + background: rgba(255, 255, 255, 0.55); + box-shadow: 0 18px 54px rgba(34, 41, 91, 0.055); + } + .vertical-feature span { + color: var(--purple); + font-family: var(--mono); + font-size: 17px; + } + .vertical-feature strong { + color: var(--muted); + font-family: var(--mono); + font-size: 21px; + font-weight: 550; + letter-spacing: -0.03em; + } + .vertical-feature:last-child { + grid-column: 1 / -1; + width: calc(50% - 9px); + } + .vertical-footer { + margin-top: auto; + padding-top: 56px; + border-top: 1px solid rgba(104, 92, 246, 0.14); + } + .vertical-footer .url { font-size: 30px; } + `, + }; +} + +const scenes = [ + socialCard(), + socialCardSmall(), + websiteSocialCard(), + storeMarquee(), + storeSmall(), + banner('en'), + banner('tr'), + bannerVertical(), +]; + +function html(scene) { + return ` + + + + + + ${scene.body} + `; +} + +async function renderAll() { + const browser = await chromium.launch(); + try { + for (const scene of scenes) { + const output = path.join(DIR, scene.file); + await mkdir(path.dirname(output), { recursive: true }); + + const page = await browser.newPage({ + viewport: { width: scene.width, height: scene.height }, + deviceScaleFactor: SUPERSAMPLE, + }); + await page.setContent(html(scene), { waitUntil: 'load' }); + await page.evaluate(async () => { + await Promise.all(Array.from(document.images).map((image) => { + if (image.complete) return undefined; + return new Promise((resolve, reject) => { + image.addEventListener('load', resolve, { once: true }); + image.addEventListener('error', reject, { once: true }); + }); + })); + await document.fonts.ready; + }); + const supersampled = await page.screenshot({ scale: 'device' }); + const finalBase64 = await page.evaluate(async ({ pngBase64, width, height }) => { + const image = new Image(); + image.src = `data:image/png;base64,${pngBase64}`; + await image.decode(); + + const canvas = document.createElement('canvas'); + canvas.width = width; + canvas.height = height; + const context = canvas.getContext('2d'); + context.imageSmoothingEnabled = true; + context.imageSmoothingQuality = 'high'; + context.drawImage(image, 0, 0, width, height); + return canvas.toDataURL('image/png').slice('data:image/png;base64,'.length); + }, { + pngBase64: supersampled.toString('base64'), + width: scene.width, + height: scene.height, + }); + await writeFile(output, Buffer.from(finalBase64, 'base64')); + await page.close(); + console.log('rendered', path.relative(DIR, output)); + } + + const websiteSocial = path.join(DIR, 'website', 'og-image.png'); + await copyFile(websiteSocial, path.join(ROOT, 'web', 'og-image.png')); + await copyFile(websiteSocial, path.join(ROOT, 'web', 'twitter-image.png')); + console.log('synced web/og-image.png and web/twitter-image.png'); + } finally { + await browser.close(); + } +} + +renderAll().catch((error) => { + console.error(error); + process.exit(1); +}); diff --git a/assets/brand-assets-2026-2/store-promo-1400x560.png b/assets/brand-assets-2026-2/store-promo-1400x560.png new file mode 100644 index 000000000..19fdad144 Binary files /dev/null and b/assets/brand-assets-2026-2/store-promo-1400x560.png differ diff --git a/assets/brand-assets-2026-2/store-promo-440x280.png b/assets/brand-assets-2026-2/store-promo-440x280.png new file mode 100644 index 000000000..cc98f598a Binary files /dev/null and b/assets/brand-assets-2026-2/store-promo-440x280.png differ diff --git a/assets/brand-assets-2026-2/webbrain-social-card-300x188.png b/assets/brand-assets-2026-2/webbrain-social-card-300x188.png new file mode 100644 index 000000000..357eb1ef2 Binary files /dev/null and b/assets/brand-assets-2026-2/webbrain-social-card-300x188.png differ diff --git a/assets/brand-assets-2026-2/webbrain-social-card.png b/assets/brand-assets-2026-2/webbrain-social-card.png new file mode 100644 index 000000000..27dce95ba Binary files /dev/null and b/assets/brand-assets-2026-2/webbrain-social-card.png differ diff --git a/assets/brand-assets-2026-2/website/og-image.png b/assets/brand-assets-2026-2/website/og-image.png new file mode 100644 index 000000000..35edc2159 Binary files /dev/null and b/assets/brand-assets-2026-2/website/og-image.png differ diff --git a/package.json b/package.json index becbb7ffc..32751f1a9 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "build:web": "npm run build:web:landing && npm run build:blog && npm run build:docs", "build:zip": "node scripts/build-zip.mjs", "trace:otlp": "node scripts/trace-to-otlp.mjs", - "sync:logo": "python3 scripts/sync-logo-assets.py && python3 scripts/gen-store-promos.py && node assets/webstore-explainer-2026/render.mjs", + "sync:logo": "python3 scripts/sync-logo-assets.py && python3 scripts/gen-store-promos.py && node assets/webstore-explainer-2026/render.mjs && node assets/brand-assets-2026-2/render.mjs", "bump": "node scripts/bump-version.mjs", "release": "node scripts/bump-version.mjs --release" }, diff --git a/scripts/build-blog.mjs b/scripts/build-blog.mjs index fe205aff7..93cfcf184 100644 --- a/scripts/build-blog.mjs +++ b/scripts/build-blog.mjs @@ -1159,12 +1159,12 @@ function sharedHead({ title, description, canonical, ogType = 'website', ogTitle - - + + - + diff --git a/scripts/sync-logo-assets.py b/scripts/sync-logo-assets.py index b4782ebf2..d4b17fe4d 100644 --- a/scripts/sync-logo-assets.py +++ b/scripts/sync-logo-assets.py @@ -53,20 +53,6 @@ def icon_logo(mark: Image.Image, size: int) -> Image.Image: return cropped.resize((size, size), Image.Resampling.LANCZOS) -def wide_social_logo(source: Image.Image, width: int, height: int) -> Image.Image: - """Center the full logo on a row-matched background for seamless sides.""" - square = full_logo(source, height).convert("RGB") - canvas = Image.new("RGB", (width, height)) - draw = ImageDraw.Draw(canvas) - for y in range(height): - left = square.getpixel((0, y)) - right = square.getpixel((height - 1, y)) - color = tuple((left[i] + right[i]) // 2 for i in range(3)) - draw.line((0, y, width, y), fill=color) - canvas.paste(square, ((width - height) // 2, 0)) - return canvas - - def save_png(image: Image.Image, path: Path) -> None: path.parent.mkdir(parents=True, exist_ok=True) image.save(path, format="PNG", optimize=True) @@ -119,8 +105,9 @@ def main() -> None: shutil.copyfile(CANONICAL, WEB / "logo-github.png") save_png(icon_logo(mark, 64), WEB / "favicon.png") - save_png(full_logo(source, 512), WEB / "twitter-image.png") - save_png(wide_social_logo(source, 1200, 630), WEB / "og-image.png") + # Website social cards are typography-led composites generated by + # assets/brand-assets-2026-2/render.mjs. Do not replace them with + # logo-only derivatives here. for path, box, radius in COMPOSITE_LOGOS: replace_composite_logo(path, source, box, radius) diff --git a/test/run.js b/test/run.js index 93c244a4d..d8046e693 100644 --- a/test/run.js +++ b/test/run.js @@ -15270,8 +15270,11 @@ test('logo metadata and generated icon assets use the correct canonical artwork assert.ok(expected.equals(read(rel)), `${rel}: same-size logo derivatives should be identical`); } } - assert.deepEqual(dimensions('web/twitter-image.png'), [512, 512]); + assert.deepEqual(dimensions('web/twitter-image.png'), [1200, 630]); assert.deepEqual(dimensions('web/og-image.png'), [1200, 630]); + const websiteSocial = read('assets/brand-assets-2026-2/website/og-image.png'); + assert.ok(websiteSocial.equals(read('web/og-image.png')), 'website OG image should match its rendered source'); + assert.ok(websiteSocial.equals(read('web/twitter-image.png')), 'website Twitter image should match its rendered source'); assert.deepEqual(dimensions('assets/store-promo-440x280.png'), [440, 280]); assert.deepEqual(dimensions('assets/store-promo-1400x560.png'), [1400, 560]); for (const [rel, size] of [ @@ -15281,6 +15284,13 @@ test('logo metadata and generated icon assets use the correct canonical artwork ['assets/webbrain-social-card-300x188.png', [300, 188]], ['assets/webbrain-social-card.png', [1280, 640]], ['web/assets/webbrain-ollama-heart.png', [1200, 630]], + ['assets/brand-assets-2026-2/webbrain-social-card-300x188.png', [300, 188]], + ['assets/brand-assets-2026-2/webbrain-social-card.png', [1280, 640]], + ['assets/brand-assets-2026-2/store-promo-440x280.png', [440, 280]], + ['assets/brand-assets-2026-2/store-promo-1400x560.png', [1400, 560]], + ['assets/brand-assets-2026-2/banners/webbrain-banner-en.png', [2560, 800]], + ['assets/brand-assets-2026-2/banners/webbrain-banner-tr.png', [2560, 800]], + ['assets/brand-assets-2026-2/banners/webbrain-banner-vertical-en.png', [1280, 2560]], ]) { assert.deepEqual(dimensions(rel), size, `${rel}: branded composite dimensions changed`); } @@ -15289,20 +15299,29 @@ test('logo metadata and generated icon assets use the correct canonical artwork assert.match(packageJson.scripts['sync:logo'], /sync-logo-assets\.py/); assert.match(packageJson.scripts['sync:logo'], /gen-store-promos\.py/); assert.match(packageJson.scripts['sync:logo'], /webstore-explainer-2026\/render\.mjs/); + assert.match(packageJson.scripts['sync:logo'], /brand-assets-2026-2\/render\.mjs/); const logoSync = fs.readFileSync(path.join(ROOT, 'scripts/sync-logo-assets.py'), 'utf8'); assert.match(logoSync, /MARK = ROOT \/ "assets" \/ "logo-mark\.png"/); assert.match(logoSync, /save_png\(icon_logo\(mark, size\), icon_dir/); assert.match(logoSync, /save_jpeg\(full_logo\(source, 128\), ASSETS \/ "logo-github-128\.jpg"\)/); assert.match(logoSync, /replace_composite_logo\(path, source, box, radius\)/); + assert.doesNotMatch(logoSync, /WEB \/ "twitter-image\.png"|WEB \/ "og-image\.png"/); const template = fs.readFileSync(path.join(ROOT, 'web/build/template.html'), 'utf8'); const blogBuilder = fs.readFileSync(path.join(ROOT, 'scripts/build-blog.mjs'), 'utf8'); assert.match(template, //); assert.match(template, /class="brand-logo" src="\/logo-github\.png"/); assert.match(blogBuilder, /class="brand-logo" src="\/logo-github\.png"/); + assert.match(template, //); + assert.match(template, //); + assert.match(blogBuilder, //); assert.doesNotMatch(template + blogBuilder, /favicon\.svg|brain emoji icon|🧠/); + const brandRenderer = fs.readFileSync(path.join(ROOT, 'assets/brand-assets-2026-2/render.mjs'), 'utf8'); + assert.match(brandRenderer, /const SUPERSAMPLE = 2/); + assert.match(brandRenderer, /imageSmoothingQuality = 'high'/); + for (const [label, rel] of [ ['chrome', 'src/chrome/manifest.json'], ['firefox', 'src/firefox/manifest.json'], diff --git a/web/ar/index.html b/web/ar/index.html index f5d436619..050187bfa 100644 --- a/web/ar/index.html +++ b/web/ar/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/blog/agent-security-model/index.html b/web/blog/agent-security-model/index.html index d8e172529..eb1ec5553 100644 --- a/web/blog/agent-security-model/index.html +++ b/web/blog/agent-security-model/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/agents-a1-webbrain-planner-benchmark/index.html b/web/blog/agents-a1-webbrain-planner-benchmark/index.html index a3a88fc15..a6394f39c 100644 --- a/web/blog/agents-a1-webbrain-planner-benchmark/index.html +++ b/web/blog/agents-a1-webbrain-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/five-things-you-shouldnt-do-with-webbrain/index.html b/web/blog/five-things-you-shouldnt-do-with-webbrain/index.html index 7ec10d973..854509329 100644 --- a/web/blog/five-things-you-shouldnt-do-with-webbrain/index.html +++ b/web/blog/five-things-you-shouldnt-do-with-webbrain/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/gemma-4-12b-qat-planner-benchmark/index.html b/web/blog/gemma-4-12b-qat-planner-benchmark/index.html index e22328a82..d279b6342 100644 --- a/web/blog/gemma-4-12b-qat-planner-benchmark/index.html +++ b/web/blog/gemma-4-12b-qat-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/gemma-4-31b-qat-planner-benchmark/index.html b/web/blog/gemma-4-31b-qat-planner-benchmark/index.html index 2bc30e763..e2cc2e824 100644 --- a/web/blog/gemma-4-31b-qat-planner-benchmark/index.html +++ b/web/blog/gemma-4-31b-qat-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/gemma4-turkish-pruning/index.html b/web/blog/gemma4-turkish-pruning/index.html index 3d11b4593..1185578c1 100644 --- a/web/blog/gemma4-turkish-pruning/index.html +++ b/web/blog/gemma4-turkish-pruning/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/glm52-nvidia-webbrain-planner-benchmark/index.html b/web/blog/glm52-nvidia-webbrain-planner-benchmark/index.html index 369f1e715..77a477db2 100644 --- a/web/blog/glm52-nvidia-webbrain-planner-benchmark/index.html +++ b/web/blog/glm52-nvidia-webbrain-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/index.html b/web/blog/index.html index c076cf687..4f8a1d613 100644 --- a/web/blog/index.html +++ b/web/blog/index.html @@ -14,12 +14,12 @@ - - + + - + diff --git a/web/blog/liquid-lfm25-tool-calling/index.html b/web/blog/liquid-lfm25-tool-calling/index.html index b95d53c94..a1152cf07 100644 --- a/web/blog/liquid-lfm25-tool-calling/index.html +++ b/web/blog/liquid-lfm25-tool-calling/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/llm-tool-calling-benchmark/index.html b/web/blog/llm-tool-calling-benchmark/index.html index 484968a1d..9658c91e9 100644 --- a/web/blog/llm-tool-calling-benchmark/index.html +++ b/web/blog/llm-tool-calling-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/local-planner-q4-june-2026/index.html b/web/blog/local-planner-q4-june-2026/index.html index fddb8fe71..5565e83e1 100644 --- a/web/blog/local-planner-q4-june-2026/index.html +++ b/web/blog/local-planner-q4-june-2026/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/mimo-v25-pro-vs-flash/index.html b/web/blog/mimo-v25-pro-vs-flash/index.html index 6016c7a6a..e8bb9ae92 100644 --- a/web/blog/mimo-v25-pro-vs-flash/index.html +++ b/web/blog/mimo-v25-pro-vs-flash/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/minimax-m3-webbrain-cloud-tool-calling/index.html b/web/blog/minimax-m3-webbrain-cloud-tool-calling/index.html index 9c202a5b4..5e54880d3 100644 --- a/web/blog/minimax-m3-webbrain-cloud-tool-calling/index.html +++ b/web/blog/minimax-m3-webbrain-cloud-tool-calling/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/molmo2-8b-tool-calling/index.html b/web/blog/molmo2-8b-tool-calling/index.html index 1c416d79b..27412fafe 100644 --- a/web/blog/molmo2-8b-tool-calling/index.html +++ b/web/blog/molmo2-8b-tool-calling/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/nanbeige-42-3b-bf16-planner-benchmark/index.html b/web/blog/nanbeige-42-3b-bf16-planner-benchmark/index.html index b050e9143..d2b9dce4d 100644 --- a/web/blog/nanbeige-42-3b-bf16-planner-benchmark/index.html +++ b/web/blog/nanbeige-42-3b-bf16-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/nemotron3-ultra-openrouter-planner-benchmark/index.html b/web/blog/nemotron3-ultra-openrouter-planner-benchmark/index.html index 641ca560d..4fb011ec3 100644 --- a/web/blog/nemotron3-ultra-openrouter-planner-benchmark/index.html +++ b/web/blog/nemotron3-ultra-openrouter-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/nex-n2-mini-openrouter-planner-benchmark/index.html b/web/blog/nex-n2-mini-openrouter-planner-benchmark/index.html index c2ecac1c8..051a05fe6 100644 --- a/web/blog/nex-n2-mini-openrouter-planner-benchmark/index.html +++ b/web/blog/nex-n2-mini-openrouter-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/ollama-launch-handoff/index.html b/web/blog/ollama-launch-handoff/index.html index 5de9f9c0c..0e3b4ff62 100644 --- a/web/blog/ollama-launch-handoff/index.html +++ b/web/blog/ollama-launch-handoff/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/ornith-35b-webbrain-planner-benchmark/index.html b/web/blog/ornith-35b-webbrain-planner-benchmark/index.html index abc426742..ba489eac7 100644 --- a/web/blog/ornith-35b-webbrain-planner-benchmark/index.html +++ b/web/blog/ornith-35b-webbrain-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/poolside-laguna-m1-openrouter-planner-benchmark/index.html b/web/blog/poolside-laguna-m1-openrouter-planner-benchmark/index.html index ff8b4102a..ffd28ad8b 100644 --- a/web/blog/poolside-laguna-m1-openrouter-planner-benchmark/index.html +++ b/web/blog/poolside-laguna-m1-openrouter-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/poolside-laguna-s-openrouter-planner-benchmark/index.html b/web/blog/poolside-laguna-s-openrouter-planner-benchmark/index.html index da9ec149d..52fe1b120 100644 --- a/web/blog/poolside-laguna-s-openrouter-planner-benchmark/index.html +++ b/web/blog/poolside-laguna-s-openrouter-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/poolside-laguna-xs-openrouter-planner-benchmark/index.html b/web/blog/poolside-laguna-xs-openrouter-planner-benchmark/index.html index b066be3d8..fee5f09a7 100644 --- a/web/blog/poolside-laguna-xs-openrouter-planner-benchmark/index.html +++ b/web/blog/poolside-laguna-xs-openrouter-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/qwen36-27b-nvfp4-planner-benchmark/index.html b/web/blog/qwen36-27b-nvfp4-planner-benchmark/index.html index 6532d1050..ef641c5a0 100644 --- a/web/blog/qwen36-27b-nvfp4-planner-benchmark/index.html +++ b/web/blog/qwen36-27b-nvfp4-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/qwen37-plus-openrouter-planner-benchmark/index.html b/web/blog/qwen37-plus-openrouter-planner-benchmark/index.html index c0b1e100c..128a501bc 100644 --- a/web/blog/qwen37-plus-openrouter-planner-benchmark/index.html +++ b/web/blog/qwen37-plus-openrouter-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/tencent-hy3-openrouter-planner-benchmark/index.html b/web/blog/tencent-hy3-openrouter-planner-benchmark/index.html index 9b84aec56..92f999548 100644 --- a/web/blog/tencent-hy3-openrouter-planner-benchmark/index.html +++ b/web/blog/tencent-hy3-openrouter-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/thinking-machines-inkling-openrouter-planner-benchmark/index.html b/web/blog/thinking-machines-inkling-openrouter-planner-benchmark/index.html index eb494349d..d6dab58ae 100644 --- a/web/blog/thinking-machines-inkling-openrouter-planner-benchmark/index.html +++ b/web/blog/thinking-machines-inkling-openrouter-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/thinkingcap-qwen36-27b-planner-benchmark/index.html b/web/blog/thinkingcap-qwen36-27b-planner-benchmark/index.html index a2d42b4ed..d85828c4f 100644 --- a/web/blog/thinkingcap-qwen36-27b-planner-benchmark/index.html +++ b/web/blog/thinkingcap-qwen36-27b-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/tiny-lfm25-raw-planner-benchmark/index.html b/web/blog/tiny-lfm25-raw-planner-benchmark/index.html index a21723d1e..142ca9193 100644 --- a/web/blog/tiny-lfm25-raw-planner-benchmark/index.html +++ b/web/blog/tiny-lfm25-raw-planner-benchmark/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/vision-model-shootout/index.html b/web/blog/vision-model-shootout/index.html index 6932ece96..78f2904f0 100644 --- a/web/blog/vision-model-shootout/index.html +++ b/web/blog/vision-model-shootout/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/vision-shootout-round-2/index.html b/web/blog/vision-shootout-round-2/index.html index aa176eb83..b3f2d9f54 100644 --- a/web/blog/vision-shootout-round-2/index.html +++ b/web/blog/vision-shootout-round-2/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/vision-shootout-round-3/index.html b/web/blog/vision-shootout-round-3/index.html index 55dffa8bf..221e568b3 100644 --- a/web/blog/vision-shootout-round-3/index.html +++ b/web/blog/vision-shootout-round-3/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/vision-shootout-round-4/index.html b/web/blog/vision-shootout-round-4/index.html index fc4b55e48..10fd9b334 100644 --- a/web/blog/vision-shootout-round-4/index.html +++ b/web/blog/vision-shootout-round-4/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/webbrain-cloud-local-model-benchmarks/index.html b/web/blog/webbrain-cloud-local-model-benchmarks/index.html index 4536b1fd8..90fc0b75c 100644 --- a/web/blog/webbrain-cloud-local-model-benchmarks/index.html +++ b/web/blog/webbrain-cloud-local-model-benchmarks/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/blog/webmcp-integration/index.html b/web/blog/webmcp-integration/index.html index 848936b4a..ba0df44e2 100644 --- a/web/blog/webmcp-integration/index.html +++ b/web/blog/webmcp-integration/index.html @@ -15,12 +15,12 @@ - - + + - + diff --git a/web/bn/index.html b/web/bn/index.html index 2217b7a41..499a8e18b 100644 --- a/web/bn/index.html +++ b/web/bn/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/build/template.html b/web/build/template.html index f1133f6f5..d9b123a86 100644 --- a/web/build/template.html +++ b/web/build/template.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/de/index.html b/web/de/index.html index c4f172ccd..be64608e1 100644 --- a/web/de/index.html +++ b/web/de/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/es/index.html b/web/es/index.html index b2caddcac..a3ff452af 100644 --- a/web/es/index.html +++ b/web/es/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/fa/index.html b/web/fa/index.html index 3d145101a..a5ff2c7f5 100644 --- a/web/fa/index.html +++ b/web/fa/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/fr/index.html b/web/fr/index.html index de5d1a9e3..26d8ac231 100644 --- a/web/fr/index.html +++ b/web/fr/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/he/index.html b/web/he/index.html index 88157ce00..e5af47404 100644 --- a/web/he/index.html +++ b/web/he/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/hi/index.html b/web/hi/index.html index 8b6795d66..0ecc21177 100644 --- a/web/hi/index.html +++ b/web/hi/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/id/index.html b/web/id/index.html index cfd37cf1f..a51aba306 100644 --- a/web/id/index.html +++ b/web/id/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/index.html b/web/index.html index a0017debd..daae1ddf1 100644 --- a/web/index.html +++ b/web/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/ja/index.html b/web/ja/index.html index b98a5f7ae..846dcac98 100644 --- a/web/ja/index.html +++ b/web/ja/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/ko/index.html b/web/ko/index.html index 1e5221231..d35ce4103 100644 --- a/web/ko/index.html +++ b/web/ko/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/ms/index.html b/web/ms/index.html index 71155b398..4d6afc8ca 100644 --- a/web/ms/index.html +++ b/web/ms/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/nl/index.html b/web/nl/index.html index 7a25a17bf..8c0b0f10f 100644 --- a/web/nl/index.html +++ b/web/nl/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/og-image.png b/web/og-image.png index eb3eb99d5..35edc2159 100644 Binary files a/web/og-image.png and b/web/og-image.png differ diff --git a/web/pt/index.html b/web/pt/index.html index 54cb88714..3875e4e98 100644 --- a/web/pt/index.html +++ b/web/pt/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/ru/index.html b/web/ru/index.html index ed46b7657..57ccce460 100644 --- a/web/ru/index.html +++ b/web/ru/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/th/index.html b/web/th/index.html index 53e831838..d80d10fad 100644 --- a/web/th/index.html +++ b/web/th/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/tl/index.html b/web/tl/index.html index 4f82fddfb..7229db285 100644 --- a/web/tl/index.html +++ b/web/tl/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/tr/index.html b/web/tr/index.html index 875dce83e..1ff946534 100644 --- a/web/tr/index.html +++ b/web/tr/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/twitter-image.png b/web/twitter-image.png index e00965604..35edc2159 100644 Binary files a/web/twitter-image.png and b/web/twitter-image.png differ diff --git a/web/uk/index.html b/web/uk/index.html index 9c640da00..fd3d9fa68 100644 --- a/web/uk/index.html +++ b/web/uk/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/vi/index.html b/web/vi/index.html index 8e3039bab..fc365e875 100644 --- a/web/vi/index.html +++ b/web/vi/index.html @@ -17,12 +17,12 @@ - - + + - + diff --git a/web/zh/index.html b/web/zh/index.html index 3c710221d..c8032fcae 100644 --- a/web/zh/index.html +++ b/web/zh/index.html @@ -17,12 +17,12 @@ - - + + - +