diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index d41b519..c239f04 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -1,8 +1,8 @@ { "name": "brand-studio", "owner": { - "name": "REPLACE-WITH-YOUR-NAME", - "url": "https://github.com/REPLACE-WITH-YOUR-GITHUB-USER" + "name": "Shadowtor", + "url": "https://github.com/shadowtor" }, "metadata": { "description": "Brand identity and logo design skill: brief to sketches to full brand kit.", diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json index 672a51d..882fc65 100644 --- a/.claude-plugin/plugin.json +++ b/.claude-plugin/plugin.json @@ -3,11 +3,11 @@ "description": "Brand identity and logo design from a business brief: research, three greyscale sketches for approval, independent sub-agent review, then colour, type, lockups and a full kit (logos in colour/dark/black/white/greyscale as SVG/PNG/PDF/JPG, tested favicons, social banners, stationery, merch mockups chosen for the business, tokens, brand guidelines PDF).", "version": "1.0.0", "author": { - "name": "REPLACE-WITH-YOUR-NAME", - "url": "https://github.com/REPLACE-WITH-YOUR-GITHUB-USER" + "name": "Shadowtor", + "url": "https://github.com/shadowtor" }, - "homepage": "https://github.com/REPLACE-WITH-YOUR-GITHUB-USER/brand-studio", - "repository": "https://github.com/REPLACE-WITH-YOUR-GITHUB-USER/brand-studio", + "homepage": "https://github.com/shadowtor/BrandDesign", + "repository": "https://github.com/shadowtor/BrandDesign", "license": "MIT", "keywords": ["logo", "branding", "brand-identity", "svg", "favicon", "brand-guidelines", "mockups", "design"] } diff --git a/.gitattributes b/.gitattributes index dfe0770..544f341 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,2 +1,12 @@ # Auto detect text files and perform LF normalization * text=auto +*.svg text eol=lf +*.py text eol=lf +*.md text eol=lf +*.json text eol=lf +*.png binary +*.jpg binary +*.jpeg binary +*.pdf binary +*.ico binary +*.gz binary diff --git a/.gitignore b/.gitignore index 2fd15c8..cabc6d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,37 @@ +# OS / editor .DS_Store Thumbs.db +desktop.ini +.vscode/ +.idea/ + +# Python __pycache__/ *.pyc +.venv/ +venv/ + +# build output dist/ +*.zip +*.log + +# working folders and full kits: examples/ holds the curated previews instead +brand-studio-work/ *-workspace/ +kit/ +deliver/ preview*.html -# working files and downloaded third-party mockup PSDs must never be committed -brand-studio-work/ + +# third-party mockup PSDs are downloaded to ~/.cache/brand-studio and must never be committed *.psd *.psb +*.ai +*.eps mockups-cache/ +.cache/ + +# secrets +.env +.env.* +*.pem diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..668df6e --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,20 @@ +# Contributing + +Thanks for helping. The most useful contributions: + +- **Merch items**: add a row to `ITEMS` in `skills/brand-studio/scripts/merch_catalog.py` (label, mockups-design.com page slug or `None`, + logo form, scale, cylinder). If there is no free PSD, add an illustration function to `merch.py`. If a PSD needs placement tweaks, + add an entry to `ADJUST` after comparing the result with the mockup's own preview image. +- **Business types**: extend `BUSINESS_TYPES` / `ALIASES` with what that kind of business really makes (not a generic mug and shirt). +- **Reference data**: sector palettes and logos you have the right to redistribute (see `references/library-guide.md`). +- **Evals**: prompts and expected behaviour in `skills/brand-studio/evals/`. +- **Bug reports**: include your OS, `python skills/brand-studio/scripts/check_setup.py` output and the failing command. + +## Before opening a pull request +1. `python tools/smoke_test.py` passes (needs a Chromium browser and internet). +2. Any new script has a docstring with usage, runs with `--help`, and keeps working on Windows, macOS and Linux (no shell-specific code). +3. New third-party data or fonts: add them to `THIRD_PARTY_NOTICES.md` with their licence. Never commit PSD/PSB files, client work or + anything you do not have the right to publish. +4. Keep claims honest: tests say what they do not cover; heuristics are labelled as heuristics. + +By contributing you agree your work is released under the repository's MIT licence. diff --git a/README.md b/README.md index c56037a..2584c9b 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,206 @@ -# BrandDesign +# brand-studio +[![Smoke test](https://github.com/shadowtor/BrandDesign/actions/workflows/test.yml/badge.svg)](https://github.com/shadowtor/BrandDesign/actions/workflows/test.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) + +**A brand identity and logo design skill for AI coding agents** (Claude Code, Codex CLI, Gemini CLI and anything that reads +Agent Skills folders: a directory with a `SKILL.md`). Give it a business brief; it researches the category, shows **three greyscale +logo sketches** for you to choose from, has an **independent sub-agent review them**, and only then builds the full brand kit. + +![Three example brands built entirely by the skill: Kiln, Rookery and Marigold Press](examples/overview.png) + +Kiln (coffee roastery), Rookery (gaming community) and Marigold Press (illustrator): fictional briefs, every file in +[`examples/`](examples) was produced by the skill. Merch is chosen for each business, not a generic mug and shirt. + +**Contents:** [What you get](#what-you-get) · [Install](#install) · [Use](#use) · [Merch by business type](#merch-is-chosen-for-the-business) · +[Examples](#examples) · [Limits](#what-it-will-not-do-for-you) · [Develop](#develop) · [Credits](#credits-and-attribution) + +## What you get + +| | | +|---|---| +| **Logos** | square, horizontal, vertical, symbol, wordmark × colour (light), colour (dark), black, white, greyscale × **SVG / PNG / JPG / PDF** | +| **Favicons** | favicon.svg/.ico, 16–48 px, apple-touch, 192/512, maskable, web manifest, head snippet, plus a **test sheet and report** (ICO structure, sizes, manifest, safe zone, 16 px legibility on light and dark tabs) | +| **Social** | avatars (3 backgrounds × 3 sizes) and banners for LinkedIn, X, Facebook, YouTube, link previews, Instagram | +| **Stationery** | A4 letterhead (sample + blank), header and footer strips, business card print file with bleed, email signature | +| **Merch mockups** | items chosen for the business type (a coffee bean bag and travel mug for a roaster; jersey, mouse mat and hoodie for a gaming community; USB stick, cables and lanyards for tech…), **photographic** via free PSD mockups (opt-in) or labelled illustrations | +| **Guidelines** | a PDF built from the real files: idea, logo family, clear space, versions, colour (HEX/RGB/HSL/OKLCH, contrast), type, misuse (including ones only this mark can suffer), favicon test, social, stationery, merch | +| **Tokens** | CSS, SCSS, Tailwind, DTCG JSON, GIMP palette, swatches; font embed notes | + +**How it works:** intake → category research (bundled 1,400-logo and brand-palette libraries + live Fontsource/colour APIs) → +8–12 one-line concepts → **three different sketches** (black SVG, audited at 16 px, one colour, reversed) → independent review → +**you pick** → refine, colour (WCAG-audited), type (real outlined fonts), lockups → `build_kit.py` → kit review → handover with the +open items stated plainly (trademark search, print proofing, real-browser favicon check). + +## Install + +You need Python 3.9+, a Chromium-based browser (Chrome, Edge, Brave, Chromium) and internet access for fonts. [`uv`](https://docs.astral.sh/uv/) +is recommended (it installs Pillow, pypdf, fonttools, uharfbuzz and psd-tools on first use). + +### A. Claude Code plugin marketplace + +```text +/plugin marketplace add shadowtor/BrandDesign +/plugin install brand-studio@brand-studio +``` + +### B. Installer script (Claude Code, Codex CLI, Gemini CLI, any agent) + +```bash +git clone https://github.com/shadowtor/BrandDesign.git +cd BrandDesign +python tools/install.py --claude --codex # or --gemini, --project, --dest , --link (symlink for development) +python skills/brand-studio/scripts/check_setup.py # verifies Python, uv, browser, network +``` + +Manual alternative: copy the `skills/brand-studio` folder to `~/.claude/skills/brand-studio` (Claude Code), `~/.codex/skills/brand-studio` +(Codex), `~/.gemini/skills/brand-studio` (Gemini) or your agent's skills folder. Start a **new session** afterwards. + +### C. Let your AI agent install it (copy-paste) + +Paste this into your agent. It follows [`docs/INSTALL-FOR-AGENTS.md`](docs/INSTALL-FOR-AGENTS.md), which it can also read from the repo. + +```text +Install the "brand-studio" Agent Skill for me. + +1. Clone https://github.com/shadowtor/BrandDesign (or git pull if I already have it) and read + docs/INSTALL-FOR-AGENTS.md in it. Follow that file exactly. +2. Install it for the agent I am using right now (python tools/install.py --claude, --codex or --gemini; use --dest for others). + Only copy the skills/brand-studio folder; do not change anything inside it and do not run any other script from it. +3. Run: python skills/brand-studio/scripts/check_setup.py. If it reports a FAIL, show me the line and its fix and stop. If it reports + WARN lines (for example uv missing), explain what is limited and offer the fix. +4. Tell me where it was installed, the check result, and that I must start a new session. Do not commit, push or download anything + else. Then give me one example request I can try. +``` + +### D. Upload as a skill file + +`python tools/package_skill.py` writes `dist/brand-studio.zip` (and a `-lite` zip without the reference SVGs) for UIs that take a skill upload. +Note: the skill runs scripts and a browser; use an environment that allows both (a code-capable agent, not plain chat). + +## Use + +Just ask: + +> Design a brand identity for **Rookery**, a competitive-but-welcoming gaming community. Three logo sketches first. + +> Here is our logo (logo.svg): what is wrong with it, and how would you refresh it without losing recognition? + +> Turn this symbol into a favicon set and social avatars, and test the favicon at 16 px. + +It asks a few questions (or states assumptions), shows the concept sheet and **stops**. Pick a direction and say go; it builds the kit +into the folder you name (on Windows keep the work folder on a short path). + +Build a kit by hand from approved artwork: + +```bash +cp skills/brand-studio/templates/brand.example.json brand.json # edit names, colours, logo file paths, business_type +python skills/brand-studio/scripts/build_kit.py brand.json --out deliver # everything except photo mockups +python skills/brand-studio/scripts/build_kit.py brand.json --out deliver --photo-mockups # + photographic merch previews +``` + +Photographic merch previews are opt-in: the first run downloads free PSDs from mockups-design.com into `~/.cache/brand-studio` +(roughly 5 minutes; see [credits](#credits-and-attribution)). + +## Merch is chosen for the business + +`scripts/merch_catalog.py` maps a `business_type` to the items that kind of business really makes (override with an explicit list). + +| Business | Items | +|---|---| +| Coffee | bean bag, travel mug, takeaway cup, mug, apron, tote, tee, cap | +| Gaming / esports | team jersey, mouse mat, hoodie, tee, cap, sticker sheet, lanyard, keyring | +| Tech / SaaS | business card, USB stick, charging cable, lanyard, phone case, laptop sleeve, tee, sticker sheet | +| Artist / illustrator | sticker sheet, business card, tee, tote, notebook, poster, pin badge | +| + fashion, fitness, finance, services, health, beauty, events, music, education, community, retail, trades, kids, pets, bakery, bar | see [`merch-catalogue.md`](skills/brand-studio/references/merch-catalogue.md) | + +Each item uses a photographic mockup when a free PSD exists, otherwise a drawn illustration, and every file is labelled +*photographic mockup* or *illustration* in the guidelines. Nothing is shown that was not actually made. + +## Examples + +Fictional brands, built end to end. Each folder has the `brand.json`, the final SVG artwork, every SVG logo version, and previews of +the guidelines PDF, favicon test, social banner, letterhead and merch mockups. + +| Example | Business | Mark | Merch set | +|---|---|---|---| +| [Kiln](examples/kiln) | specialty coffee roastery | arched kiln mouth with an ember | bean bag, takeaway cup, mug, travel mug, apron, tote | +| [Rookery](examples/rookery) | competitive gaming community | pixel-block rook with one lit window | jersey, mouse mat, hoodie, tee, cap, sticker sheet | +| [Marigold Press](examples/marigold) | independent illustrator | eight-petal marigold seen from above | sticker sheet, business card, tee, tote, notebook, poster | + +## What it will not do for you + +- **No trademark clearance.** Search before launch (IP Australia, WIPO Global Brand Database, EUIPO TMview, USPTO). The skill says so every time. +- **CMYK is indicative, Pantone is blank.** Print needs the printer's profile and a proof. +- **The favicon test is a simulated tab.** Open the live site in a real browser once. +- **Mockups are previews**, not publishable artwork; third-party PSDs are never redistributed. +- It cannot guarantee a mark is unique. The reference libraries are for study; never copy or trace them. + +## Develop + +```bash +python tools/smoke_test.py # runs the scripts end to end (needs a Chromium browser + internet) +python tools/package_skill.py # dist/brand-studio.zip +python tools/install.py --link # symlink the skill into your agent folders and edit in place +``` + +Layout: [`docs/architecture.md`](docs/architecture.md). Contributions welcome: see [`CONTRIBUTING.md`](CONTRIBUTING.md) (new merch items, +business types, sector reference data, evals). + +## Licence + +MIT, see [LICENSE](LICENSE). Incorporates MIT work (see credits). The reference logo and palette libraries, fonts and mockup PSDs are +third-party material with their own terms: [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). + +--- + +## Credits and attribution + +### Built on +- **[kaankiziltug/logo-design-skill](https://github.com/kaankiziltug/logo-design-skill)** (MIT): the design process, principles, SVG + construction and testing tooling, concept sheet, 1,400-logo reference library and its example boards. +- **[fatihaydost/brand-identity-skill](https://github.com/fatihaydost/brand-identity-skill)** (MIT): the one-mechanism idea, AI-defaults + reflex test, OKLCH palette build and WCAG/colour-blindness audit, honest print guidance, kit and critique structure, token export. + +### Mockup sources (used for previews only) + +The photographic previews in `examples/` were made with free PSD mockups from **[mockups-design.com](https://mockups-design.com/)** +(licence: free for any purpose including commercial use, no attribution required, but the PSD files themselves may not be +redistributed; flattened finished images may be shared: [licence](https://mockups-design.com/license/)). We credit them anyway. The PSDs +are **not** in this repository: the skill downloads them on demand into `~/.cache/brand-studio/mockups` when you run `--photo-mockups`. + +| Mockup | Pack | Used in | +|---|---|---| +| [Coffee cup](https://mockups-design.com/paper-coffee-cup-mockup/) | MD049 Free Coffee Paper Cup Mockup | Kiln | +| [Food pouch (coffee bean bag stand-in)](https://mockups-design.com/free-food-pouch-mockup/) | MD474 Free Food Bag Mockup | Kiln | +| [Oval mug](https://mockups-design.com/round-bellied-mug-mockup/) | MD1258 Oval Mug Mockup | Kiln | +| [Apron](https://mockups-design.com/stitched-bib-apron-mockup/) | MD1260 Apron Mockup | Kiln | +| [Hanging tote bag](https://mockups-design.com/hanging-tote-bag-mockup/) | MDP071 Hanging Tote Bag Mockup | Kiln, Marigold Press | +| [Large mouse pad](https://mockups-design.com/oversized-mouse-pad-mockup/) | MD1237 Large Mousepad Mockup | Rookery | +| [Hoodie](https://mockups-design.com/free-hoodie-mockup/) | MDP059 Hoodie Mockup | Rookery | +| [T-shirt](https://mockups-design.com/mens-t-shirt-mockup/) | MD815 T-Shirt Mockup | Rookery, Marigold Press | +| [Baseball cap](https://mockups-design.com/free-baseball-cap-mockup/) | MD341 Free Baseball Cap Mockup | Rookery | +| [Business card](https://mockups-design.com/free-business-card-mockup/) | MD050 Business Card Mockup | Marigold Press | +| [Spiral notebook](https://mockups-design.com/free-spiral-notebook-mockup/) | MD095 Spiral Notebook Mockup | Marigold Press | +| [Poster in frame](https://mockups-design.com/free-posters-mockup/) | MD078 Free Poster Mockup | Marigold Press | + +Merch items with no free PSD on that site (jersey, lanyard, phone case, cable, travel mug, sticker sheet…) are drawn by the skill and +labelled **illustration** in every kit. **[Unblast](https://unblast.com/mockups/)** has many more (lanyards, jerseys, phone cases, +USB cards, tumblers, coffee packaging): its mockups come from third-party authors with their own licences and a JavaScript +download step, so the skill does not download them automatically; download one yourself, read its licence, and pass it with +`psd_mockup.py --psd`. Thank you to both sites and to the mockup authors. + +### Inspiration and reference sites +[Brand New](https://www.underconsideration.com/brandnew/) · [Fonts In Use](https://fontsinuse.com/) · +[Branding Style Guides](https://brandingstyleguides.com/) · [Standards Manual](https://standardsmanual.com/) (NASA 1976, NYCTA 1970) · +[Google Fonts Knowledge](https://fonts.google.com/knowledge) · [Are.na](https://www.are.na/) · guideline anatomy from NASA, NYCTA, Mozilla, +GitLab, Spotify, Uber Eats, Atlassian and Mailchimp (links in `skills/brand-studio/references/bi-kit.md`). + +### Services queried at run time +[Google Fonts](https://fonts.google.com/) and the [Fontsource API](https://fontsource.org/docs/api) (fonts, licences), +[TheColorAPI](https://www.thecolorapi.com/) and [Colormind](http://colormind.io/) (palette suggestions), [Iconify](https://iconify.design/) +(symbol inspiration only). Fonts in the examples are SIL OFL families: Young Serif, Hanken Grotesk, Chakra Petch, Barlow, Instrument Serif, +Instrument Sans. + +### Research behind the guidance +Colour, type and logo guidance cites its sources inline in the `bi-*` reference cards (WCAG 2.2, Labrecque et al., Phillips et al., +Henderson & Cote and others, each tagged strong / limited / practice). diff --git a/docs/INSTALL-FOR-AGENTS.md b/docs/INSTALL-FOR-AGENTS.md index 4166f86..94977cf 100644 --- a/docs/INSTALL-FOR-AGENTS.md +++ b/docs/INSTALL-FOR-AGENTS.md @@ -14,8 +14,8 @@ You are an AI coding agent (Claude Code, Codex CLI, Gemini CLI, Cursor, Copilot ## 1. Get the repository ```bash -git clone https://github.com/REPLACE-WITH-YOUR-GITHUB-USER/brand-studio.git -cd brand-studio +git clone https://github.com/shadowtor/BrandDesign.git +cd BrandDesign ``` If the user already has a clone, run `git pull` instead. If `git` is not available, download the repository ZIP from GitHub and extract it. @@ -37,7 +37,7 @@ Use `python3` instead of `python` on macOS/Linux when `python` is missing; on Wi Add `--link` to symlink instead of copy (useful if the user will edit the repository). **Claude Code plugin alternative** (no clone needed): tell the user to run -`/plugin marketplace add REPLACE-WITH-YOUR-GITHUB-USER/brand-studio` and then `/plugin install brand-studio@brand-studio`. +`/plugin marketplace add shadowtor/BrandDesign` and then `/plugin install brand-studio@brand-studio`. You cannot run slash commands yourself; give them these two lines. ## 3. Verify @@ -49,7 +49,7 @@ python skills/brand-studio/scripts/check_setup.py Expected: `PASS` for Python and a Chromium browser; `PASS` or `WARN` for uv and network. A `FAIL` means the skill cannot work: fix it first (the line includes the fix). `INFO` lines for Pillow/pypdf/fonttools are normal: they are installed on demand. If `uv` is missing, offer to install it (command is in the `WARN` line) or run -`pip install pillow pypdf fonttools uharfbuzz` for the same effect. +`pip install pillow pypdf fonttools uharfbuzz pymupdf` (plus `"psd-tools[composite]" numpy scipy scikit-image` for `--photo-mockups`) for the same effect. Optional deeper check (needs internet, ~2 minutes): `python tools/smoke_test.py`. diff --git a/examples/kiln/README.md b/examples/kiln/README.md new file mode 100644 index 0000000..9518949 --- /dev/null +++ b/examples/kiln/README.md @@ -0,0 +1,32 @@ +# Kiln + +*Specialty coffee roastery, Istanbul (fictional). Not a real business: made to show what the skill produces.* + +- Business type: **coffee** (decides the merch set) +- Merch: Coffee bean bag (photo), Takeaway coffee cup (photo), Mug (photo), Travel mug (illustration), Apron (photo), Tote bag (photo) +- Brand data: [`brand.json`](brand.json) · final artwork: [`final/`](final) · all SVG logo versions: [`logo/svg/`](logo/svg) +- Guidelines PDF: [`preview/kiln-brand-guidelines.pdf`](preview/kiln-brand-guidelines.pdf) + +## Logo versions (horizontal and symbol × colour-light, colour-dark, black, white, greyscale) + +![Logo versions](preview/logo-versions.jpg) + +## Merch chosen for this business + +![Merch](preview/merch.jpg) + +## Guidelines pages + +![Guidelines](preview/guidelines-pages.jpg) + +## Favicon test + +![Favicon test](preview/favicon-test.jpg) + +## Social banner and letterhead + +![Banner](preview/social-banner.jpg) + +![Letterhead](preview/letterhead.jpg) + +Photographic mockups are previews built from free PSDs by mockups-design.com (see the main README credits). The PSDs are not included. diff --git a/examples/kiln/brand.json b/examples/kiln/brand.json new file mode 100644 index 0000000..4674b20 --- /dev/null +++ b/examples/kiln/brand.json @@ -0,0 +1,61 @@ +{ + "name": "Kiln", + "slug": "kiln", + "tagline": "Small-batch coffee, roasted in Istanbul", + "business_type": "coffee", + "adjectives": [ + "warm", + "crafted", + "modern" + ], + "mechanism": "The arched firing mouth of a kiln with one ember inside: where the coffee is made.", + "rationale": "Fictional example brand. A specialty roastery that wants a crafted, modern look without rustic clich\u00e9. The arch is the kiln; the ember is the roast; the arch also reads as a K-less initial 'n'.", + "colors": { + "primary": "#D9480F", + "secondary": "#F2B544", + "ink": "#1F1A17", + "paper": "#F7F5F0", + "accent": "#F2B544" + }, + "color_names": { + "primary": "Kiln Orange", + "secondary": "Ember", + "accent": "Ember", + "ink": "Roast", + "paper": "Parchment" + }, + "logo": { + "symbol": "final/symbol.svg", + "horizontal": "final/horizontal.svg", + "vertical": "final/vertical.svg", + "square": "final/square.svg", + "wordmark": "final/wordmark.svg", + "favicon_source": "final/favicon-source.svg", + "app_icon": { + "bg": "#F7F5F0", + "fg": "keep" + }, + "dark_map": { + "#1f1a17": "#f7f5f0" + }, + "dark_ground": "#14100E" + }, + "fonts": { + "display": "Young Serif", + "text": "Hanken Grotesk", + "display_weight": 400 + }, + "contact": { + "address": "1 Example Street, Istanbul", + "email": "hello@kiln.example", + "web": "kiln.example" + }, + "merch": [ + "coffee-bag", + "coffee-cup", + "mug", + "travel-mug", + "apron", + "tote" + ] +} \ No newline at end of file diff --git a/examples/kiln/final/favicon-source.svg b/examples/kiln/final/favicon-source.svg new file mode 100644 index 0000000..104e9c0 --- /dev/null +++ b/examples/kiln/final/favicon-source.svg @@ -0,0 +1 @@ +favicon \ No newline at end of file diff --git a/examples/kiln/final/horizontal.svg b/examples/kiln/final/horizontal.svg new file mode 100644 index 0000000..361f3a4 --- /dev/null +++ b/examples/kiln/final/horizontal.svg @@ -0,0 +1 @@ +Kiln horizontal \ No newline at end of file diff --git a/examples/kiln/final/square.svg b/examples/kiln/final/square.svg new file mode 100644 index 0000000..d11e2ef --- /dev/null +++ b/examples/kiln/final/square.svg @@ -0,0 +1 @@ +Kiln square \ No newline at end of file diff --git a/examples/kiln/final/symbol.svg b/examples/kiln/final/symbol.svg new file mode 100644 index 0000000..65147e1 --- /dev/null +++ b/examples/kiln/final/symbol.svg @@ -0,0 +1 @@ +Kiln symbol \ No newline at end of file diff --git a/examples/kiln/final/vertical.svg b/examples/kiln/final/vertical.svg new file mode 100644 index 0000000..be8313d --- /dev/null +++ b/examples/kiln/final/vertical.svg @@ -0,0 +1 @@ +Kiln vertical \ No newline at end of file diff --git a/examples/kiln/final/wordmark.svg b/examples/kiln/final/wordmark.svg new file mode 100644 index 0000000..f9666c5 --- /dev/null +++ b/examples/kiln/final/wordmark.svg @@ -0,0 +1 @@ +Kiln \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-horizontal-black.svg b/examples/kiln/logo/svg/kiln-horizontal-black.svg new file mode 100644 index 0000000..43025ee --- /dev/null +++ b/examples/kiln/logo/svg/kiln-horizontal-black.svg @@ -0,0 +1 @@ +Kiln horizontal \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-horizontal-colour-dark.svg b/examples/kiln/logo/svg/kiln-horizontal-colour-dark.svg new file mode 100644 index 0000000..8599daa --- /dev/null +++ b/examples/kiln/logo/svg/kiln-horizontal-colour-dark.svg @@ -0,0 +1 @@ +Kiln horizontal \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-horizontal-colour-light.svg b/examples/kiln/logo/svg/kiln-horizontal-colour-light.svg new file mode 100644 index 0000000..361f3a4 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-horizontal-colour-light.svg @@ -0,0 +1 @@ +Kiln horizontal \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-horizontal-greyscale.svg b/examples/kiln/logo/svg/kiln-horizontal-greyscale.svg new file mode 100644 index 0000000..de7839f --- /dev/null +++ b/examples/kiln/logo/svg/kiln-horizontal-greyscale.svg @@ -0,0 +1 @@ +Kiln horizontal \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-horizontal-white.svg b/examples/kiln/logo/svg/kiln-horizontal-white.svg new file mode 100644 index 0000000..56bba2f --- /dev/null +++ b/examples/kiln/logo/svg/kiln-horizontal-white.svg @@ -0,0 +1 @@ +Kiln horizontal \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-square-black.svg b/examples/kiln/logo/svg/kiln-square-black.svg new file mode 100644 index 0000000..76965af --- /dev/null +++ b/examples/kiln/logo/svg/kiln-square-black.svg @@ -0,0 +1 @@ +Kiln square \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-square-colour-dark.svg b/examples/kiln/logo/svg/kiln-square-colour-dark.svg new file mode 100644 index 0000000..76c2b21 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-square-colour-dark.svg @@ -0,0 +1 @@ +Kiln square \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-square-colour-light.svg b/examples/kiln/logo/svg/kiln-square-colour-light.svg new file mode 100644 index 0000000..d11e2ef --- /dev/null +++ b/examples/kiln/logo/svg/kiln-square-colour-light.svg @@ -0,0 +1 @@ +Kiln square \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-square-greyscale.svg b/examples/kiln/logo/svg/kiln-square-greyscale.svg new file mode 100644 index 0000000..f961691 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-square-greyscale.svg @@ -0,0 +1 @@ +Kiln square \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-square-white.svg b/examples/kiln/logo/svg/kiln-square-white.svg new file mode 100644 index 0000000..cf869d6 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-square-white.svg @@ -0,0 +1 @@ +Kiln square \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-symbol-black.svg b/examples/kiln/logo/svg/kiln-symbol-black.svg new file mode 100644 index 0000000..e2ae0b1 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-symbol-black.svg @@ -0,0 +1 @@ +Kiln symbol \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-symbol-colour-dark.svg b/examples/kiln/logo/svg/kiln-symbol-colour-dark.svg new file mode 100644 index 0000000..ddeccf7 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-symbol-colour-dark.svg @@ -0,0 +1 @@ +Kiln symbol \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-symbol-colour-light.svg b/examples/kiln/logo/svg/kiln-symbol-colour-light.svg new file mode 100644 index 0000000..65147e1 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-symbol-colour-light.svg @@ -0,0 +1 @@ +Kiln symbol \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-symbol-greyscale.svg b/examples/kiln/logo/svg/kiln-symbol-greyscale.svg new file mode 100644 index 0000000..70a4e6b --- /dev/null +++ b/examples/kiln/logo/svg/kiln-symbol-greyscale.svg @@ -0,0 +1 @@ +Kiln symbol \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-symbol-white.svg b/examples/kiln/logo/svg/kiln-symbol-white.svg new file mode 100644 index 0000000..87abc11 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-symbol-white.svg @@ -0,0 +1 @@ +Kiln symbol \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-vertical-black.svg b/examples/kiln/logo/svg/kiln-vertical-black.svg new file mode 100644 index 0000000..17dc766 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-vertical-black.svg @@ -0,0 +1 @@ +Kiln vertical \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-vertical-colour-dark.svg b/examples/kiln/logo/svg/kiln-vertical-colour-dark.svg new file mode 100644 index 0000000..d45b313 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-vertical-colour-dark.svg @@ -0,0 +1 @@ +Kiln vertical \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-vertical-colour-light.svg b/examples/kiln/logo/svg/kiln-vertical-colour-light.svg new file mode 100644 index 0000000..be8313d --- /dev/null +++ b/examples/kiln/logo/svg/kiln-vertical-colour-light.svg @@ -0,0 +1 @@ +Kiln vertical \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-vertical-greyscale.svg b/examples/kiln/logo/svg/kiln-vertical-greyscale.svg new file mode 100644 index 0000000..ec99f29 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-vertical-greyscale.svg @@ -0,0 +1 @@ +Kiln vertical \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-vertical-white.svg b/examples/kiln/logo/svg/kiln-vertical-white.svg new file mode 100644 index 0000000..4fc699d --- /dev/null +++ b/examples/kiln/logo/svg/kiln-vertical-white.svg @@ -0,0 +1 @@ +Kiln vertical \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-wordmark-black.svg b/examples/kiln/logo/svg/kiln-wordmark-black.svg new file mode 100644 index 0000000..cedacd7 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-wordmark-black.svg @@ -0,0 +1 @@ +Kiln \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-wordmark-colour-dark.svg b/examples/kiln/logo/svg/kiln-wordmark-colour-dark.svg new file mode 100644 index 0000000..8c4cea2 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-wordmark-colour-dark.svg @@ -0,0 +1 @@ +Kiln \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-wordmark-colour-light.svg b/examples/kiln/logo/svg/kiln-wordmark-colour-light.svg new file mode 100644 index 0000000..f9666c5 --- /dev/null +++ b/examples/kiln/logo/svg/kiln-wordmark-colour-light.svg @@ -0,0 +1 @@ +Kiln \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-wordmark-greyscale.svg b/examples/kiln/logo/svg/kiln-wordmark-greyscale.svg new file mode 100644 index 0000000..5898ebb --- /dev/null +++ b/examples/kiln/logo/svg/kiln-wordmark-greyscale.svg @@ -0,0 +1 @@ +Kiln \ No newline at end of file diff --git a/examples/kiln/logo/svg/kiln-wordmark-white.svg b/examples/kiln/logo/svg/kiln-wordmark-white.svg new file mode 100644 index 0000000..5a17e2f --- /dev/null +++ b/examples/kiln/logo/svg/kiln-wordmark-white.svg @@ -0,0 +1 @@ +Kiln \ No newline at end of file diff --git a/examples/kiln/preview/favicon-test.jpg b/examples/kiln/preview/favicon-test.jpg new file mode 100644 index 0000000..f3247fa Binary files /dev/null and b/examples/kiln/preview/favicon-test.jpg differ diff --git a/examples/kiln/preview/guidelines-pages.jpg b/examples/kiln/preview/guidelines-pages.jpg new file mode 100644 index 0000000..8fc029f Binary files /dev/null and b/examples/kiln/preview/guidelines-pages.jpg differ diff --git a/examples/kiln/preview/kiln-brand-guidelines.pdf b/examples/kiln/preview/kiln-brand-guidelines.pdf new file mode 100644 index 0000000..1d4a308 Binary files /dev/null and b/examples/kiln/preview/kiln-brand-guidelines.pdf differ diff --git a/examples/kiln/preview/letterhead.jpg b/examples/kiln/preview/letterhead.jpg new file mode 100644 index 0000000..85d67d4 Binary files /dev/null and b/examples/kiln/preview/letterhead.jpg differ diff --git a/examples/kiln/preview/logo-versions.jpg b/examples/kiln/preview/logo-versions.jpg new file mode 100644 index 0000000..a90dd93 Binary files /dev/null and b/examples/kiln/preview/logo-versions.jpg differ diff --git a/examples/kiln/preview/merch.jpg b/examples/kiln/preview/merch.jpg new file mode 100644 index 0000000..e392454 Binary files /dev/null and b/examples/kiln/preview/merch.jpg differ diff --git a/examples/kiln/preview/mockups/apron-photo.jpg b/examples/kiln/preview/mockups/apron-photo.jpg new file mode 100644 index 0000000..ba7c489 Binary files /dev/null and b/examples/kiln/preview/mockups/apron-photo.jpg differ diff --git a/examples/kiln/preview/mockups/coffee-bag-photo.jpg b/examples/kiln/preview/mockups/coffee-bag-photo.jpg new file mode 100644 index 0000000..ebab169 Binary files /dev/null and b/examples/kiln/preview/mockups/coffee-bag-photo.jpg differ diff --git a/examples/kiln/preview/mockups/coffee-cup-photo.jpg b/examples/kiln/preview/mockups/coffee-cup-photo.jpg new file mode 100644 index 0000000..c8c0935 Binary files /dev/null and b/examples/kiln/preview/mockups/coffee-cup-photo.jpg differ diff --git a/examples/kiln/preview/mockups/mug-photo.jpg b/examples/kiln/preview/mockups/mug-photo.jpg new file mode 100644 index 0000000..d4f80e4 Binary files /dev/null and b/examples/kiln/preview/mockups/mug-photo.jpg differ diff --git a/examples/kiln/preview/mockups/tote-photo.jpg b/examples/kiln/preview/mockups/tote-photo.jpg new file mode 100644 index 0000000..7788875 Binary files /dev/null and b/examples/kiln/preview/mockups/tote-photo.jpg differ diff --git a/examples/kiln/preview/mockups/travel-mug-illustration.jpg b/examples/kiln/preview/mockups/travel-mug-illustration.jpg new file mode 100644 index 0000000..198fd25 Binary files /dev/null and b/examples/kiln/preview/mockups/travel-mug-illustration.jpg differ diff --git a/examples/kiln/preview/social-banner.jpg b/examples/kiln/preview/social-banner.jpg new file mode 100644 index 0000000..1d55900 Binary files /dev/null and b/examples/kiln/preview/social-banner.jpg differ diff --git a/examples/marigold/README.md b/examples/marigold/README.md new file mode 100644 index 0000000..e407cb6 --- /dev/null +++ b/examples/marigold/README.md @@ -0,0 +1,32 @@ +# Marigold Press + +*Independent illustrator selling prints, stickers and totes (fictional). Not a real business: made to show what the skill produces.* + +- Business type: **artist** (decides the merch set) +- Merch: Sticker sheet (illustration), Business card (photo), T-shirt (photo), Tote bag (photo), Notebook (photo), Poster (photo) +- Brand data: [`brand.json`](brand.json) · final artwork: [`final/`](final) · all SVG logo versions: [`logo/svg/`](logo/svg) +- Guidelines PDF: [`preview/marigold-brand-guidelines.pdf`](preview/marigold-brand-guidelines.pdf) + +## Logo versions (horizontal and symbol × colour-light, colour-dark, black, white, greyscale) + +![Logo versions](preview/logo-versions.jpg) + +## Merch chosen for this business + +![Merch](preview/merch.jpg) + +## Guidelines pages + +![Guidelines](preview/guidelines-pages.jpg) + +## Favicon test + +![Favicon test](preview/favicon-test.jpg) + +## Social banner and letterhead + +![Banner](preview/social-banner.jpg) + +![Letterhead](preview/letterhead.jpg) + +Photographic mockups are previews built from free PSDs by mockups-design.com (see the main README credits). The PSDs are not included. diff --git a/examples/marigold/brand.json b/examples/marigold/brand.json new file mode 100644 index 0000000..97f2c43 --- /dev/null +++ b/examples/marigold/brand.json @@ -0,0 +1,61 @@ +{ + "name": "Marigold Press", + "slug": "marigold", + "tagline": "Small prints, big colour", + "business_type": "artist", + "adjectives": [ + "warm", + "playful", + "handmade" + ], + "mechanism": "A marigold seen from above: eight round petals around a deep teal heart, like a printed dot or a sticker.", + "rationale": "Fictional example brand. An independent illustrator selling prints, stickers and tote bags at markets and online. Circles are the shape of stickers, dots and presses; marigold is a flower that grows in anyone's garden.", + "colors": { + "primary": "#1F6F6B", + "secondary": "#F2A900", + "ink": "#23222B", + "paper": "#FAF8F5", + "accent": "#F2A900" + }, + "color_names": { + "primary": "Press Teal", + "secondary": "Marigold", + "accent": "Marigold", + "ink": "Ink", + "paper": "Paper" + }, + "logo": { + "symbol": "final/symbol.svg", + "horizontal": "final/horizontal.svg", + "vertical": "final/vertical.svg", + "square": "final/square.svg", + "wordmark": "final/wordmark.svg", + "favicon_source": "final/favicon-source.svg", + "app_icon": { + "bg": "#FAF8F5", + "fg": "keep" + }, + "dark_map": { + "#23222b": "#faf8f5", + "#1f6f6b": "#5FC3BC" + }, + "dark_ground": "#17161C" + }, + "fonts": { + "display": "Instrument Serif", + "text": "Instrument Sans", + "display_weight": 400 + }, + "contact": { + "email": "hello@marigold.example", + "web": "marigold.example" + }, + "merch": [ + "sticker-sheet", + "business-card", + "tee", + "tote", + "notebook", + "poster" + ] +} \ No newline at end of file diff --git a/examples/marigold/final/favicon-source.svg b/examples/marigold/final/favicon-source.svg new file mode 100644 index 0000000..c91b006 --- /dev/null +++ b/examples/marigold/final/favicon-source.svg @@ -0,0 +1 @@ +favicon \ No newline at end of file diff --git a/examples/marigold/final/horizontal.svg b/examples/marigold/final/horizontal.svg new file mode 100644 index 0000000..30502e0 --- /dev/null +++ b/examples/marigold/final/horizontal.svg @@ -0,0 +1 @@ +Marigold Press horizontal \ No newline at end of file diff --git a/examples/marigold/final/square.svg b/examples/marigold/final/square.svg new file mode 100644 index 0000000..3404637 --- /dev/null +++ b/examples/marigold/final/square.svg @@ -0,0 +1 @@ +Marigold Press square \ No newline at end of file diff --git a/examples/marigold/final/symbol.svg b/examples/marigold/final/symbol.svg new file mode 100644 index 0000000..c4f34fe --- /dev/null +++ b/examples/marigold/final/symbol.svg @@ -0,0 +1 @@ +Marigold Press symbol \ No newline at end of file diff --git a/examples/marigold/final/vertical.svg b/examples/marigold/final/vertical.svg new file mode 100644 index 0000000..f31ca26 --- /dev/null +++ b/examples/marigold/final/vertical.svg @@ -0,0 +1 @@ +Marigold Press vertical \ No newline at end of file diff --git a/examples/marigold/final/wordmark.svg b/examples/marigold/final/wordmark.svg new file mode 100644 index 0000000..8fed3be --- /dev/null +++ b/examples/marigold/final/wordmark.svg @@ -0,0 +1 @@ +Marigold Press \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-horizontal-black.svg b/examples/marigold/logo/svg/marigold-horizontal-black.svg new file mode 100644 index 0000000..9f42805 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-horizontal-black.svg @@ -0,0 +1 @@ +Marigold Press horizontal \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-horizontal-colour-dark.svg b/examples/marigold/logo/svg/marigold-horizontal-colour-dark.svg new file mode 100644 index 0000000..4494bd0 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-horizontal-colour-dark.svg @@ -0,0 +1 @@ +Marigold Press horizontal \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-horizontal-colour-light.svg b/examples/marigold/logo/svg/marigold-horizontal-colour-light.svg new file mode 100644 index 0000000..30502e0 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-horizontal-colour-light.svg @@ -0,0 +1 @@ +Marigold Press horizontal \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-horizontal-greyscale.svg b/examples/marigold/logo/svg/marigold-horizontal-greyscale.svg new file mode 100644 index 0000000..0a5de46 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-horizontal-greyscale.svg @@ -0,0 +1 @@ +Marigold Press horizontal \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-horizontal-white.svg b/examples/marigold/logo/svg/marigold-horizontal-white.svg new file mode 100644 index 0000000..5d39328 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-horizontal-white.svg @@ -0,0 +1 @@ +Marigold Press horizontal \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-square-black.svg b/examples/marigold/logo/svg/marigold-square-black.svg new file mode 100644 index 0000000..2d3fd87 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-square-black.svg @@ -0,0 +1 @@ +Marigold Press square \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-square-colour-dark.svg b/examples/marigold/logo/svg/marigold-square-colour-dark.svg new file mode 100644 index 0000000..00b81c0 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-square-colour-dark.svg @@ -0,0 +1 @@ +Marigold Press square \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-square-colour-light.svg b/examples/marigold/logo/svg/marigold-square-colour-light.svg new file mode 100644 index 0000000..3404637 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-square-colour-light.svg @@ -0,0 +1 @@ +Marigold Press square \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-square-greyscale.svg b/examples/marigold/logo/svg/marigold-square-greyscale.svg new file mode 100644 index 0000000..a2b783f --- /dev/null +++ b/examples/marigold/logo/svg/marigold-square-greyscale.svg @@ -0,0 +1 @@ +Marigold Press square \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-square-white.svg b/examples/marigold/logo/svg/marigold-square-white.svg new file mode 100644 index 0000000..61d0806 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-square-white.svg @@ -0,0 +1 @@ +Marigold Press square \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-symbol-black.svg b/examples/marigold/logo/svg/marigold-symbol-black.svg new file mode 100644 index 0000000..496cfea --- /dev/null +++ b/examples/marigold/logo/svg/marigold-symbol-black.svg @@ -0,0 +1 @@ +Marigold Press symbol \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-symbol-colour-dark.svg b/examples/marigold/logo/svg/marigold-symbol-colour-dark.svg new file mode 100644 index 0000000..0143d49 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-symbol-colour-dark.svg @@ -0,0 +1 @@ +Marigold Press symbol \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-symbol-colour-light.svg b/examples/marigold/logo/svg/marigold-symbol-colour-light.svg new file mode 100644 index 0000000..c4f34fe --- /dev/null +++ b/examples/marigold/logo/svg/marigold-symbol-colour-light.svg @@ -0,0 +1 @@ +Marigold Press symbol \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-symbol-greyscale.svg b/examples/marigold/logo/svg/marigold-symbol-greyscale.svg new file mode 100644 index 0000000..671f4ed --- /dev/null +++ b/examples/marigold/logo/svg/marigold-symbol-greyscale.svg @@ -0,0 +1 @@ +Marigold Press symbol \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-symbol-white.svg b/examples/marigold/logo/svg/marigold-symbol-white.svg new file mode 100644 index 0000000..b7757fc --- /dev/null +++ b/examples/marigold/logo/svg/marigold-symbol-white.svg @@ -0,0 +1 @@ +Marigold Press symbol \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-vertical-black.svg b/examples/marigold/logo/svg/marigold-vertical-black.svg new file mode 100644 index 0000000..b7b6d22 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-vertical-black.svg @@ -0,0 +1 @@ +Marigold Press vertical \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-vertical-colour-dark.svg b/examples/marigold/logo/svg/marigold-vertical-colour-dark.svg new file mode 100644 index 0000000..5dd9053 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-vertical-colour-dark.svg @@ -0,0 +1 @@ +Marigold Press vertical \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-vertical-colour-light.svg b/examples/marigold/logo/svg/marigold-vertical-colour-light.svg new file mode 100644 index 0000000..f31ca26 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-vertical-colour-light.svg @@ -0,0 +1 @@ +Marigold Press vertical \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-vertical-greyscale.svg b/examples/marigold/logo/svg/marigold-vertical-greyscale.svg new file mode 100644 index 0000000..4f83867 --- /dev/null +++ b/examples/marigold/logo/svg/marigold-vertical-greyscale.svg @@ -0,0 +1 @@ +Marigold Press vertical \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-vertical-white.svg b/examples/marigold/logo/svg/marigold-vertical-white.svg new file mode 100644 index 0000000..407fe8f --- /dev/null +++ b/examples/marigold/logo/svg/marigold-vertical-white.svg @@ -0,0 +1 @@ +Marigold Press vertical \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-wordmark-black.svg b/examples/marigold/logo/svg/marigold-wordmark-black.svg new file mode 100644 index 0000000..516109c --- /dev/null +++ b/examples/marigold/logo/svg/marigold-wordmark-black.svg @@ -0,0 +1 @@ +Marigold Press \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-wordmark-colour-dark.svg b/examples/marigold/logo/svg/marigold-wordmark-colour-dark.svg new file mode 100644 index 0000000..4e8481b --- /dev/null +++ b/examples/marigold/logo/svg/marigold-wordmark-colour-dark.svg @@ -0,0 +1 @@ +Marigold Press \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-wordmark-colour-light.svg b/examples/marigold/logo/svg/marigold-wordmark-colour-light.svg new file mode 100644 index 0000000..8fed3be --- /dev/null +++ b/examples/marigold/logo/svg/marigold-wordmark-colour-light.svg @@ -0,0 +1 @@ +Marigold Press \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-wordmark-greyscale.svg b/examples/marigold/logo/svg/marigold-wordmark-greyscale.svg new file mode 100644 index 0000000..02fdb8e --- /dev/null +++ b/examples/marigold/logo/svg/marigold-wordmark-greyscale.svg @@ -0,0 +1 @@ +Marigold Press \ No newline at end of file diff --git a/examples/marigold/logo/svg/marigold-wordmark-white.svg b/examples/marigold/logo/svg/marigold-wordmark-white.svg new file mode 100644 index 0000000..090c2cb --- /dev/null +++ b/examples/marigold/logo/svg/marigold-wordmark-white.svg @@ -0,0 +1 @@ +Marigold Press \ No newline at end of file diff --git a/examples/marigold/preview/favicon-test.jpg b/examples/marigold/preview/favicon-test.jpg new file mode 100644 index 0000000..32ecdcf Binary files /dev/null and b/examples/marigold/preview/favicon-test.jpg differ diff --git a/examples/marigold/preview/guidelines-pages.jpg b/examples/marigold/preview/guidelines-pages.jpg new file mode 100644 index 0000000..02681c7 Binary files /dev/null and b/examples/marigold/preview/guidelines-pages.jpg differ diff --git a/examples/marigold/preview/letterhead.jpg b/examples/marigold/preview/letterhead.jpg new file mode 100644 index 0000000..ff70dc7 Binary files /dev/null and b/examples/marigold/preview/letterhead.jpg differ diff --git a/examples/marigold/preview/logo-versions.jpg b/examples/marigold/preview/logo-versions.jpg new file mode 100644 index 0000000..7ca11cb Binary files /dev/null and b/examples/marigold/preview/logo-versions.jpg differ diff --git a/examples/marigold/preview/marigold-brand-guidelines.pdf b/examples/marigold/preview/marigold-brand-guidelines.pdf new file mode 100644 index 0000000..c38be2d Binary files /dev/null and b/examples/marigold/preview/marigold-brand-guidelines.pdf differ diff --git a/examples/marigold/preview/merch.jpg b/examples/marigold/preview/merch.jpg new file mode 100644 index 0000000..10dc753 Binary files /dev/null and b/examples/marigold/preview/merch.jpg differ diff --git a/examples/marigold/preview/mockups/business-card-photo.jpg b/examples/marigold/preview/mockups/business-card-photo.jpg new file mode 100644 index 0000000..1967a0c Binary files /dev/null and b/examples/marigold/preview/mockups/business-card-photo.jpg differ diff --git a/examples/marigold/preview/mockups/notebook-photo.jpg b/examples/marigold/preview/mockups/notebook-photo.jpg new file mode 100644 index 0000000..370a94c Binary files /dev/null and b/examples/marigold/preview/mockups/notebook-photo.jpg differ diff --git a/examples/marigold/preview/mockups/poster-photo.jpg b/examples/marigold/preview/mockups/poster-photo.jpg new file mode 100644 index 0000000..be86929 Binary files /dev/null and b/examples/marigold/preview/mockups/poster-photo.jpg differ diff --git a/examples/marigold/preview/mockups/sticker-sheet-illustration.jpg b/examples/marigold/preview/mockups/sticker-sheet-illustration.jpg new file mode 100644 index 0000000..ff03e98 Binary files /dev/null and b/examples/marigold/preview/mockups/sticker-sheet-illustration.jpg differ diff --git a/examples/marigold/preview/mockups/tee-photo.jpg b/examples/marigold/preview/mockups/tee-photo.jpg new file mode 100644 index 0000000..a6622ee Binary files /dev/null and b/examples/marigold/preview/mockups/tee-photo.jpg differ diff --git a/examples/marigold/preview/mockups/tote-photo.jpg b/examples/marigold/preview/mockups/tote-photo.jpg new file mode 100644 index 0000000..55756c2 Binary files /dev/null and b/examples/marigold/preview/mockups/tote-photo.jpg differ diff --git a/examples/marigold/preview/social-banner.jpg b/examples/marigold/preview/social-banner.jpg new file mode 100644 index 0000000..202ff59 Binary files /dev/null and b/examples/marigold/preview/social-banner.jpg differ diff --git a/examples/overview.png b/examples/overview.png new file mode 100644 index 0000000..5c08049 Binary files /dev/null and b/examples/overview.png differ diff --git a/examples/rookery/README.md b/examples/rookery/README.md new file mode 100644 index 0000000..7f80ced --- /dev/null +++ b/examples/rookery/README.md @@ -0,0 +1,32 @@ +# Rookery + +*Competitive but welcoming gaming community (fictional). Not a real business: made to show what the skill produces.* + +- Business type: **gaming** (decides the merch set) +- Merch: Team jersey (illustration), Mouse mat (photo), Hoodie (photo), T-shirt (photo), Cap (photo), Sticker sheet (illustration) +- Brand data: [`brand.json`](brand.json) · final artwork: [`final/`](final) · all SVG logo versions: [`logo/svg/`](logo/svg) +- Guidelines PDF: [`preview/rookery-brand-guidelines.pdf`](preview/rookery-brand-guidelines.pdf) + +## Logo versions (horizontal and symbol × colour-light, colour-dark, black, white, greyscale) + +![Logo versions](preview/logo-versions.jpg) + +## Merch chosen for this business + +![Merch](preview/merch.jpg) + +## Guidelines pages + +![Guidelines](preview/guidelines-pages.jpg) + +## Favicon test + +![Favicon test](preview/favicon-test.jpg) + +## Social banner and letterhead + +![Banner](preview/social-banner.jpg) + +![Letterhead](preview/letterhead.jpg) + +Photographic mockups are previews built from free PSDs by mockups-design.com (see the main README credits). The PSDs are not included. diff --git a/examples/rookery/brand.json b/examples/rookery/brand.json new file mode 100644 index 0000000..800aa0a --- /dev/null +++ b/examples/rookery/brand.json @@ -0,0 +1,60 @@ +{ + "name": "Rookery", + "slug": "rookery", + "tagline": "Play together. Win together.", + "business_type": "gaming", + "adjectives": [ + "competitive", + "welcoming", + "sharp" + ], + "mechanism": "A rook (the chess piece that guards the corners) built from pixel-square blocks, with one lit window.", + "rationale": "Fictional example brand. A community of competitive players who also want newcomers to feel welcome. Chess supplies strategy and teamwork; the blocky crenellations nod to pixels; the lime window is the one light left on for new players.", + "colors": { + "primary": "#12141C", + "secondary": "#8BE01E", + "ink": "#12141C", + "paper": "#F4F6F8", + "accent": "#8BE01E" + }, + "color_names": { + "primary": "Night Shift", + "secondary": "Lobby Lime", + "accent": "Lobby Lime", + "ink": "Night Shift", + "paper": "Daylight" + }, + "logo": { + "symbol": "final/symbol.svg", + "horizontal": "final/horizontal.svg", + "vertical": "final/vertical.svg", + "square": "final/square.svg", + "wordmark": "final/wordmark.svg", + "favicon_source": "final/favicon-source.svg", + "app_icon": { + "bg": "#12141C", + "fg": "keep" + }, + "dark_map": { + "#12141c": "#f4f6f8" + }, + "dark_ground": "#0B0C11" + }, + "fonts": { + "display": "Chakra Petch", + "text": "Barlow", + "display_weight": 700 + }, + "contact": { + "email": "hello@rookery.example", + "web": "rookery.example" + }, + "merch": [ + "jersey", + "mousemat", + "hoodie", + "tee", + "cap", + "sticker-sheet" + ] +} \ No newline at end of file diff --git a/examples/rookery/final/favicon-source.svg b/examples/rookery/final/favicon-source.svg new file mode 100644 index 0000000..101ced9 --- /dev/null +++ b/examples/rookery/final/favicon-source.svg @@ -0,0 +1 @@ +favicon \ No newline at end of file diff --git a/examples/rookery/final/horizontal.svg b/examples/rookery/final/horizontal.svg new file mode 100644 index 0000000..951e872 --- /dev/null +++ b/examples/rookery/final/horizontal.svg @@ -0,0 +1 @@ +Rookery horizontal \ No newline at end of file diff --git a/examples/rookery/final/square.svg b/examples/rookery/final/square.svg new file mode 100644 index 0000000..34f9729 --- /dev/null +++ b/examples/rookery/final/square.svg @@ -0,0 +1 @@ +Rookery square \ No newline at end of file diff --git a/examples/rookery/final/symbol.svg b/examples/rookery/final/symbol.svg new file mode 100644 index 0000000..039881b --- /dev/null +++ b/examples/rookery/final/symbol.svg @@ -0,0 +1 @@ +Rookery symbol \ No newline at end of file diff --git a/examples/rookery/final/vertical.svg b/examples/rookery/final/vertical.svg new file mode 100644 index 0000000..c6170b5 --- /dev/null +++ b/examples/rookery/final/vertical.svg @@ -0,0 +1 @@ +Rookery vertical \ No newline at end of file diff --git a/examples/rookery/final/wordmark.svg b/examples/rookery/final/wordmark.svg new file mode 100644 index 0000000..dc07762 --- /dev/null +++ b/examples/rookery/final/wordmark.svg @@ -0,0 +1 @@ +ROOKERY \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-horizontal-black.svg b/examples/rookery/logo/svg/rookery-horizontal-black.svg new file mode 100644 index 0000000..45ee01a --- /dev/null +++ b/examples/rookery/logo/svg/rookery-horizontal-black.svg @@ -0,0 +1 @@ +Rookery horizontal \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-horizontal-colour-dark.svg b/examples/rookery/logo/svg/rookery-horizontal-colour-dark.svg new file mode 100644 index 0000000..457e906 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-horizontal-colour-dark.svg @@ -0,0 +1 @@ +Rookery horizontal \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-horizontal-colour-light.svg b/examples/rookery/logo/svg/rookery-horizontal-colour-light.svg new file mode 100644 index 0000000..951e872 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-horizontal-colour-light.svg @@ -0,0 +1 @@ +Rookery horizontal \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-horizontal-greyscale.svg b/examples/rookery/logo/svg/rookery-horizontal-greyscale.svg new file mode 100644 index 0000000..acbed3d --- /dev/null +++ b/examples/rookery/logo/svg/rookery-horizontal-greyscale.svg @@ -0,0 +1 @@ +Rookery horizontal \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-horizontal-white.svg b/examples/rookery/logo/svg/rookery-horizontal-white.svg new file mode 100644 index 0000000..3545f8b --- /dev/null +++ b/examples/rookery/logo/svg/rookery-horizontal-white.svg @@ -0,0 +1 @@ +Rookery horizontal \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-square-black.svg b/examples/rookery/logo/svg/rookery-square-black.svg new file mode 100644 index 0000000..557cd34 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-square-black.svg @@ -0,0 +1 @@ +Rookery square \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-square-colour-dark.svg b/examples/rookery/logo/svg/rookery-square-colour-dark.svg new file mode 100644 index 0000000..ff1ef1d --- /dev/null +++ b/examples/rookery/logo/svg/rookery-square-colour-dark.svg @@ -0,0 +1 @@ +Rookery square \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-square-colour-light.svg b/examples/rookery/logo/svg/rookery-square-colour-light.svg new file mode 100644 index 0000000..34f9729 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-square-colour-light.svg @@ -0,0 +1 @@ +Rookery square \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-square-greyscale.svg b/examples/rookery/logo/svg/rookery-square-greyscale.svg new file mode 100644 index 0000000..10ec50f --- /dev/null +++ b/examples/rookery/logo/svg/rookery-square-greyscale.svg @@ -0,0 +1 @@ +Rookery square \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-square-white.svg b/examples/rookery/logo/svg/rookery-square-white.svg new file mode 100644 index 0000000..8030145 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-square-white.svg @@ -0,0 +1 @@ +Rookery square \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-symbol-black.svg b/examples/rookery/logo/svg/rookery-symbol-black.svg new file mode 100644 index 0000000..ad54fd2 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-symbol-black.svg @@ -0,0 +1 @@ +Rookery symbol \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-symbol-colour-dark.svg b/examples/rookery/logo/svg/rookery-symbol-colour-dark.svg new file mode 100644 index 0000000..694d605 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-symbol-colour-dark.svg @@ -0,0 +1 @@ +Rookery symbol \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-symbol-colour-light.svg b/examples/rookery/logo/svg/rookery-symbol-colour-light.svg new file mode 100644 index 0000000..039881b --- /dev/null +++ b/examples/rookery/logo/svg/rookery-symbol-colour-light.svg @@ -0,0 +1 @@ +Rookery symbol \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-symbol-greyscale.svg b/examples/rookery/logo/svg/rookery-symbol-greyscale.svg new file mode 100644 index 0000000..0f27269 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-symbol-greyscale.svg @@ -0,0 +1 @@ +Rookery symbol \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-symbol-white.svg b/examples/rookery/logo/svg/rookery-symbol-white.svg new file mode 100644 index 0000000..249736b --- /dev/null +++ b/examples/rookery/logo/svg/rookery-symbol-white.svg @@ -0,0 +1 @@ +Rookery symbol \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-vertical-black.svg b/examples/rookery/logo/svg/rookery-vertical-black.svg new file mode 100644 index 0000000..b7c8bb4 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-vertical-black.svg @@ -0,0 +1 @@ +Rookery vertical \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-vertical-colour-dark.svg b/examples/rookery/logo/svg/rookery-vertical-colour-dark.svg new file mode 100644 index 0000000..8e3337d --- /dev/null +++ b/examples/rookery/logo/svg/rookery-vertical-colour-dark.svg @@ -0,0 +1 @@ +Rookery vertical \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-vertical-colour-light.svg b/examples/rookery/logo/svg/rookery-vertical-colour-light.svg new file mode 100644 index 0000000..c6170b5 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-vertical-colour-light.svg @@ -0,0 +1 @@ +Rookery vertical \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-vertical-greyscale.svg b/examples/rookery/logo/svg/rookery-vertical-greyscale.svg new file mode 100644 index 0000000..112d62c --- /dev/null +++ b/examples/rookery/logo/svg/rookery-vertical-greyscale.svg @@ -0,0 +1 @@ +Rookery vertical \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-vertical-white.svg b/examples/rookery/logo/svg/rookery-vertical-white.svg new file mode 100644 index 0000000..f910faf --- /dev/null +++ b/examples/rookery/logo/svg/rookery-vertical-white.svg @@ -0,0 +1 @@ +Rookery vertical \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-wordmark-black.svg b/examples/rookery/logo/svg/rookery-wordmark-black.svg new file mode 100644 index 0000000..abaa7d2 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-wordmark-black.svg @@ -0,0 +1 @@ +ROOKERY \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-wordmark-colour-dark.svg b/examples/rookery/logo/svg/rookery-wordmark-colour-dark.svg new file mode 100644 index 0000000..9800174 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-wordmark-colour-dark.svg @@ -0,0 +1 @@ +ROOKERY \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-wordmark-colour-light.svg b/examples/rookery/logo/svg/rookery-wordmark-colour-light.svg new file mode 100644 index 0000000..dc07762 --- /dev/null +++ b/examples/rookery/logo/svg/rookery-wordmark-colour-light.svg @@ -0,0 +1 @@ +ROOKERY \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-wordmark-greyscale.svg b/examples/rookery/logo/svg/rookery-wordmark-greyscale.svg new file mode 100644 index 0000000..daf633d --- /dev/null +++ b/examples/rookery/logo/svg/rookery-wordmark-greyscale.svg @@ -0,0 +1 @@ +ROOKERY \ No newline at end of file diff --git a/examples/rookery/logo/svg/rookery-wordmark-white.svg b/examples/rookery/logo/svg/rookery-wordmark-white.svg new file mode 100644 index 0000000..212f47b --- /dev/null +++ b/examples/rookery/logo/svg/rookery-wordmark-white.svg @@ -0,0 +1 @@ +ROOKERY \ No newline at end of file diff --git a/examples/rookery/preview/favicon-test.jpg b/examples/rookery/preview/favicon-test.jpg new file mode 100644 index 0000000..e6e4eb0 Binary files /dev/null and b/examples/rookery/preview/favicon-test.jpg differ diff --git a/examples/rookery/preview/guidelines-pages.jpg b/examples/rookery/preview/guidelines-pages.jpg new file mode 100644 index 0000000..da7903a Binary files /dev/null and b/examples/rookery/preview/guidelines-pages.jpg differ diff --git a/examples/rookery/preview/letterhead.jpg b/examples/rookery/preview/letterhead.jpg new file mode 100644 index 0000000..bbee86f Binary files /dev/null and b/examples/rookery/preview/letterhead.jpg differ diff --git a/examples/rookery/preview/logo-versions.jpg b/examples/rookery/preview/logo-versions.jpg new file mode 100644 index 0000000..541c6cf Binary files /dev/null and b/examples/rookery/preview/logo-versions.jpg differ diff --git a/examples/rookery/preview/merch.jpg b/examples/rookery/preview/merch.jpg new file mode 100644 index 0000000..49846d9 Binary files /dev/null and b/examples/rookery/preview/merch.jpg differ diff --git a/examples/rookery/preview/mockups/cap-photo.jpg b/examples/rookery/preview/mockups/cap-photo.jpg new file mode 100644 index 0000000..7ae006e Binary files /dev/null and b/examples/rookery/preview/mockups/cap-photo.jpg differ diff --git a/examples/rookery/preview/mockups/hoodie-photo.jpg b/examples/rookery/preview/mockups/hoodie-photo.jpg new file mode 100644 index 0000000..4df2e64 Binary files /dev/null and b/examples/rookery/preview/mockups/hoodie-photo.jpg differ diff --git a/examples/rookery/preview/mockups/jersey-illustration.jpg b/examples/rookery/preview/mockups/jersey-illustration.jpg new file mode 100644 index 0000000..7f6856d Binary files /dev/null and b/examples/rookery/preview/mockups/jersey-illustration.jpg differ diff --git a/examples/rookery/preview/mockups/mousemat-photo.jpg b/examples/rookery/preview/mockups/mousemat-photo.jpg new file mode 100644 index 0000000..ffbc183 Binary files /dev/null and b/examples/rookery/preview/mockups/mousemat-photo.jpg differ diff --git a/examples/rookery/preview/mockups/sticker-sheet-illustration.jpg b/examples/rookery/preview/mockups/sticker-sheet-illustration.jpg new file mode 100644 index 0000000..0abc440 Binary files /dev/null and b/examples/rookery/preview/mockups/sticker-sheet-illustration.jpg differ diff --git a/examples/rookery/preview/mockups/tee-photo.jpg b/examples/rookery/preview/mockups/tee-photo.jpg new file mode 100644 index 0000000..500000c Binary files /dev/null and b/examples/rookery/preview/mockups/tee-photo.jpg differ diff --git a/examples/rookery/preview/rookery-brand-guidelines.pdf b/examples/rookery/preview/rookery-brand-guidelines.pdf new file mode 100644 index 0000000..96c661d Binary files /dev/null and b/examples/rookery/preview/rookery-brand-guidelines.pdf differ diff --git a/examples/rookery/preview/social-banner.jpg b/examples/rookery/preview/social-banner.jpg new file mode 100644 index 0000000..facb2f1 Binary files /dev/null and b/examples/rookery/preview/social-banner.jpg differ diff --git a/skills/brand-studio/SKILL.md b/skills/brand-studio/SKILL.md index b00e9cf..11da56c 100644 --- a/skills/brand-studio/SKILL.md +++ b/skills/brand-studio/SKILL.md @@ -96,7 +96,7 @@ picks. Skip the pause only if they said not to check in. `--sym-scale/--gap/--word-width` by eye, render, keep the numbers. Colour the final files with palette hexes. 5. Favicon legibility: a dark mark vanishes on dark browser tabs. Give the favicon its own source with a light backing disc (`logo.favicon_source`) and set `logo.app_icon` to `{"bg": paper, "fg": "keep"}` so the app icon keeps the colour mark on a light tile (the test flags the failure; fix it, don't just report it). 6. Fill `final/` and `brand.json` (`templates/brand.example.json`), add 1–2 misuse drawings only this mark can suffer. -6. `build_kit.py brand.json --out deliver` (≈2 min; stages independent). Add `--photo-mockups` for photographic previews: it downloads the sector's free PSD mockups from mockups-design.com on demand (user-approved; cached in `~/.cache/brand-studio/mockups`, never redistributed, previews only) and places the logo in them with `psd_mockup.py` (mug, tee, sweatshirt, apron, card, signboard; adds ~5 min the first time). Always compare with the mockup's own JPG; if a PSD cannot be filled cleanly say so and keep the flat mockups. **Open and look at**: `guidelines/pages/*.png`, +6. `build_kit.py brand.json --out deliver` (≈2 min; stages independent). **Merch is chosen for the business, not generic**: set `business_type` (and, for unusual brands, an explicit `merch` list) from `merch_catalog.py` — a coffee roaster gets a bean bag, travel mug and apron; a gaming community a jersey, mouse mat and hoodie; a tech company a business card, USB stick, cable, lanyard and laptop sleeve; an illustrator a sticker sheet, cards, tote and tee (`references/merch-catalogue.md`). Add `--photo-mockups` for photographic previews: it downloads the free PSD mockups for those items from mockups-design.com on demand (user-approved; cached in `~/.cache/brand-studio/mockups`, never redistributed, previews only) and places the logo in them with `psd_mockup.py` (~5 min the first time). Items with no PSD page get a drawn illustration; the guidelines "In use" pages show only the real mockup files, labelled photographic or illustration. Always compare with the mockup's own JPG; if a PSD cannot be filled cleanly say so and keep the illustration. **Open and look at**: `guidelines/pages/*.png`, `favicons/favicon-test.png` + report, `mockups/*-merch-overview.png`, one banner, the letterhead PNG, one PDF. 7. **Independent review of the kit** with the review agent (colour, type, favicon sheet, mockups, guideline pages). Fix, rebuild. 8. Present: where the files are, the favicon test result (say what it does not cover), review outcome, and the @@ -147,10 +147,11 @@ existing logo (the library is for learning, never tracing). | `identity-system.md` · `bi-tokens-export.md` | system, tokens | | `critique.md` · `bi-critique.md` · `redesign.md` | critique/refresh modes | | `review-agent.md` | the independent review | +| `merch-catalogue.md` | choosing merch items, adding PSD sources | | `live-sources.md` · `library-guide.md` · `examples.md` | APIs/sites; library; worked examples (`assets/examples/`) | ## 9. Script cheat-sheet `search_library.py` · `palette/search_palettes.py` · `live_sources.py` · `outline_text.py` · `svg_audit.py` · `preview_sheet.py` · `concept_sheet.py` · `render_png.py` · `export_variants.py` · `compose_lockup.py` · `review_pack.py` · `palette/palette_build.py` · `palette/palette_audit.py` · `build_kit.py` (calls `favicon_test.py`, `collateral.py`, `merch.py`, `guidelines.py`) -· `psd_mockup.py` (optional photo mockups; `--set`, `--page`, `--psd`) · `presentation_board.py` (extra 6-mockup client board per concept, `--list-mockups`). Each has `--help`. +· `merch_catalog.py` (business type → items) · `psd_mockup.py` (optional photo mockups; `--set`, `--item`, `--psd`) · `check_setup.py` · `presentation_board.py` (extra 6-mockup client board per concept, `--list-mockups`). Each has `--help`. diff --git a/skills/brand-studio/references/merch-catalogue.md b/skills/brand-studio/references/merch-catalogue.md new file mode 100644 index 0000000..b0c43ee --- /dev/null +++ b/skills/brand-studio/references/merch-catalogue.md @@ -0,0 +1,41 @@ +# Merchandise: choose items the brand would really make + +Merch mockups exist to judge the logo *in use*, so the items must be things this kind of business would plausibly produce, not a +generic mug-and-shirt set. `scripts/merch_catalog.py` holds the catalogue; `brand.json` selects from it. + +## How items are chosen +1. Set `business_type` in brand.json (free word; aliases map it: `cafe`→coffee, `esports`→gaming, `illustrator`→artist, + `fintech`→finance, `wishlist`→retail...). If absent, `industry` is used; unknown → `general`. +2. The business type gives an ordered list (first 6–8 used). Examples: + - **coffee**: coffee bean bag, travel mug, takeaway cup, mug, apron, tote, tee, cap + - **gaming**: team jersey, mouse mat, hoodie, tee, cap, sticker sheet, lanyard, keyring + - **tech / saas**: business card, USB stick, charging cable, lanyard, phone case, laptop sleeve, tee, sticker sheet + - **artist**: sticker sheet, business card, tee, tote, notebook, poster, pin badge + - also fashion, fitness, finance, services, health, beauty, event, music, education, community, retail, trades, kids, pets, bakery, bar, food +3. **Override when the brand is unusual**: set `"merch": ["item", ...]` using keys from `merch_catalog.ITEMS`. Think about who the + customer is and what they would actually hold, wear or have on their desk (a climbing gym: chalk bag is not in the catalogue, + so pick the nearest: tote + bottle + tee, and say so). Do not pad the list: 6 good items beat 12 generic ones. + +## Where each mockup comes from (in this order) +1. **Photographic** (`--photo-mockups`): the free PSD from mockups-design.com for that item (`ITEMS[...][1]` is the page slug), + downloaded on demand into `~/.cache/brand-studio/mockups`, logo placed in the smart-object layer by `psd_mockup.py`. +2. **Illustration**: a flat vector scene drawn by `merch.py` for items with no PSD page (jersey, lanyard, phone case, cable, + travel mug, sticker sheet...) or when the PSD cannot be filled cleanly. +3. Never invent an item that has neither: leave it out and say so. + +`mockups/manifest.json` lists every real mockup file (`kind: photo | illustration`); the guidelines "In use" pages are built from it, +so the guideline PDF only ever shows files that exist in the kit and labels each one. + +## Adding items or sources +- New item: add a row to `ITEMS` (label, mockups-design page slug or `None`, logo form, scale, cylinder degrees) and, if there is no + PSD page, a scene function in `merch.py` (`SCENES`). +- New PSD: run `psd_mockup.py brand.json --psd file.psd --out out.png --item `; check against the mockup's own JPG; tune `scale` / + `cylinder` in the catalogue. PSD layouts vary: the script looks for a smart object named Design (or Your design / Logo), hides + "delete this layer" slides, maps the artboard onto the smart object's transform quad and clips with its mask. +- Unblast (unblast.com) hosts many more mockups (lanyards, jerseys, phone cases, USB cards, tumblers, coffee packaging) but each is + third-party with its own licence and a JavaScript download step: download by hand, read the licence on the page, then use `--psd`. + +## Licences (preview use) +mockups-design.com: free for any purpose incl. commercial, no attribution required, but do not redistribute the PSD files; sharing a +flattened finished image is allowed. Keep PSDs in the cache folder, never in a deliverable or repository. Credit the site in any +public write-up (see the repository README). diff --git a/skills/brand-studio/scripts/check_setup.py b/skills/brand-studio/scripts/check_setup.py new file mode 100644 index 0000000..f0abcee --- /dev/null +++ b/skills/brand-studio/scripts/check_setup.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 +"""Check that this machine can run brand-studio: Python, uv, a Chromium-based browser, optional packages, network. + + python scripts/check_setup.py # prints PASS / WARN / FAIL lines; exit code 1 only on a FAIL + python scripts/check_setup.py --offline + +FAIL = the skill cannot work. WARN = a feature is limited (the line says which and how to fix it). +""" +import argparse +import importlib.util +import os +import shutil +import sys +import urllib.request + +HERE = os.path.dirname(os.path.abspath(__file__)) +sys.path.insert(0, HERE) + + +def line(level, msg, fix=""): + print(f"{level:<5} {msg}" + (f"\n fix: {fix}" if fix and level != "PASS" else "")) + return level == "FAIL" + + +def main(): + ap = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter) + ap.add_argument("--offline", action="store_true") + a = ap.parse_args() + bad = False + v = sys.version_info + bad |= line("PASS" if v >= (3, 9) else "FAIL", f"Python {v.major}.{v.minor}.{v.micro}", "install Python 3.9 or newer") + uv = shutil.which("uv") + line("PASS" if uv else "WARN", "uv " + ("found" if uv else "not found (needed to auto-install Pillow, pypdf, fonttools, psd-tools)"), + "" if uv else "Windows: powershell -c \"irm https://astral.sh/uv/install.ps1 | iex\" macOS/Linux: curl -LsSf https://astral.sh/uv/install.sh | sh (or, without uv: pip install pillow pypdf fonttools uharfbuzz pymupdf; add \"psd-tools[composite]\" numpy scipy scikit-image for --photo-mockups)") + try: + import render_png + chrome = render_png.find_chrome() + except Exception: + chrome = None + bad |= line("PASS" if chrome else "FAIL", "Chromium-based browser " + (chrome if chrome else "not found (renders every PNG/PDF)"), + "" if chrome else "install Chrome, Edge, Brave or Chromium") + for mod, pkg, why in (("PIL", "pillow", "PNG/JPG output"), ("pypdf", "pypdf", "PDF output"), ("fontTools", "fonttools", "wordmark outlining"), + ("uharfbuzz", "uharfbuzz", "wordmark kerning"), ("psd_tools", "psd-tools[composite]", "optional photographic mockups"), + ("fitz", "pymupdf", "guideline page PNGs")): + have = importlib.util.find_spec(mod) is not None or (mod == "fitz" and importlib.util.find_spec("pymupdf") is not None) + line("PASS" if have else "INFO", f"{pkg} {'installed' if have else 'not installed (' + why + '; installed on demand through uv)'}") + if not a.offline: + for name, url in (("Google Fonts", "https://fonts.googleapis.com/css2?family=Figtree"), ("Fontsource API", "https://api.fontsource.org/v1/fonts/figtree"), + ("mockups-design.com (optional photo mockups)", "https://mockups-design.com/")): + try: + urllib.request.urlopen(urllib.request.Request(url, headers={"User-Agent": "curl/8"}), timeout=15).read(100) + line("PASS", f"network: {name}") + except Exception as exc: + line("WARN", f"network: {name} unreachable ({exc})", "outlining fonts and photo mockups need internet; the rest works offline") + print("\n" + ("Setup has a blocking problem." if bad else "Ready.")) + sys.exit(1 if bad else 0) + + +if __name__ == "__main__": + main() diff --git a/skills/brand-studio/scripts/guidelines.py b/skills/brand-studio/scripts/guidelines.py index 5fce5e1..ae98031 100644 --- a/skills/brand-studio/scripts/guidelines.py +++ b/skills/brand-studio/scripts/guidelines.py @@ -247,8 +247,24 @@ def exists(*parts): def img_uri(path): + """data: URI for a raster file. Large images (mockup photos, banners) are re-encoded as JPEG <= 1600 px so the PDF stays small.""" import base64 + import io ext = os.path.splitext(path)[1].lower().lstrip(".") + if ext in ("png", "jpg", "jpeg") and os.path.getsize(path) > 300_000: + from PIL import Image + im = Image.open(path) + if im.mode in ("RGBA", "LA", "P"): + im = im.convert("RGBA") + bg = Image.new("RGB", im.size, "white") + bg.paste(im, mask=im.split()[3]) + im = bg + else: + im = im.convert("RGB") + im.thumbnail((1600, 1600)) + buf = io.BytesIO() + im.save(buf, "JPEG", quality=82, optimize=True) + return "data:image/jpeg;base64," + base64.b64encode(buf.getvalue()).decode("ascii") mime = {"jpg": "jpeg", "svg": "svg+xml"}.get(ext, ext) return f"data:image/{mime};base64," + base64.b64encode(open(path, "rb").read()).decode("ascii") diff --git a/skills/brand-studio/scripts/kitlib.py b/skills/brand-studio/scripts/kitlib.py index e0575ca..f0e7bf5 100644 --- a/skills/brand-studio/scripts/kitlib.py +++ b/skills/brand-studio/scripts/kitlib.py @@ -403,7 +403,7 @@ def pick_variant(variants, ground): reach 2:1 and at least one reaches 3:1 against it (accents may be lighter than the main colour); else the best.""" for n in ("colour-light", "colour-dark"): cs = [contrast(c, ground) for c in (used_colors(variants[n]) or ["#000000"])] - if min(cs) >= 1.5 and max(cs) >= 3.0: + if min(cs) >= 1.2 and max(cs) >= 3.0: return variants[n], n n = "white" if contrast("#ffffff", ground) >= contrast("#000000", ground) else "black" return variants[n], n diff --git a/skills/brand-studio/scripts/merch_catalog.py b/skills/brand-studio/scripts/merch_catalog.py index a97295d..873b648 100644 --- a/skills/brand-studio/scripts/merch_catalog.py +++ b/skills/brand-studio/scripts/merch_catalog.py @@ -50,6 +50,15 @@ "coaster": ("Coaster", "free-round-coaster-mockup", "symbol", 0.6, 0), } +# placement tweaks learned from checking each PSD against its own preview: dx/dy are fractions of the design area +# (dy > 0 moves down), form/scale override the ITEMS defaults. Everything else uses ITEMS. +ADJUST = { + "hoodie": {"form": "symbol", "scale": 0.1, "dx": 0.2, "dy": -0.1}, # left chest, clear of the drawstrings + "tote": {"scale": 0.36, "dy": 0.22}, # below the handles + "coffee-cup": {"scale": 0.55}, + "mousemat": {"scale": 0.35}, +} + BUSINESS_TYPES = { "coffee": ["coffee-bag", "travel-mug", "coffee-cup", "mug", "apron", "tote", "tee", "cap"], "food": ["apron", "paper-bag", "coffee-cup", "box", "tote", "label", "tee", "cap"], @@ -125,4 +134,6 @@ def page_url(item): def spec(item): label, slug, form, scale, cyl = ITEMS[item] - return {"label": label, "page": page_url(item), "form": form, "scale": scale, "cylinder": cyl} + s = {"label": label, "page": page_url(item), "form": form, "scale": scale, "cylinder": cyl, "dx": 0.0, "dy": 0.0} + s.update(ADJUST.get(item, {})) + return s diff --git a/skills/brand-studio/scripts/psd_mockup.py b/skills/brand-studio/scripts/psd_mockup.py index e03fe0c..8223d0c 100644 --- a/skills/brand-studio/scripts/psd_mockup.py +++ b/skills/brand-studio/scripts/psd_mockup.py @@ -90,18 +90,18 @@ def find_psds(folder): return sorted(os.path.join(d, f) for d, _, fs in os.walk(folder) for f in fs if f.lower().endswith(".psd")) -def find_design_layer(psd): - best = None - for l in psd.descendants(): - if l.kind == "smartobject" and l.visible and l.name.lower() in ("design", "your design", "logo", "your logo", "artwork"): - best = l - break - if best is None: - for l in psd.descendants(): - if l.kind == "smartobject" and l.visible: - best = l - break - return best +DESIGN_NAMES = re.compile(r"design|project|logo|artwork|print|mouse ?pad|your|label|cover|front|place", re.I) +# whole words only: "lace" (shoe-lace layers) must not match inside "Place your design here" +SKIP_NAMES = re.compile(r"\b(laces?|colou?rs?|shadows?|backgrounds?|highlights?|textures?|masks?|base|delete)\b", re.I) + + +def find_design_layers(psd): + """Every visible smart object that carries the printed design (a cup PSD has one per cup; a desk scene may also have a laptop screen). + A layer whose name says design/logo/artwork wins over the skip list.""" + strong = re.compile(r"design|logo|artwork|project|mouse ?pad|your", re.I) + cand = [l for l in psd.descendants() if l.kind == "smartobject" and l.visible and (strong.search(l.name) or not SKIP_NAMES.search(l.name))] + named = [l for l in cand if DESIGN_NAMES.search(l.name)] + return named or cand[:1] def cylinder_map(img, deg): @@ -119,108 +119,104 @@ def cylinder_map(img, deg): def build(brand, psd_path, out, variant=None, cylinder=None, scale=None, preset=None, show_ref=True, form=None): - from PIL import Image + from PIL import Image, ImageChops from psd_tools import PSDImage from psd_tools.api.layers import PixelLayer + import numpy as np import render_png psd = PSDImage.open(psd_path) for l in psd.descendants(): # optimisation slides the authors ask you to delete if re.search(r"delete|read me|instruction", l.name, re.I) and l.kind in ("pixel", "type", "smartobject"): l.visible = False - layer = find_design_layer(psd) - if layer is None: + layers = find_design_layers(psd) + if not layers: print("No smart-object design layer found. Layers:") for l in psd.descendants(): print(f" {l.kind:12} {l.name!r} visible={l.visible}") raise SystemExit(2) - so = layer.smart_object - tb = so.transform_box - xs, ys = tb[0::2], tb[1::2] - box = (min(xs), min(ys), max(xs), max(ys)) - bounds = so.warp.get(b"bounds", {}) - sw, sh = int(bounds.get(b"Rght", box[2] - box[0])), int(bounds.get(b"Btom", box[3] - box[1])) - if preset in merch_catalog.ITEMS: - sp = merch_catalog.spec(preset) - pre = {"cylinder": sp["cylinder"], "scale": sp["scale"]} - form = form or sp["form"] - else: - pre = PRESETS["default"] - cyl = pre["cylinder"] if cylinder is None else cylinder - sc = pre["scale"] if scale is None else scale + sp = merch_catalog.spec(preset) if preset in merch_catalog.ITEMS else {"cylinder": 0, "scale": 0.6, "form": None, "dx": 0.0, "dy": 0.0} + form = form or sp["form"] + cyl = sp["cylinder"] if cylinder is None else cylinder + sc = sp["scale"] if scale is None else scale - # colour of the item under the design area (hide design, composite, sample) - layer.visible = False - base = psd.composite(force=True).convert("RGB") - cx, cy = int((layer.bbox[0] + layer.bbox[2]) / 2), int((layer.bbox[1] + layer.bbox[3]) / 2) - r, g, b = base.getpixel((cx, cy)) - ground = kitlib.to_hex(r, g, b) + for l in layers: + l.visible = False + base = psd.composite(force=True).convert("RGB") # the item without any design: used to pick the logo version - # artboard with the logo vs = None - order = [form] if form else [] - for form_ in order + ["horizontal", "vertical", "symbol"]: - p = kitlib.logo_path(brand, form_) - if p and os.path.exists(p): - vs = kitlib.variants_of(kitlib.tight_viewbox(kitlib.read(p)), {**brand["logo"], **brand["colors"]}) + for form_ in ([form] if form else []) + ["horizontal", "vertical", "symbol"]: + pth = kitlib.logo_path(brand, form_) + if pth and os.path.exists(pth): + vs = kitlib.variants_of(kitlib.tight_viewbox(kitlib.read(pth)), {**brand["logo"], **brand["colors"]}) break if vs is None: raise SystemExit("error: no logo files in brand.json") - raw, vname = kitlib.pick_variant(vs, ground) - g_ = kitlib.geometry(raw) - # the smart object is usually stretched into a box of a different shape than its own canvas: pre-compensate so the - # logo keeps its proportions on the item (desired size is measured in the box, converted back to canvas units) - import math as _m - qd = lambda a, b: _m.hypot(tb[2 * b] - tb[2 * a], tb[2 * b + 1] - tb[2 * a + 1]) - bwq, bhq = (qd(0, 1) + qd(3, 2)) / 2, (qd(0, 3) + qd(1, 2)) / 2 - fx, fy = sw / bwq, sh / bhq # canvas units per box pixel - wd = sc * bwq - hd = wd * g_["h"] / g_["w"] - if hd > bhq * 0.7: - hd = bhq * 0.7 - wd = hd * g_["w"] / g_["h"] - lw, lh = max(2, int(wd * fx)), max(2, int(hd * fy)) - with tempfile.TemporaryDirectory() as tmp: - svgp = os.path.join(tmp, "l.svg") - open(svgp, "w", encoding="utf-8").write(kitlib.fit_attrs(raw)) - lp = os.path.join(tmp, "l.png") - nat_h = max(2, int(lw * g_["h"] / g_["w"])) - render_png.render(svgp, lp, lw, nat_h) - logo = Image.open(lp).convert("RGBA").resize((lw, lh), Image.LANCZOS) # deliberate stretch: the smart object is squeezed back into its box - art = Image.new("RGBA", (sw, sh), (0, 0, 0, 0)) - art.alpha_composite(logo, ((sw - lw) // 2, (sh - lh) // 2)) - if cyl: - art = cylinder_map(art, cyl) - # map the artboard onto the smart object's transform quad (handles rotation and perspective) - import numpy as np - q = [(tb[0], tb[1]), (tb[2], tb[3]), (tb[4], tb[5]), (tb[6], tb[7])] - src = [(0, 0), (sw, 0), (sw, sh), (0, sh)] - A, B = [], [] - for (x, y), (u, v) in zip(q, src): - A.append([x, y, 1, 0, 0, 0, -u * x, -u * y]); B.append(u) - A.append([0, 0, 0, x, y, 1, -v * x, -v * y]); B.append(v) - coef = np.linalg.solve(np.array(A, float), np.array(B, float)) - canvas = art.transform(psd.size, Image.PERSPECTIVE, coef.tolist(), Image.BICUBIC) - # clip with the smart object's own layer mask when it has one (not its placeholder pixels, which can be sparse) - try: - if layer.has_mask(): - from PIL import ImageChops - m = layer.mask.topil() - full = Image.new("L", psd.size, 0) - full.paste(m, (layer.mask.left, layer.mask.top)) - canvas.putalpha(ImageChops.multiply(canvas.split()[3], full)) - except Exception: - pass - parent = layer.parent - idx = list(parent).index(layer) - newl = PixelLayer.frompil(canvas, psd, name="Brand design", top=0, left=0) - parent.insert(idx + 1, newl) if hasattr(parent, "insert") else parent.append(newl) + + notes = [] + for layer in layers: + so = layer.smart_object + tb = so.transform_box + bounds = so.warp.get(b"bounds", {}) + xs, ys = tb[0::2], tb[1::2] + sw = int(bounds.get(b"Rght", max(xs) - min(xs))) + sh = int(bounds.get(b"Btom", max(ys) - min(ys))) + x0, y0, x1, y1 = (max(0, layer.bbox[0]), max(0, layer.bbox[1]), min(psd.size[0], layer.bbox[2]), min(psd.size[1], layer.bbox[3])) + if x1 - x0 < 4 or y1 - y0 < 4: + x0, y0, x1, y1 = 0, 0, psd.size[0], psd.size[1] + reg = base.crop((x0, y0, x1, y1)).resize((24, 24)) + arr = np.asarray(reg).reshape(-1, 3) + px = arr[np.argsort(arr.sum(axis=1))] # median of the area: shadows and creases do not decide the logo colour + r, g, b = (int(v) for v in px[len(px) // 2]) + ground = kitlib.to_hex(r, g, b) + raw, vname = kitlib.pick_variant(vs, ground) + g_ = kitlib.geometry(raw) + # the smart object is stretched into a box of another shape than its own canvas: pre-compensate so the logo keeps + # its proportions on the item (size measured in the box, converted back to canvas units) + qd = lambda i, j: math.hypot(tb[2 * j] - tb[2 * i], tb[2 * j + 1] - tb[2 * i + 1]) + bwq, bhq = max(1.0, (qd(0, 1) + qd(3, 2)) / 2), max(1.0, (qd(0, 3) + qd(1, 2)) / 2) + fx, fy = sw / bwq, sh / bhq + wd = sc * bwq + hd = wd * g_["h"] / g_["w"] + if hd > bhq * 0.7: + hd = bhq * 0.7 + wd = hd * g_["w"] / g_["h"] + lw, lh = max(2, int(wd * fx)), max(2, int(hd * fy)) + with tempfile.TemporaryDirectory() as tmp: + svgp = os.path.join(tmp, "l.svg") + open(svgp, "w", encoding="utf-8").write(kitlib.fit_attrs(raw)) + lp = os.path.join(tmp, "l.png") + render_png.render(svgp, lp, lw, max(2, int(lw * g_["h"] / g_["w"]))) + logo = Image.open(lp).convert("RGBA").resize((lw, lh), Image.LANCZOS) # deliberate stretch (see above) + art = Image.new("RGBA", (sw, sh), (0, 0, 0, 0)) + art.alpha_composite(logo, (int((sw - lw) / 2 + sp["dx"] * sw), int((sh - lh) / 2 + sp["dy"] * sh))) + if cyl: + art = cylinder_map(art, cyl) + q = [(tb[0], tb[1]), (tb[2], tb[3]), (tb[4], tb[5]), (tb[6], tb[7])] + src = [(0, 0), (sw, 0), (sw, sh), (0, sh)] + A, B = [], [] + for (x, y), (u, v) in zip(q, src): + A.append([x, y, 1, 0, 0, 0, -u * x, -u * y]); B.append(u) + A.append([0, 0, 0, x, y, 1, -v * x, -v * y]); B.append(v) + coef = np.linalg.solve(np.array(A, float), np.array(B, float)) + canvas = art.transform(psd.size, Image.PERSPECTIVE, coef.tolist(), Image.BICUBIC) + try: # clip with the smart object's own mask when it has one (not its placeholder pixels, which can be sparse) + if layer.has_mask(): + m_ = layer.mask.topil() + full = Image.new("L", psd.size, 0) + full.paste(m_, (layer.mask.left, layer.mask.top)) + canvas.putalpha(ImageChops.multiply(canvas.split()[3], full)) + except Exception: + pass + parent = layer.parent + idx = list(parent).index(layer) + newl = PixelLayer.frompil(canvas, psd, name="Brand design", top=0, left=0) + parent.insert(idx + 1, newl) if hasattr(parent, "insert") else parent.append(newl) + notes.append(f"{layer.name}: {vname} on {ground}") result = psd.composite(force=True).convert("RGB") os.makedirs(os.path.dirname(os.path.abspath(out)), exist_ok=True) result.save(out) - # also write a contact image next to the mockup's own preview JPG when present - note = f"logo version {vname} on item colour {ground}; cylinder {cyl}°, width {sc:.2f}" - return out, note + return out, "; ".join(notes) + f"; cylinder {cyl} deg, width {sc:.2f}" def build_set(brand, out_dir, items=None): diff --git a/skills/brand-studio/templates/brand.example.json b/skills/brand-studio/templates/brand.example.json index 5494bb2..3a614db 100644 --- a/skills/brand-studio/templates/brand.example.json +++ b/skills/brand-studio/templates/brand.example.json @@ -3,6 +3,7 @@ "slug": "kiln", "tagline": "Small-batch coffee, roasted in Istanbul", "industry": "coffee", + "business_type": "coffee", "adjectives": ["warm", "crafted", "modern"], "mechanism": "The arched mouth of a kiln, with one ember inside: the place where the coffee is made.", "rationale": "One sentence of why this answers the brief. Only claims you can stand behind; no invented stats.", @@ -26,6 +27,6 @@ "contact": {"address": "12 Roaster Lane, Istanbul", "phone": "+90 212 000 0000", "email": "hello@kiln.example", "web": "kiln.example"}, "contact_name": "Name Surname", "contact_role": "Head Roaster", - "merch": ["mug", "tote", "apron", "tee", "cap", "sticker"], + "merch": ["coffee-bag", "coffee-cup", "mug", "travel-mug", "apron", "tote"], "misuse_extra": [{"svg": "final/misuse-1.svg", "label": "Don't close the arch"}] }