Pular para o conteúdo

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 slide
settings.json optional: choices the creator makes for the deck or for one slide
style.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 of 3:4 (1080×1440), 4:5 (1080×1350) and 9: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.
  • templates keys: a slide kind, a family, or content. cover, cta and content are required, each with at least one variant without when.
  • How a template is chosen for a slide: its own kind, then its family, then content. Within a key, the first variant whose when holds 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 (with options [{value, label}]; values are slugs), color (hex), font (a Google Fonts family), text (maxLength up to 80), image.
  • scope: deck (the default) or slide.
  • brand: one of logo, brand, secondary, highlight, font-heading or font-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-light and --set-<id>-on-dark
    • fonts: --set-<id> as a font stack

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-aspect
  • data-parity: even or odd, so light and dark pages can take turns.
  • data-has-picture
  • data-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 a data-fit element do not fit their box. Size text with calc(<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-*, plus alt and src on img and the SVG presentation attributes. The importer drops scripts, on* handlers, links, forms, iframes, <style> and <link>.

  • Styles and stylesheet.

    • At-rules: only @media, @supports, @keyframes and @font-face (with src to assets/).
    • url() only to the pack’s own assets/ files or to #fragments.
    • Never @import, expression(), javascript:, image-set() or -moz-binding. Escapes are decoded before this check.
  • 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.