From 3d9301d239626aeed18a129d3e81bd1e676ca632 Mon Sep 17 00:00:00 2001 From: Silent Mode Date: Mon, 21 Sep 2026 00:48:35 +0200 Subject: [PATCH] feat(studio): twelve more starting points so a name is not stuck with a landing page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The four templates covered a launch page and a link hub. Everyone else — a writer, a restaurant, a shop, a project that ships releases — started from Blank and rebuilt the same scaffolding by hand. These twelve cover the shapes people actually asked for, each one written to be overwritten: plain copy that reads as an instruction, no images to source, no JavaScript to keep working. Every entry now carries its own card text and filter category, and the top-bar list is generated from the map, so adding the thirteenth is one object literal and nothing else. --- js/studio.js | 651 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 650 insertions(+), 1 deletion(-) diff --git a/js/studio.js b/js/studio.js index 13d12a1..87edd06 100644 --- a/js/studio.js +++ b/js/studio.js @@ -187,9 +187,23 @@ async function importLive({ confirmIfDirty = true } = {}) { function notice(text) { $("notice-text").textContent = text; $("notice").hidden = false; } // ---------- templates ---------- +// Every entry carries its own card text: `label` and `tag` are what the +// picker shows, `cat` is the filter it answers to. The bodies are written to +// be thrown away — each line is a prompt for the owner to overwrite — so they +// deliberately have no translation entries; the studio's chrome does. +// +// Class names are prefixed per template (.pf-, .bi-, .rs-, …) so a template +// and any sx-* section dropped on top of it never fight over a selector. +// Palettes rotate light-neutral / dark-neutral / warm / acid so the gallery +// never shows four of the same page in a row. const TEMPLATES = { - blank: { html: `

${esc(name)}

Start building.

`, css: `body{font-family:system-ui,sans-serif;margin:0;color:#111}` }, + blank: { + label: "Blank page", tag: "Start from nothing.", cat: "special", + html: `

${esc(name)}

Start building.

`, + css: `body{font-family:system-ui,sans-serif;margin:0;color:#111}`, + }, landing: { + label: "Landing page", tag: "Hero, three features, call to action.", cat: "landing", html: `

Hello from ${esc(name)}

@@ -215,6 +229,7 @@ body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;col .foot{text-align:center;padding:28px;color:#6a7488;font-size:13px;border-top:1px solid #e6e9f0}`, }, profile: { + label: "Profile / link hub", tag: "Avatar, bio and a stack of links.", cat: "special", html: `
★
@@ -235,6 +250,7 @@ h1{margin:0 0 6px;font-size:26px} .link:hover{border-color:#d6ff3d}`, }, business: { + label: "Business one-pager", tag: "About, services, hours, contact.", cat: "business", html: `

We are open

Say what you do in one sentence.

@@ -257,6 +273,626 @@ body{margin:0;font-family:Georgia,serif;color:#2b1d12;background:#fff8f0} .grid b{display:block;margin-bottom:6px} .foot{text-align:center;padding:24px;color:#8a6d55;font-size:13px}`, }, + + // --- light neutral --- + portfolio: { + label: "Portfolio", tag: "A grid of work, one line about you.", cat: "landing", + html: ` +
+
+ ${esc(name)} + +
+
+
+

I design things that
hold up under use.

+

Two sentences on what you make and who you make it for. Leave out the adjectives you would not say out loud.

+
+
+

Project one

What it was, what you did, what changed.

+

Project two

What it was, what you did, what changed.

+

Project three

What it was, what you did, what changed.

+

Project four

What it was, what you did, what changed.

+
+
+

About

+

Where you are, what you use, what you are looking for next. A working email beats a contact form.

+ hello@example +
+
© ${new Date().getFullYear()} ${esc(name)}
`, + css: ` +body{margin:0;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;color:#15181d;background:#fafafa;line-height:1.6} +.pf-top{border-bottom:1px solid #e6e7ea;background:#fff} +.pf-in{max-width:1040px;margin:0 auto;padding:18px 24px;display:flex;justify-content:space-between;align-items:center} +.pf-in b{font-size:16px;letter-spacing:-.01em} +.pf-in a{margin-left:20px;color:#5a6069;text-decoration:none;font-size:14px} +.pf-in a:hover{color:#15181d} +.pf-hero{max-width:1040px;margin:0 auto;padding:88px 24px 56px} +.pf-hero h1{font-size:52px;line-height:1.08;letter-spacing:-.025em;margin:0 0 20px;font-weight:600} +.pf-hero p{max-width:560px;color:#5a6069;font-size:18px;margin:0} +.pf-work{max-width:1040px;margin:0 auto;padding:0 24px 64px;display:grid;grid-template-columns:repeat(auto-fit,minmax(300px,1fr));gap:36px 28px} +.pf-shot{aspect-ratio:4/3;border-radius:12px;background:linear-gradient(135deg,#eceef1,#dfe2e7);margin-bottom:16px} +.pf-item h3{margin:0 0 6px;font-size:18px;font-weight:600} +.pf-item p{margin:0;color:#5a6069;font-size:15px} +.pf-about{border-top:1px solid #e6e7ea;background:#fff} +.pf-about h2{font-size:15px;text-transform:uppercase;letter-spacing:.12em;color:#8b9099;margin:0 0 14px} +.pf-about,.pf-about>*{max-width:1040px;margin-left:auto;margin-right:auto} +.pf-about{padding:56px 24px} +.pf-about p{max-width:620px;margin:0 0 18px;font-size:17px} +.pf-mail{color:#15181d;font-weight:600;border-bottom:2px solid #15181d;text-decoration:none;padding-bottom:1px} +.pf-foot{max-width:1040px;margin:0 auto;padding:28px 24px;color:#8b9099;font-size:13px} +@media(max-width:600px){.pf-hero h1{font-size:34px}.pf-in nav a{margin-left:12px}}`, + }, + "blog-post": { + label: "Blog post", tag: "One article — title, byline, body, replies.", cat: "blog", + html: ` +
${esc(name)}Archive
+
+

Essays

+

The title goes here, and it can run to two lines

+

By an author · ${new Date().toLocaleDateString("en-GB", { day: "numeric", month: "long", year: "numeric" })} · 6 min

+

The opening paragraph does the work of a subtitle. Say what the reader gets if they stay.

+

A normal paragraph. Long-form type wants a measure of around 70 characters and generous leading — that is what the CSS below is doing, and it is the one thing worth keeping when you rewrite this.

+

A section heading

+

Another paragraph. Links look like this, and a phrase can be emphasised or made strong without changing the rhythm of the line.

+
A pulled quote earns its indent when it is someone else's sentence, not a louder version of your own.
+

Close on something concrete. What changed, what you would do differently, where the reader goes next.

+
+
+

Replies

+

No replies yet.

+
+
© ${new Date().getFullYear()} ${esc(name)}
`, + css: ` +body{margin:0;background:#fffefb;color:#1b1a17;font-family:Georgia,'Times New Roman',serif;line-height:1.7} +.bp-top{display:flex;gap:20px;max-width:720px;margin:0 auto;padding:22px 24px;font-family:system-ui,sans-serif;font-size:14px} +.bp-top a{color:#6f6a60;text-decoration:none} +.bp-top a:first-child{font-weight:600;color:#1b1a17} +.bp{max-width:680px;margin:0 auto;padding:20px 24px 56px} +.bp-kicker{font-family:system-ui,sans-serif;font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:#b5561f;margin:0 0 14px} +.bp h1{font-size:42px;line-height:1.15;letter-spacing:-.015em;margin:0 0 16px} +.bp-meta{font-family:system-ui,sans-serif;font-size:14px;color:#8a8579;margin:0 0 32px} +.bp-lead{font-size:21px;color:#3d3a34;margin:0 0 28px} +.bp p{font-size:18px;margin:0 0 24px} +.bp h2{font-size:26px;margin:40px 0 14px;letter-spacing:-.01em} +.bp a{color:#b5561f} +.bp blockquote{margin:32px 0;padding:4px 0 4px 24px;border-left:3px solid #e6dfd2;color:#57524a;font-style:italic;font-size:19px} +.bp-replies{max-width:680px;margin:0 auto;padding:32px 24px;border-top:1px solid #e6dfd2} +.bp-replies h2{font-family:system-ui,sans-serif;font-size:14px;letter-spacing:.1em;text-transform:uppercase;color:#8a8579;margin:0 0 12px} +.bp-none{color:#8a8579;font-size:16px;margin:0} +.bp-foot{max-width:680px;margin:0 auto;padding:24px;color:#a8a294;font-size:13px;font-family:system-ui,sans-serif} +@media(max-width:600px){.bp h1{font-size:30px}.bp-lead{font-size:18px}}`, + }, + resume: { + label: "Résumé", tag: "One page: skills, history, a way to reach you.", cat: "special", + html: ` +
+
+

Your Name

What you do · City

+

hello@example
${esc(name)}

+
+
+

Summary

+

Three lines at most. What you build, how long you have been doing it, and the kind of problem you want next.

+
+
+

Skills

+
  • One
  • Two
  • Three
  • Four
  • Five
  • Six
+
+
+

Experience

+
RoleCompany · 2024 — now

What you owned and what measurably changed because of it.

+
RoleCompany · 2021 — 2024

What you owned and what measurably changed because of it.

+
RoleCompany · 2018 — 2021

What you owned and what measurably changed because of it.

+
+
+

Education

+
DegreeInstitution · 2018
+
+

Ctrl/Cmd + P prints this page straight to a PDF — the print rules below drop the shadow and the margins.

+
`, + css: ` +body{margin:0;background:#f4f5f7;color:#15181d;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.6} +.cv{max-width:760px;margin:40px auto;background:#fff;padding:48px 52px;border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,.08)} +.cv-head{display:flex;justify-content:space-between;align-items:flex-start;gap:20px;padding-bottom:24px;border-bottom:2px solid #15181d;margin-bottom:8px} +.cv-head h1{margin:0;font-size:32px;letter-spacing:-.02em} +.cv-role{margin:4px 0 0;color:#5a6069} +.cv-reach{margin:0;text-align:right;font-size:14px;line-height:1.7} +.cv-reach a{color:#15181d} +.cv-sec{padding:24px 0;border-bottom:1px solid #eceef1} +.cv-sec h2{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:#8b9099;margin:0 0 14px} +.cv-sec>p{margin:0;max-width:60ch} +.cv-tags{list-style:none;display:flex;flex-wrap:wrap;gap:8px;padding:0;margin:0} +.cv-tags li{background:#f0f1f4;border-radius:6px;padding:5px 11px;font-size:14px} +.cv-row{margin-bottom:18px} +.cv-row:last-child{margin-bottom:0} +.cv-row b{font-size:16px} +.cv-row span{display:block;color:#8b9099;font-size:14px;margin-bottom:5px} +.cv-row p{margin:0;color:#41464e;max-width:62ch} +.cv-print{margin:24px 0 0;font-size:14px;color:#8b9099} +@media print{body{background:#fff}.cv{box-shadow:none;margin:0;padding:0}.cv-print{display:none}} +@media(max-width:620px){.cv{margin:0;padding:28px 22px}.cv-head{flex-direction:column}.cv-reach{text-align:left}}`, + }, + + // --- dark neutral --- + "blog-index": { + label: "Blog", tag: "A list of posts with tags down the side.", cat: "blog", + html: ` +
+
${esc(name)}
+
+
+
+

The most recent post

One or two sentences of the opening, enough to decide whether to click.

+ +

A shorter note

One or two sentences of the opening, enough to decide whether to click.

+ +
+ +
+
© ${new Date().getFullYear()} ${esc(name)} · no trackers, no newsletter pop-up
`, + css: ` +body{margin:0;background:#0d1015;color:#e3e6eb;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.65} +a{color:#e3e6eb} +.bi-top{border-bottom:1px solid #1f242c} +.bi-in{max-width:980px;margin:0 auto;padding:20px 24px;display:flex;justify-content:space-between;align-items:center} +.bi-in b{font-size:16px} +.bi-in a{margin-left:20px;color:#8d96a5;text-decoration:none;font-size:14px} +.bi-in a:hover{color:#fff} +.bi-body{max-width:980px;margin:0 auto;padding:48px 24px;display:grid;grid-template-columns:1fr 220px;gap:56px;align-items:start} +.bi-post{padding-bottom:30px;margin-bottom:30px;border-bottom:1px solid #1f242c} +.bi-post:last-child{border:0;margin:0;padding:0} +.bi-post time{font-size:13px;color:#6d7787;letter-spacing:.02em} +.bi-post h2{margin:6px 0 8px;font-size:24px;letter-spacing:-.015em;line-height:1.25} +.bi-post h2 a{text-decoration:none} +.bi-post h2 a:hover{color:#8ab4ff} +.bi-post p{margin:0;color:#98a1b0} +.bi-side h3{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:#6d7787;margin:0 0 12px} +.bi-side h3+ul+h3{margin-top:28px} +.bi-tags{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:7px} +.bi-tags a{display:inline-block;background:#161b22;border:1px solid #232933;border-radius:6px;padding:4px 10px;font-size:13px;color:#98a1b0;text-decoration:none} +.bi-tags a:hover{border-color:#3a434f;color:#fff} +.bi-foot{border-top:1px solid #1f242c;padding:24px;text-align:center;color:#6d7787;font-size:13px} +@media(max-width:760px){.bi-body{grid-template-columns:1fr;gap:40px}}`, + }, + docs: { + label: "Documentation", tag: "Sidebar contents, one long article.", cat: "special", + html: ` +
${esc(name)} docs
+
+ +
+

Install

+

One paragraph saying what the reader is about to do and how long it takes. Then the command.

+
curl -fsSL https://${esc(name)}/install.sh | sh
+

Configure

+

What to edit and where it lives. Say what the defaults are so most readers can stop here.

+ +
KeyDefaultWhat it does
port8080Where it listens.
data_dir./dataWhere state is kept.
log_levelinfoHow loud it is.
+

First run

+

The happy path, end to end, with the output the reader should actually see.

+
Note Anything that will bite a reader at 2am goes in a box like this one.
+
+
`, + css: ` +body{margin:0;background:#0f1216;color:#dfe3e9;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.7} +.dc-top{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:14px 22px;border-bottom:1px solid #1d222a;background:#0b0e12;position:sticky;top:0} +.dc-top b{font-size:15px} +.dc-find{background:#151a21;border:1px solid #252b35;border-radius:8px;padding:7px 12px;color:#dfe3e9;font:inherit;font-size:13px;width:min(280px,45vw)} +.dc-body{display:grid;grid-template-columns:230px 1fr;max-width:1120px;margin:0 auto} +.dc-nav{padding:28px 18px;border-right:1px solid #1d222a;position:sticky;top:57px;align-self:start;max-height:calc(100vh - 57px);overflow:auto} +.dc-nav h4{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:#68727f;margin:22px 0 8px} +.dc-nav h4:first-child{margin-top:0} +.dc-nav a{display:block;padding:5px 10px;border-radius:7px;color:#98a1af;text-decoration:none;font-size:14px} +.dc-nav a:hover{background:#151a21;color:#fff} +.dc-nav a.on{background:#1b2230;color:#8ab4ff} +.dc-main{padding:36px 40px 80px;max-width:760px} +.dc-main h1{font-size:34px;letter-spacing:-.02em;margin:0 0 14px} +.dc-main h2{font-size:23px;letter-spacing:-.01em;margin:44px 0 12px;padding-top:12px;border-top:1px solid #1d222a} +.dc-main p{color:#aeb6c2;margin:0 0 18px} +.dc-pre{background:#0a0d11;border:1px solid #1d222a;border-radius:10px;padding:14px 16px;overflow:auto;font-size:13.5px;color:#a7e3b0} +.dc-tab{width:100%;border-collapse:collapse;font-size:14px;margin:0 0 18px} +.dc-tab th{text-align:left;color:#68727f;font-weight:600;font-size:12px;letter-spacing:.08em;text-transform:uppercase;padding:0 12px 8px 0;border-bottom:1px solid #1d222a} +.dc-tab td{padding:9px 12px 9px 0;border-bottom:1px solid #161b22;color:#aeb6c2} +.dc-note{border-left:3px solid #8ab4ff;background:#131a26;border-radius:0 8px 8px 0;padding:12px 16px;color:#aeb6c2;font-size:14.5px} +.dc-note b{color:#8ab4ff;margin-right:6px} +@media(max-width:820px){.dc-body{grid-template-columns:1fr}.dc-nav{position:static;max-height:none;border-right:0;border-bottom:1px solid #1d222a}.dc-main{padding:28px 22px 64px}}`, + }, + agency: { + label: "Agency", tag: "Case studies, services, the people behind them.", cat: "business", + html: ` +
+
+

We take the awkward half of the problem.

+

One sentence on what you do, one on who for. Resist listing technologies here — the work below does that better.

+
+
+

Selected work

+ +
+
+

What we do

+
+
Strategy

Deciding what not to build.

+
Design

Interfaces that survive a real user.

+
Engineering

Shipping it, then keeping it up.

+
Support

Being reachable after launch.

+
+
+
+

Who you would work with

+
A. PersonPartner
B. PersonDesign
C. PersonEngineering
+
+

Tell us what is stuck.

hello@example

© ${new Date().getFullYear()} ${esc(name)}

`, + css: ` +body{margin:0;background:#101114;color:#eceef2;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.6} +.ag-top{border-bottom:1px solid #1e2026} +.ag-in{max-width:1080px;margin:0 auto;padding:18px 24px;display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap} +.ag-in b{font-size:16px} +.ag-in a{margin-left:22px;color:#9aa0ad;text-decoration:none;font-size:14px} +.ag-in a:hover{color:#fff} +.ag-cta{background:#eceef2;color:#101114 !important;padding:8px 16px;border-radius:999px;font-weight:600} +.ag-hero{max-width:1080px;margin:0 auto;padding:96px 24px 72px} +.ag-hero h1{font-size:56px;line-height:1.05;letter-spacing:-.03em;margin:0 0 20px;max-width:14ch} +.ag-hero p{max-width:540px;color:#9aa0ad;font-size:18px;margin:0} +.ag-lab{font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:#6a7280;margin:0 0 24px;font-weight:600} +.ag-work,.ag-serv,.ag-team{max-width:1080px;margin:0 auto;padding:56px 24px;border-top:1px solid #1e2026} +.ag-cases{display:grid;grid-template-columns:repeat(auto-fit,minmax(280px,1fr));gap:28px} +.ag-case{text-decoration:none;color:inherit} +.ag-shot{aspect-ratio:16/10;border-radius:10px;background:linear-gradient(135deg,#1c1f26,#272b34);margin-bottom:14px} +.ag-case h3{margin:0 0 5px;font-size:18px} +.ag-case p{margin:0;color:#9aa0ad;font-size:15px} +.ag-case:hover .ag-shot{background:linear-gradient(135deg,#242832,#333844)} +.ag-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:28px} +.ag-grid b{display:block;margin-bottom:5px;font-size:17px} +.ag-grid p{margin:0;color:#9aa0ad;font-size:15px} +.ag-people{display:flex;gap:40px;flex-wrap:wrap} +.ag-face{display:block;width:72px;height:72px;border-radius:50%;background:#272b34;margin-bottom:10px} +.ag-people b{display:block;font-size:15px} +.ag-people i{color:#6a7280;font-size:13.5px;font-style:normal} +.ag-foot{border-top:1px solid #1e2026;text-align:center;padding:72px 24px 40px} +.ag-foot h2{font-size:38px;letter-spacing:-.02em;margin:0 0 24px} +.ag-cta.big{display:inline-block;margin-left:0;padding:13px 26px;font-size:16px} +.ag-foot p{color:#6a7280;font-size:13px;margin:40px 0 0} +@media(max-width:640px){.ag-hero{padding:56px 24px 40px}.ag-hero h1{font-size:36px}.ag-foot h2{font-size:26px}.ag-in nav a{margin-left:14px}}`, + }, + + // --- warm --- + restaurant: { + label: "Restaurant", tag: "Menu, hours, the address, a table.", cat: "business", + html: ` +
+

Since ${new Date().getFullYear() - 7}

+

${esc(name)}

+

Small kitchen, short menu, everything cooked the day you eat it.

+ Book a table +
+
+

Menu

+
+
+

To start

+
Bread, olive oil, salt4
+
Soup of the day7
+
Grilled vegetables, yoghurt9
+

Mains

+
Fish of the day19
+
Slow lamb, beans21
+
Mushroom orzo16
+
+
+

Sweet

+
Yoghurt, honey, walnut6
+
Chocolate, olive oil7
+

To drink

+
House red, glass5
+
House white, glass5
+
Coffee3
+
+
+

Prices include tax. Tell us about allergies when you book — the menu changes weekly.

+
+
+

Hours

Tuesday – Saturday
18:00 – 23:00
Sunday lunch 13:00 – 16:00
Closed Monday

+

Where

Street 1
City
Open in maps →

+ +
+
© ${new Date().getFullYear()} ${esc(name)}
`, + css: ` +body{margin:0;background:#fdf6ec;color:#3a2a1c;font-family:Georgia,'Times New Roman',serif;line-height:1.65} +.rs-hero{text-align:center;padding:88px 24px 72px;background:#5c2f16;color:#fdf6ec} +.rs-kick{letter-spacing:.24em;text-transform:uppercase;font-size:11px;margin:0 0 16px;color:#d9a86c;font-family:system-ui,sans-serif} +.rs-hero h1{font-size:54px;margin:0 0 14px;letter-spacing:.01em;font-weight:400} +.rs-sub{max-width:460px;margin:0 auto 28px;color:#e8cfb3;font-size:17px} +.rs-btn{display:inline-block;background:#d9a86c;color:#3a2a1c;padding:12px 26px;border-radius:2px;text-decoration:none;font-family:system-ui,sans-serif;font-weight:600;font-size:14px;letter-spacing:.04em} +.rs-btn.small{padding:9px 18px;font-size:13px;margin-bottom:8px} +.rs-menu{max-width:860px;margin:0 auto;padding:64px 24px 48px} +.rs-menu h2{text-align:center;font-size:13px;letter-spacing:.2em;text-transform:uppercase;color:#9a7550;font-family:system-ui,sans-serif;margin:0 0 36px;font-weight:600} +.rs-cols{display:grid;grid-template-columns:1fr 1fr;gap:20px 56px} +.rs-cols h3{font-size:20px;font-weight:400;margin:28px 0 12px;font-style:italic;color:#5c2f16} +.rs-cols h3:first-child{margin-top:0} +.rs-item{display:flex;justify-content:space-between;align-items:baseline;gap:12px;padding:6px 0;border-bottom:1px dotted #d8c3a8} +.rs-item b{font-weight:400;color:#9a7550} +.rs-fine{text-align:center;color:#9a7550;font-size:14px;margin:36px 0 0;font-family:system-ui,sans-serif} +.rs-when{max-width:860px;margin:0 auto;padding:40px 24px 64px;display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:36px;border-top:1px solid #e6d5bf} +.rs-when h3{font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:#9a7550;font-family:system-ui,sans-serif;margin:0 0 10px} +.rs-when p{margin:0} +.rs-when a{color:#5c2f16} +.rs-foot{text-align:center;padding:24px;background:#5c2f16;color:#c9a883;font-size:13px;font-family:system-ui,sans-serif} +@media(max-width:620px){.rs-hero h1{font-size:38px}.rs-cols{grid-template-columns:1fr;gap:0}}`, + }, + event: { + label: "Event", tag: "Date, venue, agenda, speakers, RSVP.", cat: "business", + html: ` +
+

14 November ${new Date().getFullYear()} · City

+

A one-day thing
worth travelling for

+

Eight talks, one room, no parallel tracks. Lunch is included and the coffee is good.

+ Reserve a seat +

62 of 120 seats left

+
+
+

Agenda

+
Doors and coffee

Come early, the good seats go first.

+
Opening talk

Speaker name — the title of the talk.

+
Second talk

Speaker name — the title of the talk.

+
Lunch

Included. Say what you cannot eat when you RSVP.

+
Workshops

Three rooms, pick one on the day.

+
Close and drinks

Around the corner, on us.

+
+
+

Speakers

+
A. PersonWhat they work on
B. PersonWhat they work on
C. PersonWhat they work on
D. PersonWhat they work on
+
+
+

RSVP

+
+ + + + +
+

This form needs somewhere to post to. Until you set one up, put an email address here instead.

+
+
${esc(name)} · Venue, Street 1, City · © ${new Date().getFullYear()}
`, + css: ` +body{margin:0;background:#fff9f2;color:#2f2418;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.6} +.ev-top{text-align:center;padding:80px 24px 64px;background:linear-gradient(160deg,#c2410c,#7c2d12);color:#fff4e8} +.ev-date{letter-spacing:.18em;text-transform:uppercase;font-size:12px;margin:0 0 18px;color:#fdba74} +.ev-top h1{font-size:50px;line-height:1.08;letter-spacing:-.02em;margin:0 0 18px;font-weight:700} +.ev-sub{max-width:520px;margin:0 auto 30px;color:#fed7aa;font-size:17px} +.ev-btn{display:inline-block;background:#fff4e8;color:#7c2d12;padding:13px 28px;border-radius:10px;text-decoration:none;font-weight:700;border:0;font:inherit;font-weight:700;cursor:pointer} +.ev-left{margin:14px 0 0;font-size:13px;color:#fdba74} +.ev-sec{max-width:760px;margin:0 auto;padding:56px 24px} +.ev-sec.alt{max-width:none;background:#fdefe0} +.ev-sec.alt>*{max-width:760px;margin-left:auto;margin-right:auto} +.ev-sec h2{font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:#a16207;margin:0 0 24px} +.ev-line{display:grid;grid-template-columns:78px 1fr;gap:18px;padding:14px 0;border-top:1px solid #f0dcc6} +.ev-line time{color:#c2410c;font-weight:700;font-size:15px;font-variant-numeric:tabular-nums} +.ev-line b{display:block;font-size:16px} +.ev-line p{margin:2px 0 0;color:#6b5844;font-size:15px} +.ev-spk{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:28px} +.ev-face{display:block;width:76px;height:76px;border-radius:50%;background:#f3ddc4;margin-bottom:10px} +.ev-spk b{display:block;font-size:15px} +.ev-spk i{font-style:normal;color:#8a7358;font-size:13.5px} +.ev-form{display:grid;gap:10px;max-width:420px} +.ev-form input{padding:12px 14px;border:1px solid #e6d3ba;border-radius:10px;font:inherit;background:#fff} +.ev-form input:focus{outline:2px solid #c2410c;outline-offset:1px} +.ev-form .ev-btn{background:#c2410c;color:#fff4e8;justify-self:start} +.ev-fine{color:#8a7358;font-size:13.5px;margin:14px 0 0;max-width:420px} +.ev-foot{text-align:center;padding:26px;background:#7c2d12;color:#fdba74;font-size:13px} +@media(max-width:620px){.ev-top h1{font-size:34px}.ev-line{grid-template-columns:64px 1fr;gap:12px}}`, + }, + newsletter: { + label: "Newsletter", tag: "One promise, one field, the back issues.", cat: "landing", + html: ` +
+
+

${esc(name)}

+

One letter a week about the thing you actually care about.

+

Say what is in it and how often it lands. Then say what you will never do with the address — people read that line.

+
+ + +
+

No tracking pixels. Unsubscribe from the bottom of any issue.

+
+
+

Past issues

+ #014 — The title of the issue12 September ${new Date().getFullYear()}

The one-line summary that makes the archive worth scrolling.

+ #013 — Another title05 September ${new Date().getFullYear()}

The one-line summary that makes the archive worth scrolling.

+ #012 — And another29 August ${new Date().getFullYear()}

The one-line summary that makes the archive worth scrolling.

+
+
© ${new Date().getFullYear()} ${esc(name)} · write back
+
`, + css: ` +body{margin:0;background:#fbf3e9;color:#2e261c;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.65} +.nl{max-width:620px;margin:0 auto;padding:0 24px} +.nl-head{padding:88px 0 56px} +.nl-kick{font-family:Georgia,serif;font-style:italic;color:#a8743a;margin:0 0 20px;font-size:17px} +.nl-head h1{font-size:40px;line-height:1.18;letter-spacing:-.02em;margin:0 0 20px;font-weight:700} +.nl-sub{color:#6d5d49;font-size:17px;margin:0 0 28px} +.nl-form{display:flex;gap:8px;flex-wrap:wrap} +.nl-form input{flex:1;min-width:200px;padding:14px 16px;border:1px solid #ddc9ab;border-radius:10px;font:inherit;background:#fff} +.nl-form input:focus{outline:2px solid #a8743a;outline-offset:1px} +.nl-form button{padding:14px 24px;border:0;border-radius:10px;background:#2e261c;color:#fbf3e9;font:inherit;font-weight:600;cursor:pointer} +.nl-form button:hover{background:#4a3d2d} +.nl-fine{color:#8b7c66;font-size:13.5px;margin:14px 0 0} +.nl-past{padding:8px 0 48px;border-top:1px solid #e8d8c0} +.nl-past h2{font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:#a08a6c;margin:32px 0 18px} +.nl-item{display:block;text-decoration:none;color:inherit;padding:16px 0;border-bottom:1px solid #eee1cd} +.nl-item b{display:block;font-size:17px;margin-bottom:2px} +.nl-item span{display:block;font-size:13px;color:#a08a6c;margin-bottom:6px} +.nl-item p{margin:0;color:#6d5d49;font-size:15px} +.nl-item:hover b{color:#a8743a} +.nl-foot{padding:28px 0 40px;color:#a08a6c;font-size:13px} +.nl-foot a{color:#a8743a} +@media(max-width:560px){.nl-head{padding:56px 0 40px}.nl-head h1{font-size:30px}}`, + }, + + // --- acid --- + "shop-lite": { + label: "Small shop", tag: "A few products, paid to your own address.", cat: "business", + html: ` +
${esc(name)}Paid in Bitcoin Cash · straight to your wallet
+

Four things worth making.

Say what you sell and why you make it. One honest paragraph beats a carousel.

+
+

Product one

What it is, what it is made of, how big it is.

0.05 BCHPay
+

Product two

What it is, what it is made of, how big it is.

0.08 BCHPay
+

Product three

What it is, what it is made of, how big it is.

0.12 BCHPay
+

Product four

What it is, what it is made of, how big it is.

0.20 BCHPay
+
+
+

How ordering works

+
  1. Tap Pay — your wallet opens with the address and amount filled in.
  2. Send the payment, then email the transaction id and where it should go.
  3. It ships within three working days, tracked.
+

Put your real cashaddr in each Pay link (bitcoincash:q…?amount=0.05) and a real address to email. No checkout server, no card fees, no chargebacks — and no refunds unless you offer them, so say what you do.

+
+`, + css: ` +body{margin:0;background:#0a0c08;color:#eef3e4;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.6} +.sh-top{display:flex;justify-content:space-between;align-items:center;gap:14px;flex-wrap:wrap;padding:16px 26px;border-bottom:1px solid #1d2417} +.sh-top b{font-size:16px} +.sh-pay{font-size:12.5px;color:#c6ff4a;letter-spacing:.02em} +.sh-hero{max-width:900px;margin:0 auto;padding:72px 24px 44px} +.sh-hero h1{font-size:46px;letter-spacing:-.025em;line-height:1.08;margin:0 0 16px} +.sh-hero p{max-width:520px;color:#9caa8c;font-size:17px;margin:0} +.sh-grid{max-width:900px;margin:0 auto;padding:0 24px 56px;display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:22px} +.sh-card{background:#11150d;border:1px solid #1d2417;border-radius:14px;padding:16px} +.sh-img{aspect-ratio:1;border-radius:10px;background:linear-gradient(135deg,#1a2012,#242c19);margin-bottom:14px} +.sh-card h3{margin:0 0 5px;font-size:17px} +.sh-card p{margin:0 0 14px;color:#9caa8c;font-size:14.5px} +.sh-buy{display:flex;justify-content:space-between;align-items:center;gap:10px} +.sh-buy b{color:#c6ff4a;font-size:15px;font-variant-numeric:tabular-nums} +.sh-btn{background:#c6ff4a;color:#0a0c08;text-decoration:none;font-weight:700;font-size:13.5px;padding:8px 16px;border-radius:8px} +.sh-btn:hover{background:#d9ff7e} +.sh-how{max-width:900px;margin:0 auto;padding:40px 24px 64px;border-top:1px solid #1d2417} +.sh-how h2{font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:#6f7d60;margin:0 0 18px} +.sh-how ol{margin:0 0 20px;padding-left:20px;color:#c3cdb7;max-width:62ch} +.sh-how li{margin-bottom:7px} +.sh-note{color:#7f8d70;font-size:14px;margin:0;max-width:66ch} +.sh-note code{background:#11150d;border:1px solid #1d2417;border-radius:5px;padding:1px 6px;font-size:12.5px;color:#c6ff4a} +.sh-foot{padding:24px;text-align:center;color:#6f7d60;font-size:13px;border-top:1px solid #1d2417} +.sh-foot a{color:#9caa8c} +@media(max-width:560px){.sh-hero{padding:48px 24px 32px}.sh-hero h1{font-size:32px}}`, + }, + "coming-soon": { + label: "Coming soon", tag: "A date, a way to be told, nothing else.", cat: "landing", + html: ` +
+

${esc(name)}

+

Something is being built here.

+

One sentence on what it is. One on when. Vagueness reads as vapour, so give a real month.

+
+
14days
+
06hours
+
32minutes
+
09seconds
+
+

Opening 14 November ${new Date().getFullYear()} — edit these numbers by hand, or drop in the Countdown widget from the Widgets panel to make them run.

+
+ + +
+

or follow along: Nostr · Mastodon · Email

+
+
© ${new Date().getFullYear()} ${esc(name)}
`, + css: ` +body{margin:0;min-height:100vh;display:flex;flex-direction:column;background:#070a04;color:#e9f2dc;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.6;background-image:radial-gradient(circle at 50% 0,rgba(198,255,74,.12),transparent 60%)} +.cs{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;padding:72px 24px 48px} +.cs-kick{font-family:ui-monospace,Menlo,monospace;letter-spacing:.2em;text-transform:uppercase;font-size:12px;color:#c6ff4a;margin:0 0 24px} +.cs h1{font-size:46px;line-height:1.1;letter-spacing:-.025em;margin:0 0 16px;max-width:16ch} +.cs-sub{max-width:480px;color:#93a184;font-size:17px;margin:0 0 40px} +.cs-clock{display:flex;gap:14px;flex-wrap:wrap;justify-content:center;margin-bottom:18px} +.cs-clock div{background:rgba(198,255,74,.07);border:1px solid rgba(198,255,74,.22);border-radius:12px;padding:16px 20px;min-width:84px} +.cs-clock b{display:block;font-size:34px;font-variant-numeric:tabular-nums;color:#c6ff4a;line-height:1.1} +.cs-clock span{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:#7c8a6d} +.cs-when{color:#7c8a6d;font-size:13.5px;max-width:52ch;margin:0 0 40px} +.cs-form{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;width:min(420px,100%)} +.cs-form input{flex:1;min-width:190px;padding:13px 16px;border-radius:10px;border:1px solid rgba(255,255,255,.14);background:#0d1208;color:#e9f2dc;font:inherit} +.cs-form input:focus{outline:2px solid #c6ff4a;outline-offset:1px} +.cs-form button{padding:13px 22px;border:0;border-radius:10px;background:#c6ff4a;color:#070a04;font:inherit;font-weight:700;cursor:pointer} +.cs-or{margin:22px 0 0;color:#7c8a6d;font-size:14px} +.cs-or a{color:#c6ff4a;text-decoration:none} +.cs-or a:hover{text-decoration:underline} +.cs-foot{text-align:center;padding:20px;color:#5d6a50;font-size:12.5px} +@media(max-width:520px){.cs h1{font-size:32px}.cs-clock div{padding:12px 14px;min-width:68px}.cs-clock b{font-size:26px}}`, + }, + changelog: { + label: "Changelog", tag: "What shipped, when, and what broke.", cat: "special", + html: ` +
+
${esc(name)}
+
+
+

Changelog

+

Every release, newest first. Dates are the day the build went out, not the day the work started.

+
+
+
+
0.4.0
+
+

addedchanged

+
  • The thing people kept asking for, in one line.
  • Another thing, phrased as what the user can now do.
  • A setting moved. Say where it went.
+
+
+
+
0.3.2
+
+

fixed

+
  • The crash on the thing. Say what triggered it — people want to know if it was them.
  • A slow query that is no longer slow.
+
+
+
+
0.3.0
+
+

addedbreaking

+
  • The new capability, in the user's words.
  • Breaking: what you have to change before upgrading, and what happens if you do not.
+
+
+
+`, + css: ` +body{margin:0;background:#08090a;color:#e8ecef;font-family:system-ui,-apple-system,Segoe UI,Roboto,sans-serif;line-height:1.65} +.cl-top{border-bottom:1px solid #191c1f} +.cl-in{max-width:820px;margin:0 auto;padding:18px 24px;display:flex;justify-content:space-between;align-items:center} +.cl-in b{font-size:15px} +.cl-in a{margin-left:20px;color:#7e8792;text-decoration:none;font-size:14px} +.cl-in a:hover{color:#fff} +.cl-intro{max-width:820px;margin:0 auto;padding:56px 24px 32px} +.cl-intro h1{font-size:38px;letter-spacing:-.025em;margin:0 0 10px} +.cl-intro p{margin:0;color:#8b949e;max-width:56ch} +.cl{max-width:820px;margin:0 auto;padding:0 24px 40px} +.cl-rel{display:grid;grid-template-columns:130px 1fr;gap:28px;padding:28px 0;border-top:1px solid #191c1f} +.cl-ver b{display:block;font-size:19px;font-variant-numeric:tabular-nums;color:#d4ff4f} +.cl-ver time{display:block;color:#6e7681;font-size:13px;margin-top:3px} +.cl-tags{margin:0 0 10px;display:flex;gap:6px;flex-wrap:wrap} +.t{font-size:11px;letter-spacing:.08em;text-transform:uppercase;font-weight:600;padding:3px 9px;border-radius:999px;border:1px solid} +.t.add{color:#d4ff4f;border-color:rgba(212,255,79,.35);background:rgba(212,255,79,.08)} +.t.fix{color:#7ee3b0;border-color:rgba(126,227,176,.35);background:rgba(126,227,176,.08)} +.t.chg{color:#8ab4ff;border-color:rgba(138,180,255,.35);background:rgba(138,180,255,.08)} +.t.brk{color:#ff8fa3;border-color:rgba(255,143,163,.35);background:rgba(255,143,163,.08)} +.cl-body ul{margin:0;padding-left:20px;color:#b6bec7} +.cl-body li{margin-bottom:7px} +.cl-body b{color:#ff8fa3} +.cl-foot{border-top:1px solid #191c1f;padding:24px;text-align:center;color:#6e7681;font-size:13px} +@media(max-width:620px){.cl-rel{grid-template-columns:1fr;gap:10px}.cl-ver{display:flex;align-items:baseline;gap:12px}.cl-ver time{margin:0}}`, + }, }; // ---------- editor ---------- @@ -526,6 +1162,19 @@ $("picker").addEventListener("click", (e) => { const b = e.target.closest("[data-tpl]"); if (!b) return; loadTemplate(b.dataset.tpl); $("picker").hidden = true; status("Template loaded — edit, then Publish"); }); +// The template list in the top bar is generated from TEMPLATES, so adding a +// template is a one-place change. +(function fillTemplateSelect() { + const sel = $("tpl-select"); + const first = sel.options[0]; // "Templates…" — keep the node, i18n owns its text + sel.innerHTML = ""; + sel.appendChild(first); + for (const [key, t] of Object.entries(TEMPLATES)) { + const o = document.createElement("option"); + o.value = key; o.textContent = t.label || key; + sel.appendChild(o); + } +})(); $("tpl-select").addEventListener("change", (e) => { const v = e.target.value; e.target.value = ""; if (!v) return;