Ce document s’adresse aux agents IA (Claude Code, Codex, ou tout agent qui pilote un navigateur via Playwright / CDP, ou qui exécute du JavaScript dans la page). Il explique comment utiliser le générateur de guide de marque (app.html) : importer un ou deux .binksy, partir de zéro, ajouter des assets, choisir un style, régler les crédits du graphiste et exporter le site, avec l’API publique window.binksyGuide.
Il existe en deux endroits, toujours identiques : AGENTS.md (Markdown, français puis anglais) et la page agent/index.html. Résumé court : llms.txt.
Points d’entrée découvrables sans JavaScript : index.html et docs.html déclarent <link rel="alternate" type="text/markdown" href="AGENTS.md">, <link rel="help" href="agent/"> et <link rel="alternate" type="text/plain" href="llms.txt">, contiennent un commentaire HTML et un <noscript> qui renvoient ici. robots.txt autorise tout et cite llms.txt et AGENTS.md.
01Règle fondamentale
Le générateur met en page ce que le graphiste fournit. Ce n’est pas un générateur de logos ni de contenus de marque.
- N’invente jamais un logo, un symbole, une icône, une couleur de marque, une police ou un texte de marque (nom, slogan, présentation, valeurs). Ce que l’utilisateur fournit (fichiers
.binksy, SVG, couleurs, polices, textes, assets) fait foi. - Ne redessine pas un SVG fourni et ne modifie pas sa géométrie. Ne remplace pas un fichier manquant par un fichier « approchant ».
- Un titre ou une introduction que tu proposes reste une suggestion : fais-la valider avant de l’enregistrer avec
setOptions. - Aucune clé API, aucun service en ligne. Le générateur n’embarque aucune IA ; c’est toi qui décides et vérifies. Ne demande jamais de clé à l’utilisateur.
- Tout est local : lecture des fichiers, calculs et ZIP sont faits dans le navigateur. Rien n’est envoyé à un serveur. Les réglages sont mémorisés dans le stockage du navigateur.
Après chaque action : relis await binksyGuide.state(). Un appel ou un clic n’est pas une preuve de réussite.
02Démarrer
Lancer le générateur
Le site déployé (dossier dist/, produit par python3 build.py) contient : index.html (accueil), app.html (le générateur), docs.html (documentation), agent/index.html (cette page), AGENTS.md, llms.txt, robots.txt, demo/ (fichiers de démonstration) et assets/.
cd dist && python3 -m http.server 8000
# puis ouvrir http://127.0.0.1:8000/app.html
- http:// recommandé : les fichiers de démo et les URL relatives (
demo/avora.binksy) se chargent parfetch. - file:// marche aussi (ouvrir
app.htmldirectement), mais les navigateurs bloquentfetchsurfile://: passe alors les fichiers enFile/Blob,ArrayBuffer,Uint8Array, data URL ou base64, pas en URL. - N’importe quel hébergement statique convient (Netlify, Vercel, GitHub Pages…).
- Utilise un profil de navigateur dédié aux tests : les réglages (style, crédits…) sont mémorisés pour l’origine.
Deux façons de piloter
- API JavaScript (recommandé) :
window.binksyGuide, dansapp.html. - Clics : les commandes clés portent un attribut stable
data-agent(voir § 9).
await binksyGuide.ready();
binksyGuide.version; // "2.0.0"
binksyGuide.help(); // [{name, signature, description}]
await binksyGuide.state();
03Conventions de l’API
- Toutes les méthodes sont async (sauf
version,help()etstyles()) et renvoient du JSON simple. - Fichiers acceptés :
File/Blob,ArrayBuffer,Uint8Array, data URL, base64, URL relative ou absolue (chargée parfetch) et, pour les SVG, le texte SVG lui-même. - Une erreur rejette la promesse avec un message explicite : lis-le, corrige l’appel, puis relis
state(). - Toujours commencer par
await binksyGuide.ready().
04Référence de window.binksyGuide
await binksyGuide.ready();
binksyGuide.version; // "2.0.0"
binksyGuide.help(); // [{name, signature, description}]
await binksyGuide.state(); // {brand, sources, versions, palette, fonts, missingFonts, assets, options, style, credits, sections, files}
await binksyGuide.importBinksy(file, 'logokit' | 'multiformats'); // kind facultatif : détecté sinon
await binksyGuide.startBlank({ brand: 'Nom' }); // partir de zéro
await binksyGuide.addLogo(svg, { name: 'Horizontal', kind: 'horizontal'|'vertical'|'icon'|'wordmark'|'monogram'|'other' });
await binksyGuide.addColor({ hex: '#ff5500', name: 'Orange', role: 'accent' }); // rôles : primary, secondary, accent, text, background, surface, neutral, light, dark
await binksyGuide.removeColor('#ff5500');
await binksyGuide.addFont(file, { family: 'Inter', weight: 400, italic: false, licence: 'OFL', free: true });
await binksyGuide.addAsset(file, { category: 'mockup'|'social'|'print'|'web'|'other', title: 'Affiche', caption: '' }); // → {id}
await binksyGuide.removeAsset(id);
await binksyGuide.setOptions({ lang: 'fr'|'en', brand, title, intro, sections: { logo: true, formats: false, ... } });
await binksyGuide.setBrandText({ tagline, description, history, mission, vision, goals, values, audience, positioning, personality, tone, voice, voiceDont, keywords, activity });
binksyGuide.styles(); // [{id, name, description}]
await binksyGuide.setStyle('suisse');
await binksyGuide.setCredits({ name: 'Binks Design', email, instagram, website, phone, links: [{ label, url }], show: true });
await binksyGuide.exportSite({ download: true, base64: false }); // → {name, size, count, base64?}
await binksyGuide.reset();
| Méthode | Rôle |
|---|---|
ready() |
Attend que le générateur soit prêt. |
version / help() |
Version de l’API, liste des méthodes. |
state() |
État complet : marque, sources, versions du logo, palette, polices, missingFonts (polices de la hiérarchie sans fichier), assets, options, style, crédits, sections, fichiers. |
importBinksy(file, kind?) |
Importe un .binksy Binksy LogoKit (v2 ZIP ou ancien JSON V5) ou un .binksynext Binksy LogoNext (type détecté d’après le contenu : manifest + modules). Deux appels = fusion. |
startBlank({brand}) |
Part de zéro avec un nom de marque. |
addLogo(svg, {name, kind}) |
Ajoute un logo SVG fourni par l’utilisateur. |
addColor({hex, name, role}) / removeColor(hex) |
Ajoute / retire une couleur. |
addFont(file, {family, weight, italic, licence, free}) |
Ajoute une police (TTF, OTF, WOFF, WOFF2). free: true seulement si la licence est libre. Sert aussi à fournir une police listée dans missingFonts. |
addAsset(file, {category, title, caption}) / removeAsset(id) |
Ajoute / retire un asset supplémentaire. |
setOptions({lang, brand, title, intro, sections}) |
Langue du site, nom, titre, intro, sections affichées. |
setBrandText({...}) |
Textes de la plateforme de marque (voir § 7 bis). |
styles() / setStyle(id) |
Liste des 10 styles / choix du style. |
setCredits({...}) |
Crédits du graphiste. |
exportSite({download, base64}) |
Exporte le site en ZIP. |
reset() |
Remet le générateur à zéro. |
05Sources et fusion
Sources possibles, combinables :
.binksyLogoKit (v2 ZIP ou ancien JSON V5) : versions du logo, règles (zone de protection, tailles minimales), palette, dégradés, typographies (fichiers + licences), hiérarchie, mauvais usages, brief et textes des pages du guide (plateforme de marque), mockups..binksynextBinksy LogoNext (modules.multiformats, même format interne qu’un.binksyv2 ; type détecté d’après le contenu, l’extension ne départage que les cas ambigus) : versions, palette et rôles, QR code, formats coupés / actifs, fond.- Sans
.binksy(« Partir de zéro ») : nom de marque + logos SVG importés à la main + couleurs (HEX, nom, rôle) + polices (TTF / OTF / WOFF / WOFF2, avec licence libre ou non). - Assets supplémentaires créés ailleurs : images (PNG, JPG, WebP, SVG, GIF) ou fichiers (PDF, etc.) rangés dans une catégorie :
mockup(Applications),social(Réseaux sociaux),print(Imprimés),web,other(Autres). Titre et légende modifiables.
Site exporté : chaque déclinaison de couleur du logo en SVG, PNG (2000 px, transparent), PDF (vectoriel) et JPG (fond plein), rangée dans telechargements/logos/<version>/<svg|png|pdf|jpg>/ ; chaque fichier du site (formats, favicons, fichiers de palette, mockups, assets) a un aperçu, un bouton Copier (image ou code / texte) et un bouton Télécharger.
Fusion : LogoKit prioritaire (logo, typographies, guide, mockups) ; LogoNext ajoute ses formats et le QR code ; les ajouts manuels s’ajoutent à tout.
Démonstration (marque fictive AVORA) : demo/avora.binksy (LogoKit), demo/avora-ancien-logokit.binksy (ancien format LogoKit), demo/avora-logonext.binksynext (LogoNext). N’utilise la démo que pour tester ou si l’utilisateur la demande.
06Les 10 styles
| id | Nom | En bref |
|---|---|---|
editorial |
Éditorial | grands titres, filets fins, colonnes |
suisse |
Suisse | grille stricte, fer à gauche |
minimal |
Minimal | beaucoup de blanc, un seul accent |
noir |
Noir | fond sombre, contrastes forts |
magazine |
Magazine | images en grand, titres superposés |
brutal |
Brutaliste | bordures épaisses, ombres franches |
doux |
Doux | coins arrondis, teintes douces |
technique |
Technique | grille de plan, cotes, monospace |
aplat |
Aplat | couleur de marque en grands aplats |
classique |
Classique | luxe, serif |
binksyGuide.styles() fait foi pour les descriptions. Le style change la mise en page, pas l’identité.
07Sections du site
intro, marque, ton, logo, declinaisons, protection, tailles, interdits, couleurs, typographie, applications, assets, formats, ressources. Active ou désactive-les avec setOptions({ sections: { formats: false } }). La section des bons et mauvais usages a pour id interdits (pas usages).
7 bis. Plateforme de marque (setBrandText)
Textes affichés dans Introduction (signature tagline, présentation description, activité activity), La marque (marque : history histoire, mission, vision, goals objectifs, values valeurs, audience public, positioning positionnement) et Ton et voix (ton : personality personnalité, tone ton, keywords mots-clés, voice « on dit », voiceDont « on évite »). Panneau « Plateforme de marque » dans l’interface (data-agent="brand-text").
await binksyGuide.setBrandText({
tagline: 'Texte fourni par l’utilisateur',
values: 'Valeur 1\nValeur 2\nValeur 3', // un élément par ligne : values, goals, keywords, voice, voiceDont
vision: '', // chaîne vide = bloc masqué
mission: null, // null / undefined = texte du .binksy rétabli
});
- Les textes viennent du brief et des pages du guide d’un
.binksyLogoKit, ou de l’utilisateur. Chaque bloc n’apparaît que s’il contient du texte. - N’écris jamais un texte de marque de ton cru : ne passe à
setBrandTextque des textes fournis ou validés par l’utilisateur. Pour masquer un texte, passe''.
7 ter. Polices à importer (missingFonts)
Si la hiérarchie typographique utilise une police sans fichier, l’interface affiche « Polices à importer » (un bouton par famille) et state().missingFonts les liste. Demande le fichier à l’utilisateur puis appelle addFont(file, { family: 'Nom exact de la famille' }). Ne remplace jamais une police manquante par une autre.
08Exemple complet
Dans la page (JavaScript)
const g = window.binksyGuide;
await g.ready();
await g.reset();
// 1. Sources : la démo AVORA (LogoKit + LogoNext = fusion)
await g.importBinksy('demo/avora.binksy', 'logokit');
await g.importBinksy('demo/avora-logonext.binksynext', 'multiformats');
let s = await g.state();
console.assert(s.brand && s.versions.length > 0, 'aucune version de logo');
// 2. Un asset fourni par l’utilisateur (ici en data URL)
const { id } = await g.addAsset(posterDataUrl, { category: 'print', title: 'Affiche de lancement', caption: '' });
// 3. Réglages, style et crédits
await g.setOptions({ lang: 'fr', sections: { formats: true, ressources: true } });
await g.setStyle('suisse');
await g.setCredits({
name: 'Binks Design',
email: 'graphistedubinks@gmail.com',
instagram: 'https://www.instagram.com/graphiste.binks/',
show: true,
});
// 4. Vérifier
s = await g.state();
console.assert(s.style === 'suisse' || s.style?.id === 'suisse');
console.assert(s.assets.some((a) => a.id === id));
// 5. Exporter sans boîte de téléchargement
const out = await g.exportSite({ base64: true }); // {name, size, count, base64}
Depuis Playwright (Python)
import base64, pathlib
from playwright.sync_api import sync_playwright
poster = 'data:image/png;base64,' + base64.b64encode(pathlib.Path('affiche.png').read_bytes()).decode() # fichier de l’utilisateur
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
errors = []
page.on('pageerror', lambda e: errors.append(str(e)))
page.goto('http://127.0.0.1:8000/app.html')
page.wait_for_function('window.binksyGuide')
out = page.evaluate('''async (poster) => {
const g = window.binksyGuide;
await g.ready(); await g.reset();
await g.importBinksy('demo/avora.binksy', 'logokit');
await g.importBinksy('demo/avora-logonext.binksynext', 'multiformats');
await g.addAsset(poster, { category: 'print', title: 'Affiche de lancement', caption: '' });
await g.setStyle('suisse');
await g.setCredits({ name: 'Binks Design', email: 'graphistedubinks@gmail.com',
instagram: 'https://www.instagram.com/graphiste.binks/', show: true });
const state = await g.state();
const zip = await g.exportSite({ base64: true });
return { state, zip };
}''', poster)
pathlib.Path(out['zip']['name']).write_bytes(base64.b64decode(out['zip']['base64']))
print(out['zip']['count'], 'fichiers,', out['zip']['size'], 'octets', '| erreurs :', errors)
browser.close()
Partir de zéro
await g.reset();
await g.startBlank({ brand: 'Nom fourni par l’utilisateur' });
await g.addLogo(svgTexteFourni, { name: 'Horizontal', kind: 'horizontal' });
await g.addColor({ hex: '#1d1d1b', name: 'Noir', role: 'primary' });
await g.addFont(fontBytes, { family: 'Inter', weight: 400, italic: false, licence: 'OFL', free: true });
09Repères data-agent
| Attribut | Commande |
|---|---|
import-logokit |
Importer un .binksy LogoKit |
import-multiformats |
Importer un .binksynext LogoNext |
start-blank |
Partir de zéro |
add-logo |
Ajouter un logo SVG |
add-color |
Ajouter une couleur |
add-font |
Ajouter une police |
add-asset |
Ajouter un asset supplémentaire |
brand-text |
Panneau « Plateforme de marque » (textes du site) |
style-<id> |
Choisir un style (style-suisse, style-noir…) |
export |
Exporter le site |
Exemple Playwright : page.click('[data-agent="style-suisse"]'), page.set_input_files('[data-agent="import-logokit"] input[type=file], input[data-agent="import-logokit"]', 'avora.binksy') (selon que l’attribut est sur le bouton ou sur le champ fichier — vérifie dans le DOM).
10Vérifications avant de rendre le travail
state().brandest le nom fourni par l’utilisateur (aucune faute, rien d’inventé).state().sourcesliste les sources attendues ;versionscontient chaque version du logo fournie.palette: chaque couleur a un nom et un rôle corrects.fonts:free: trueseulement pour une licence réellement libre (OFL, Apache…). Une police commerciale est affichée dans le site mais jamais téléchargeable.assets: bonne catégorie, titre et légende relus.options: langue, titre, intro (validés par l’utilisateur), sections. Textes de marque : uniquement ceux du.binksyou de l’utilisateur ;missingFontsvide (ou signalé à l’utilisateur).styleetcreditscomme demandé.exportSite({ base64: true })renvoiecount > 0etsize > 0. Décompresse le ZIP, ouvreindex.html(http etfile://) : aucune erreur console, logos visibles, chaque version de couleur présente danstelechargements/logos/<version>/{svg,png,pdf,jpg}/.- Capture d’écran de l’aperçu ou du site exporté, en bureau et en mobile.
11Limites et erreurs
- Formats non produits ici : tickets thermiques, étiquettes Zebra, vidéo, EPS, jeux complets d’icônes Android / macOS → ils restent dans Binksy LogoNext.
- CMJN : conversion simple, sans profil ICC.
- Polices non libres : affichées (intégrées) mais pas téléchargeables.
fetchimpossible enfile://: passe les fichiers en octets, data URL ou base64.- Style inconnu :
setStylerefuse un id hors destyles(). - Catégorie d’asset inconnue : seules
mockup,social,print,web,othersont acceptées. - Fichier qui n’est pas un
.binksy: l’import échoue ; demande le bon fichier à l’utilisateur au lieu de reconstruire la marque. - Téléchargement bloqué (navigateur sans interface) : utilise
exportSite({ base64: true }).
Si le comportement réel diffère de ce document, décris l’écart, fie-toi à binksyGuide.help() et à state(), et adapte-toi sans contourner les protections.
12Logique à suivre pour chaque tâche
- Comprendre la demande et ce que l’utilisateur a déjà fourni (ne redemande jamais une information donnée).
await binksyGuide.ready()puisstate().- Poser en un seul message les questions vraiment nécessaires (fichiers manquants, style, crédits) ; ne jamais combler un manque en inventant.
- Agir par l’API (ou les repères
data-agent). - Vérifier
state(), puis le rendu (aperçu, export). - Exporter et rendre le ZIP avec un résumé : sources, style, sections, nombre de fichiers.
7 ter. Sections : ordre, textes, blocs et sections personnalisées
Chaque section (intégrée, reprise d’une page du guide LogoKit ou créée à la main) peut être renommée, recevoir un chapeau, être masquée, déplacée et enrichie de blocs. Les pages LogoKit sans équivalent (photographie, iconographie, réseaux sociaux, contact, construction, page vierge…) arrivent comme sections .binksy.
binksyGuide.sections(); // [{id, title, lead, enabled, builtin, from, blocks:[…]}]
await binksyGuide.setSection('logo', { title: 'Notre logo', lead: '…', enabled: true, index: 2 });
await binksyGuide.setSection('logo', { reset: true }); // textes et blocs d’origine
const s = await binksyGuide.addSection({ title: 'Motion', lead: '…', after: 'logo', blocks: [
{ type: 'video', file: videoFile, caption: 'Animation' },
{ type: 'embed', url: 'https://vimeo.com/…', caption: 'Making-of' },
{ type: 'text', title: 'Durée', text: '2 secondes, jamais plus.' }
]});
await binksyGuide.addBlock('couleurs', { type: 'image', file: imageFile, caption: 'Ambiance' });
await binksyGuide.updateBlock(s.id, blockId, { caption: '…' });
await binksyGuide.removeBlock(s.id, blockId);
await binksyGuide.moveSection(s.id, 0);
await binksyGuide.removeSection(s.id); // sections personnalisées seulement
- Types de blocs :
text(intertitre + texte, paragraphes séparés par une ligne vide),image(PNG, JPG, WebP, GIF, SVG, AVIF),video(MP4, WebM, MOV),embed(lien YouTube ou Vimeo, lu en ligne). - Images et vidéos sont copiées octet pour octet : téléchargement en résolution d’origine dans
telechargements/sections/<section>/. Les mises en situation et assets ajoutés restent aussi à leur résolution d’origine. - Une section personnalisée sans chapeau ni bloc n’apparaît pas. Même règle : n’invente aucun texte.
This document is for AI agents (Claude Code, Codex, or any agent driving a browser through Playwright / CDP, or running JavaScript in the page). It explains how to use the brand guide generator (app.html): import one or two .binksy files, start from scratch, add assets, pick a style, set the designer credits and export the website, through the public window.binksyGuide API.
It lives in two places, always identical: AGENTS.md (Markdown, French then English) and the agent/index.html page. Short summary: llms.txt.
Entry points discoverable without JavaScript: index.html and docs.html declare <link rel="alternate" type="text/markdown" href="AGENTS.md">, <link rel="help" href="agent/"> and <link rel="alternate" type="text/plain" href="llms.txt">, and carry an HTML comment and a <noscript> pointing here. robots.txt allows everything and cites llms.txt and AGENTS.md.
01Golden rule
The generator lays out what the designer provides. It is not a logo or brand-copy generator.
- Never invent a logo, symbol, icon, brand colour, typeface or brand text (name, tagline, description, values). What the user provides (
.binksyfiles, SVGs, colours, fonts, copy, assets) is the source of truth. - Do not redraw a provided SVG or alter its geometry. Do not replace a missing file with a “close enough” one.
- A title or intro you propose is a suggestion: get it approved before saving it with
setOptions. - No API key, no online service. The generator embeds no AI; you decide and verify. Never ask the user for a key.
- Everything is local: file reading, processing and ZIP creation happen in the browser. Nothing is sent to a server. Settings are remembered in browser storage.
After every action: re-read await binksyGuide.state(). A call or a click is not proof of success.
02Getting started
Run the generator
The deployed site (dist/ folder, produced by python3 build.py) contains: index.html (home), app.html (the generator), docs.html (documentation), agent/index.html (this page), AGENTS.md, llms.txt, robots.txt, demo/ (demo files) and assets/.
cd dist && python3 -m http.server 8000
# then open http://127.0.0.1:8000/app.html
- http:// preferred: demo files and relative URLs (
demo/avora.binksy) are loaded withfetch. - file:// also works (open
app.htmldirectly), but browsers blockfetchonfile://: pass files asFile/Blob,ArrayBuffer,Uint8Array, data URL or base64, not as URLs. - Any static host works (Netlify, Vercel, GitHub Pages…).
- Use a dedicated browser profile for tests: settings (style, credits…) are remembered per origin.
Two ways to drive it
- JavaScript API (recommended):
window.binksyGuide, inapp.html. - Clicks: key controls carry a stable
data-agentattribute (see § 9).
await binksyGuide.ready();
binksyGuide.version; // "2.0.0"
binksyGuide.help(); // [{name, signature, description}]
await binksyGuide.state();
03API conventions
- Every method is async (except
version,help()andstyles()) and returns plain JSON. - Accepted files:
File/Blob,ArrayBuffer,Uint8Array, data URL, base64, relative or absolute URL (loaded withfetch) and, for SVGs, the SVG text itself. - An error rejects the promise with an explicit message: read it, fix the call, then re-read
state(). - Always start with
await binksyGuide.ready().
04window.binksyGuide reference
await binksyGuide.ready();
binksyGuide.version; // "2.0.0"
binksyGuide.help(); // [{name, signature, description}]
await binksyGuide.state(); // {brand, sources, versions, palette, fonts, missingFonts, assets, options, style, credits, sections, files}
await binksyGuide.importBinksy(file, 'logokit' | 'multiformats'); // kind optional: detected otherwise
await binksyGuide.startBlank({ brand: 'Name' }); // start from scratch
await binksyGuide.addLogo(svg, { name: 'Horizontal', kind: 'horizontal'|'vertical'|'icon'|'wordmark'|'monogram'|'other' });
await binksyGuide.addColor({ hex: '#ff5500', name: 'Orange', role: 'accent' }); // roles: primary, secondary, accent, text, background, surface, neutral, light, dark
await binksyGuide.removeColor('#ff5500');
await binksyGuide.addFont(file, { family: 'Inter', weight: 400, italic: false, licence: 'OFL', free: true });
await binksyGuide.addAsset(file, { category: 'mockup'|'social'|'print'|'web'|'other', title: 'Poster', caption: '' }); // → {id}
await binksyGuide.removeAsset(id);
await binksyGuide.setOptions({ lang: 'fr'|'en', brand, title, intro, sections: { logo: true, formats: false, ... } });
await binksyGuide.setBrandText({ tagline, description, history, mission, vision, goals, values, audience, positioning, personality, tone, voice, voiceDont, keywords, activity });
binksyGuide.styles(); // [{id, name, description}]
await binksyGuide.setStyle('suisse');
await binksyGuide.setCredits({ name: 'Binks Design', email, instagram, website, phone, links: [{ label, url }], show: true });
await binksyGuide.exportSite({ download: true, base64: false }); // → {name, size, count, base64?}
await binksyGuide.reset();
| Method | Purpose |
|---|---|
ready() |
Waits until the generator is ready. |
version / help() |
API version, list of methods. |
state() |
Full state: brand, sources, logo versions, palette, fonts, missingFonts (hierarchy fonts with no file), assets, options, style, credits, sections, files. |
importBinksy(file, kind?) |
Imports a LogoKit .binksy (v2 ZIP or legacy JSON V5) or a Binksy LogoNext .binksynext (type detected from the content: manifest + modules). Two calls = merge. |
startBlank({brand}) |
Starts from scratch with a brand name. |
addLogo(svg, {name, kind}) |
Adds a logo SVG provided by the user. |
addColor({hex, name, role}) / removeColor(hex) |
Adds / removes a colour. |
addFont(file, {family, weight, italic, licence, free}) |
Adds a font (TTF, OTF, WOFF, WOFF2). free: true only for a genuinely free licence. Also fills a font listed in missingFonts. |
addAsset(file, {category, title, caption}) / removeAsset(id) |
Adds / removes an extra asset. |
setOptions({lang, brand, title, intro, sections}) |
Site language, name, title, intro, visible sections. |
setBrandText({...}) |
Brand platform copy (see § 7 bis). |
styles() / setStyle(id) |
List of the 10 styles / pick one. |
setCredits({...}) |
Designer credits. |
exportSite({download, base64}) |
Exports the website as a ZIP. |
reset() |
Resets the generator. |
05Sources and merging
Possible sources, combinable:
- LogoKit
.binksy(v2 ZIP or legacy JSON V5): logo versions, rules (clear space, minimum sizes), palette, gradients, typefaces (files + licences), hierarchy, misuses, brief and guide-page copy (brand platform), mockups. - Binksy LogoNext
.binksynext(modules.multiformats, same internal format as.binksyv2): versions, palette and roles, QR code, cut / active formats, background. - No
.binksy(“Start from scratch”): brand name + hand-imported SVG logos + colours (HEX, name, role) + fonts (TTF / OTF / WOFF / WOFF2, free licence or not). - Extra assets made elsewhere: images (PNG, JPG, WebP, SVG, GIF) or files (PDF, etc.) filed in a category:
mockup(Applications),social(Social media),print(Print),web,other(Other). Editable title and caption.
Exported site: every logo colour version in SVG, PNG (2000 px, transparent), PDF (vector) and JPG (solid background), sorted in telechargements/logos/<version>/<svg|png|pdf|jpg>/; every file in the site (formats, favicons, palette files, mockups, assets) has a preview, a Copy button (image or code / text) and a Download button.
Merge: LogoKit wins (logo, typefaces, guide, mockups); LogoNext adds its formats and the QR code; manual additions are added on top of everything.
Demo (fictional brand AVORA): demo/avora.binksy (LogoKit), demo/avora-ancien-logokit.binksy (legacy Binksy LogoKit format), demo/avora-logonext.binksynext (LogoNext). Use the demo only for testing or when the user asks for it.
06The 10 styles
| id | Name | In short |
|---|---|---|
editorial |
Éditorial (Editorial) | big headlines, hairlines, columns |
suisse |
Suisse (Swiss) | strict grid, flush left |
minimal |
Minimal | lots of white, one accent |
noir |
Noir (Dark) | dark background, strong contrast |
magazine |
Magazine | large images, overlapping titles |
brutal |
Brutaliste (Brutalist) | thick borders, hard shadows |
doux |
Doux (Soft) | rounded corners, soft tints |
technique |
Technique (Technical) | blueprint grid, dimensions, monospace |
aplat |
Aplat (Flat colour) | brand colour in large flat areas |
classique |
Classique (Classic) | luxury, serif |
binksyGuide.styles() is authoritative for descriptions. A style changes the layout, not the identity.
07Site sections
intro, marque (the brand), ton (tone of voice), logo, declinaisons (colour variants), protection (clear space), tailles (minimum sizes), interdits (do’s and don’ts), couleurs (colours), typographie, applications, assets, formats, ressources (downloads). Toggle them with setOptions({ sections: { formats: false } }). The do’s and don’ts section id is interdits (not usages).
7 bis. Brand platform (setBrandText)
Copy shown in Introduction (tagline, description, activity), The brand (marque: history, mission, vision, goals, values, audience, positioning) and Tone of voice (ton: personality, tone, keywords, voice “we say”, voiceDont “we avoid”). “Plateforme de marque” panel in the UI (data-agent="brand-text").
await binksyGuide.setBrandText({
tagline: 'Text provided by the user',
values: 'Value 1\nValue 2\nValue 3', // one item per line: values, goals, keywords, voice, voiceDont
vision: '', // empty string = block hidden
mission: null, // null / undefined = .binksy text restored
});
- Copy comes from the brief and guide pages of a LogoKit
.binksy, or from the user. Each block only appears if it has text. - Never write brand copy yourself: only pass text the user provided or approved to
setBrandText. To hide a text, pass''.
7 ter. Fonts to import (missingFonts)
If the type hierarchy uses a font with no file, the UI shows “Polices à importer” (one button per family) and state().missingFonts lists them. Ask the user for the file, then call addFont(file, { family: 'Exact family name' }). Never substitute another font.
08Complete example
In the page (JavaScript)
const g = window.binksyGuide;
await g.ready();
await g.reset();
// 1. Sources: the AVORA demo (LogoKit + LogoNext = merge)
await g.importBinksy('demo/avora.binksy', 'logokit');
await g.importBinksy('demo/avora-logonext.binksynext', 'multiformats');
let s = await g.state();
console.assert(s.brand && s.versions.length > 0, 'no logo version');
// 2. An asset provided by the user (here as a data URL)
const { id } = await g.addAsset(posterDataUrl, { category: 'print', title: 'Launch poster', caption: '' });
// 3. Settings, style and credits
await g.setOptions({ lang: 'en', sections: { formats: true, ressources: true } });
await g.setStyle('suisse');
await g.setCredits({
name: 'Binks Design',
email: 'graphistedubinks@gmail.com',
instagram: 'https://www.instagram.com/graphiste.binks/',
show: true,
});
// 4. Verify
s = await g.state();
console.assert(s.style === 'suisse' || s.style?.id === 'suisse');
console.assert(s.assets.some((a) => a.id === id));
// 5. Export without a download dialog
const out = await g.exportSite({ base64: true }); // {name, size, count, base64}
From Playwright (Python)
import base64, pathlib
from playwright.sync_api import sync_playwright
poster = 'data:image/png;base64,' + base64.b64encode(pathlib.Path('poster.png').read_bytes()).decode() # the user's file
with sync_playwright() as p:
browser = p.chromium.launch()
page = browser.new_page()
errors = []
page.on('pageerror', lambda e: errors.append(str(e)))
page.goto('http://127.0.0.1:8000/app.html')
page.wait_for_function('window.binksyGuide')
out = page.evaluate('''async (poster) => {
const g = window.binksyGuide;
await g.ready(); await g.reset();
await g.importBinksy('demo/avora.binksy', 'logokit');
await g.importBinksy('demo/avora-logonext.binksynext', 'multiformats');
await g.addAsset(poster, { category: 'print', title: 'Launch poster', caption: '' });
await g.setStyle('suisse');
await g.setCredits({ name: 'Binks Design', email: 'graphistedubinks@gmail.com',
instagram: 'https://www.instagram.com/graphiste.binks/', show: true });
const state = await g.state();
const zip = await g.exportSite({ base64: true });
return { state, zip };
}''', poster)
pathlib.Path(out['zip']['name']).write_bytes(base64.b64decode(out['zip']['base64']))
print(out['zip']['count'], 'files,', out['zip']['size'], 'bytes', '| errors:', errors)
browser.close()
Starting from scratch
await g.reset();
await g.startBlank({ brand: 'Name given by the user' });
await g.addLogo(providedSvgText, { name: 'Horizontal', kind: 'horizontal' });
await g.addColor({ hex: '#1d1d1b', name: 'Black', role: 'primary' });
await g.addFont(fontBytes, { family: 'Inter', weight: 400, italic: false, licence: 'OFL', free: true });
09data-agent hooks
| Attribute | Control |
|---|---|
import-logokit |
Import a LogoKit .binksy |
import-multiformats |
Import a LogoNext .binksynext |
start-blank |
Start from scratch |
add-logo |
Add an SVG logo |
add-color |
Add a colour |
add-font |
Add a font |
add-asset |
Add an extra asset |
brand-text |
“Plateforme de marque” panel (site copy) |
style-<id> |
Pick a style (style-suisse, style-noir…) |
export |
Export the website |
Playwright example: page.click('[data-agent="style-suisse"]'), page.set_input_files('[data-agent="import-logokit"] input[type=file], input[data-agent="import-logokit"]', 'avora.binksy') (depending on whether the attribute sits on the button or on the file input — check the DOM).
10Checks before handing back
state().brandis the name the user gave (no typo, nothing invented).state().sourceslists the expected sources;versionsholds every logo version provided.palette: every colour has a correct name and role.fonts:free: trueonly for a genuinely free licence (OFL, Apache…). A commercial font is displayed on the site but never downloadable.assets: right category, title and caption proof-read.options: language, title, intro (approved by the user), sections. Brand copy: only from the.binksyor the user;missingFontsempty (or reported to the user).styleandcreditsas requested.exportSite({ base64: true })returnscount > 0andsize > 0. Unzip, openindex.html(http andfile://): no console error, logos visible, every colour version present intelechargements/logos/<version>/{svg,png,pdf,jpg}/.- Screenshot of the preview or of the exported site, desktop and mobile.
11Limits and errors
- Formats not produced here: thermal receipts, Zebra labels, video, EPS, full Android / macOS icon sets → they stay in Binksy LogoNext.
- CMYK: simple conversion, no ICC profile.
- Non-free fonts: displayed (embedded) but not downloadable.
fetchimpossible onfile://: pass files as bytes, data URL or base64.- Unknown style:
setStylerejects an id not listed bystyles(). - Unknown asset category: only
mockup,social,print,web,otherare accepted. - File that is not a
.binksy: the import fails; ask the user for the right file instead of rebuilding the brand. - Download blocked (headless browser): use
exportSite({ base64: true }).
If the actual behaviour differs from this document, describe the gap, trust binksyGuide.help() and state(), and adapt without bypassing safeguards.
12Logic for every task
- Understand the request and what the user already provided (never ask again for information already given).
await binksyGuide.ready()thenstate().- Ask, in a single message, only the questions that matter (missing files, style, credits); never fill a gap by inventing.
- Act through the API (or the
data-agenthooks). - Check
state(), then the rendering (preview, export). - Export and hand back the ZIP with a summary: sources, style, sections, file count.
7 ter. Sections: order, copy, blocks and custom sections
Every section (built-in, imported from a LogoKit guide page, or created by hand) can be renamed, given a lead, hidden, moved and extended with blocks. LogoKit pages with no built-in match (photography, icons, social, contact, construction, blank page…) arrive as .binksy sections.
binksyGuide.sections();
await binksyGuide.setSection('logo', { title, lead, enabled, index, reset });
await binksyGuide.addSection({ title, lead, after, blocks: [{ type: 'text' | 'image' | 'video' | 'embed', title, text, file, url, caption }] });
await binksyGuide.addBlock(sectionId, { type, file, caption, index });
await binksyGuide.updateBlock(sectionId, blockId, { ... });
await binksyGuide.removeBlock(sectionId, blockId);
await binksyGuide.moveSection(sectionId, index);
await binksyGuide.removeSection(sectionId); // custom sections only
- Images and videos are copied byte for byte and downloadable at their original resolution from
telechargements/sections/<section>/. - A custom section with neither lead nor block is not shown. Never invent copy.