Formato do pacote
Esta é a referência que a skill de templates entrega ao seu assistente de IA. Você só precisa dela para escrever ou corrigir um pacote à mão. Ela fica em inglês porque é o texto que o assistente lê.
This is the whole format lookmybio reads. When we import a pack we check it against these rules; anything the importer removes is listed in our reply.
Files
manifest.json required: what the pack is, and which template draws which slidesettings.json optional: choices the creator makes for the deck or for one slidestyle.css optional: shared by every template*.html the templates, at the top of the pack (lowercase, a-z 0-9 _ -, .html)assets/… optional pictures (png jpg gif webp svg) and fonts (woff woff2 ttf otf)Zip limits: 5 MB zipped, 20 MB unzipped, 200 files, 512 KB per text file, 4 MB per asset. A single root folder in the zip is fine. Dotfiles and __MACOSX are skipped. A file the manifest does not name is dropped with a warning.
manifest.json
{ "format": 1, "id": "my-pack", "name": "My pack", "version": "1.0.0", "description": "One line, shown in the look picker and to the outline writer.", "author": "Your name or studio", "license": "CC-BY-4.0", "aspects": ["3:4", "4:5", "9:16"], "fonts": ["Anton", "Inter Tight"], "templates": { "cover": [{ "file": "cover.html", "description": "Photo cover, big condensed headline" }], "picture": [{ "file": "picture.html", "description": "Photo on top, words below", "when": { "hasPicture": true } }], "list": [{ "file": "list.html", "description": "Headline over lines" }], "cta": [{ "file": "cta.html", "description": "The ask" }], "content": [{ "file": "content.html", "description": "Any other slide" }] }}id: lowercase letters, digits and hyphens, 2–48 characters.version:x.y.z. A new version for every change, because the importer refuses a version it already holds.aspects: any of3:4(1080×1440),4:5(1080×1350) and9:16(1080×1920). Square decks keep the built-in looks.fonts: up to 4 Google Fonts families. They load with weights 400, 600, 700, 800 and 900. A font setting adds its family too.templateskeys: a slide kind, a family, orcontent.cover,ctaandcontentare required, each with at least one variant withoutwhen.- How a template is chosen for a slide: its own kind, then its family, then
content. Within a key, the first variant whosewhenholds wins. when(every condition given must hold):hasPicture(true or false)minPoints/maxPoints(the number of list lines)aspects(a list of aspects)
Slide kinds, families and word budgets
The outline writer keeps each part within these word counts. Budgets are at 3:4; the most a part may hold is ×0.88 at 4:5 and ×1.2 at 9:16. The check deck draws both the fewest and the most.
| Kind | Family | Shows (required; optional) | Words at 3:4 (fewest–most) |
|---|---|---|---|
cover |
— | headline, visual; kicker | kicker 0–12; headline 3–9 |
photo |
picture |
headline, body, visual | headline 5–14; body 20–60 |
essay |
— | body; footnote | body 25–70; footnote 0–20 |
serif_photo |
picture |
headline, body, visual | headline 6–20; body 12–40 |
quoted_fact |
quote |
quote, visual; body | quote 8–30; body 0–30 |
arrow_list |
list |
headline, points; footnote | headline 4–12; footnote 0–25; points 3–5 lines of 2–16 |
check_list |
list |
headline, points; visual | headline 4–12; points 3–6 lines of 2–14 |
cta |
— | headline; body | headline 3–12; body 0–30 |
numbered_list |
list |
headline, points; footnote | headline 4–12; footnote 0–20; points 3–5 lines of 2–14 |
versus |
compare |
headline, sides, points | headline 3–10; sides 2–6; points 4–6 lines of 1–8 |
before_after |
compare |
headline, points; sides | headline 3–10; sides 0–6; points 2–6 lines of 2–12 |
stat |
numbers |
stat, headline; kicker, body, footnote | kicker 0–8; stat 1–3; headline 3–14; body 0–30; footnote 0–16 |
stats_grid |
numbers |
headline, points; footnote | headline 3–10; footnote 0–16; points 2–4 lines of 2–8 |
pull_quote |
quote |
quote; footnote | quote 6–36; footnote 0–10 |
steps |
list |
headline, points; footnote | headline 3–10; footnote 0–20; points 3–5 lines of 3–16 |
proof_card |
— | drawn by content.html (packs cannot show its proof data yet) |
essay has no family, so content.html draws it. Make content.html work as a body-only page.
Placeholders
Logic-less, Mustache-style. Every value is escaped where it lands, and there is no raw output.
{{name}}prints a value.{{#name}}…{{/name}}renders when the value is set or true, once per item of a list. Inside it, an item’s fields are plain names ({{text}}).{{^name}}…{{/name}}renders when the value is missing or empty.{{set.<id>}}prints a setting’s value.
Placeholders are filled only in text and in alt, title, aria-label and data-* attributes. One in a style, a URL, a tag name or the stylesheet is dropped and reported.
| Name | What it is |
|---|---|
kicker, headline, body, quote, footnote |
The slide’s words. ==word== in them becomes <mark>word</mark>; style mark. |
stat |
The big number of a stat slide. |
points |
A list. Each item has text (with marks), value and label (the two sides of value | label, for number grids), ok ("true", "false" or empty), and number (01, 02…). |
leftPoints, rightPoints |
The points split by ok (false on the left), for versus and before_after. |
left, right |
The two side names (“Antes”/“Depois” or “A”/“B” when unwritten). |
hasPoints, hasPicture, hasLogo, isFirst, isLast |
Flags for sections. |
index, total, number |
The slide’s place: 1-based, the deck size, and the index as 01. |
kind, lang |
The slide kind and the deck language (pt or en). |
handle, headerLabel |
The profile handle (without @) and the Brand Kit’s header label. |
cta |
The call-to-action lines, each with text. |
credit |
“Foto: …” for a picture we did not make. Show it small when it is set. |
Pictures
<img data-slot="…" alt=""> is filled by the app. Never write a src, except to the pack’s own assets/… files.
picture: the slide’s photo.inset: the same photo, for a smaller frame.logo: the Brand Kit logo.set.<id>: an image setting.
A slot with nothing to show gets data-empty. Hide it with img[data-empty]{display:none}.
Settings (settings.json)
{ "settings": [ { "id": "logo", "label": "Logo on every page", "type": "toggle", "default": false, "scope": "deck" }, { "id": "accent", "label": "Highlight colour", "type": "color", "default": "#FF4A1C", "scope": "slide", "brand": "highlight" }] }- Types:
toggle,select(withoptions[{value, label}]; values are slugs),color(hex),font(a Google Fonts family),text(maxLengthup to 80),image. scope:deck(the default) orslide.brand: one oflogo,brand,secondary,highlight,font-headingorfont-body. The Brand Kit value stands in until the creator picks one.- At most 16 settings.
- A value is read in this order: the slide (slide-scoped only), the deck, the creator’s saved choice, the Brand Kit, then
default. - The slide root carries every value as
data-set-<id>="…"(style with.slide[data-set-logo="true"] …). - Values also arrive as CSS variables:
- toggles:
--set-<id>: 1|0 - selects:
--set-<id>: <value> - colours:
--set-<id>, plus--set-<id>-on-lightand--set-<id>-on-dark - fonts:
--set-<id>as a font stack
- toggles:
The page
Each slide is <div class="slide" data-pack-slide …>, sized to the aspect, with the template inside it. Style it with these attributes:
data-kind: the slide kind.data-template: the template key that drew it.data-aspectdata-parity:evenorodd, so light and dark pages can take turns.data-has-picturedata-set-<id>: one per setting.
CSS variables on :root:
| Variable | What it is |
|---|---|
--paper, --background |
The brand’s light page colour. |
--ink, --text |
The brand’s text colour, near black. |
--tint |
A pale wash of a brand colour. |
--brand, --secondary, --spot |
Brand colours at full strength. Use them for shapes, not for words. |
--highlight |
The highlight colour as the brand set it. |
--on-brand |
Text that reads on --brand. |
--highlight-on-light, --highlight-on-dark, --brand-on-light, --brand-on-dark |
The colour moved just far enough to hold 3:1 on light pages (paper, tint, white) or on dark pages (ink, black). Use these for coloured words. |
--font-heading, --font-body |
The brand’s fonts, as stacks. |
--safe-top, --safe-bottom |
250px on 9:16, 0 otherwise. Keep words out of them. |
--slide-width, --slide-height |
The slide’s size in px. |
The slide’s own style also has these variables:
--index: 1-based.--total--progress: 0–100, for a progress bar.--fit: 1, stepping down to 0.5 while the words in adata-fitelement do not fit their box. Size text withcalc(<px> * var(--fit,1)).
What the importer removes
-
Templates. Only these tags are kept:
- text:
div span p h1–h6 ul ol li blockquote figure figcaption header footer section article main aside strong em b i u s small sup sub mark br hr img - inline SVG
Attributes are limited to
class id role title style data-* aria-*, plusaltandsrconimgand the SVG presentation attributes. The importer drops scripts,on*handlers, links, forms, iframes,<style>and<link>. - text:
-
Styles and stylesheet.
- At-rules: only
@media,@supports,@keyframesand@font-face(withsrctoassets/). url()only to the pack’s ownassets/files or to#fragments.- Never
@import,expression(),javascript:,image-set()or-moz-binding. Escapes are decoded before this check.
- At-rules: only
-
Assets. Each must be the type its name says: the importer checks the bytes. SVG files are sanitized the same way.
The slide page also has its own Content-Security-Policy. Only the app’s fit and check scripts can run, pictures load only over https or as data, and nothing can be sent anywhere. Anything the sanitizer missed still cannot run.