Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,7 @@ small sizes. The editable [social card](branding/social-card.html) accepts
`temporal-contract`, `tools`, `theme`). Render at 1200 × 630 with device scale
factor 1 after its fonts and images load. Exports live under
`apps/website/public/og-*.png`; project repositories carry local copies.

The default website card uses the approved framework PNG at a larger scale,
with the homepage headline and shared wordmark. Keep that composition distinct
from the individual project cards, and check it at thumbnail size when editing.
4 changes: 2 additions & 2 deletions apps/website/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default defineConfig({
"meta",
{
property: "og:image:alt",
content: "BtravStack — type-safe building blocks for the TypeScript backend",
content: "BtravStack — A backend that fits together. A smiling beetroot sits on three teal layers.",
},
],

Expand All @@ -60,7 +60,7 @@ export default defineConfig({
"meta",
{
name: "twitter:image:alt",
content: "BtravStack — type-safe building blocks for the TypeScript backend",
content: "BtravStack — A backend that fits together. A smiling beetroot sits on three teal layers.",
},
],

Expand Down
Binary file modified apps/website/public/og-btravstack.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
38 changes: 31 additions & 7 deletions branding/social-card.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
<title>btravstack brand card</title>
<link rel="stylesheet" href="../packages/theme/src/fonts.css">
<style>
/* Hallmark · component: social card · theme: Beetroot Stack
* Static artwork; interactive states do not apply.
* Pre-emit critique: P5 H5 E4 S5 R5 V4
*/
:root { --paper:#0f1014; --ink:#f3f1f5; --muted:#b9b4c0; --rule:#323039; --accent:#e875ab; --display:'Geist',sans-serif; --mono:'JetBrains Mono',monospace; }
* { box-sizing:border-box; }
body { margin:0; width:1200px; height:630px; background:var(--paper); color:var(--ink); font-family:var(--display); }
Expand All @@ -15,15 +19,29 @@
p { max-width:690px; margin:0; font-size:29px; line-height:1.5; color:var(--muted); }
.mark { position:absolute; width:230px; height:230px; right:68px; top:177px; }
footer { position:absolute; bottom:48px; left:68px; right:68px; border-top:1px solid var(--rule); padding-top:22px; display:flex; justify-content:space-between; font:16px var(--mono); color:var(--muted); }
.website-card { padding:54px 64px; overflow:hidden; }
.website-wordmark { position:relative; z-index:1; font-size:38px; font-weight:800; letter-spacing:-1.8px; }
.website-wordmark span { color:var(--accent); }
.website-card h1 { position:relative; z-index:1; margin:56px 0 23px; max-width:700px; font-size:88px; line-height:1.02; letter-spacing:-4.4px; }
.website-card h1 span { color:var(--accent); }
.website-card p { position:relative; z-index:1; font-size:24px; line-height:1.45; }
.website-mascot { position:absolute; width:610px; height:610px; top:10px; right:-48px; }
.website-address { position:absolute; left:64px; bottom:44px; font:18px var(--mono); color:var(--muted); }
</style>
<template id="website-card">
<div class="website-wordmark"><span>btrav</span>stack</div>
<h1>A backend<br>that fits<br><span>together.</span></h1>
<p>A TypeScript framework.<br>Independent libraries. One coherent stack.</p>
<img class="website-mascot" src="../apps/website/public/logos/framework.png" alt="The smiling beetroot mascot sitting on three teal layers">
<div class="website-address">btravstack.github.io</div>
</template>
<main>
<div class="brand"><img src="../apps/website/public/logos/btravstack-dark.svg" alt="">btravstack</div>
<h1></h1><p></p><img class="mark" alt="">
<footer><span class="url"></span><span>TypeScript · Open source · MIT</span></footer>
</main>
<script>
const cards = {
btravstack: ['Build with confidence.', 'A TypeScript backend framework.<br>Independent libraries. One coherent stack.', 'btravstack.github.io'],
framework: ['btravstack', 'Your application, composed.<br>Your process, taken care of.', 'btravstack.github.io/btravstack'],
unthrown: ['unthrown', 'Errors you can handle.<br>Failures you can see in the type.', 'btravstack.github.io/unthrown'],
entity: ['entity', 'Your domain, declared once.<br>Validated at the boundary.', 'btravstack.github.io/entity'],
Expand All @@ -33,11 +51,17 @@ <h1></h1><p></p><img class="mark" alt="">
theme: ['btravstack theme', 'One visual language.<br>Every project, unmistakably related.', 'btravstack.github.io'],
};
const key = new URLSearchParams(location.search).get('project') || 'btravstack';
const [name, description, url] = cards[key];
document.querySelector('h1').textContent = name;
document.querySelector('p').innerHTML = description;
document.querySelector('.url').textContent = url;
document.querySelector('.mark').src = `../apps/website/public/logos/${key}-dark.svg`;
document.querySelector('.mark').alt = `${name} logo`;
if (key === 'btravstack') {
const main = document.querySelector('main');
main.className = 'website-card';
main.replaceChildren(document.querySelector('#website-card').content.cloneNode(true));
} else {
const [name, description, url] = cards[key];
document.querySelector('h1').textContent = name;
document.querySelector('p').innerHTML = description;
document.querySelector('.url').textContent = url;
document.querySelector('.mark').src = `../apps/website/public/logos/${key}-dark.svg`;
document.querySelector('.mark').alt = `${name} logo`;
}
</script>
</html>
Loading