Files
pig/apps/web/tools/og-template.html
T
karti 0551e8dd6e Add link previews and icons; make PIG_INVITE_CODE actually work
Social and icons. A 1200x630 card, apple-touch-icon, and maskable PWA icons,
generated from an HTML template by a script so the mark, wordmark and tagline
cannot drift from the product. The apple-touch-icon referenced in index.html
was a 404 until now. Icons are drawn on an opaque plate with inset because iOS
rounds corners and Android may apply a circle — an edge-to-edge mark loses its
ears to that crop. og:image is absolute, which is the single most common
reason a card unfurls blank.

PIG_INVITE_CODE was a lie. Signup validates against the invites table, so
setting the variable only flipped a label in the UI — an operator would set it,
hand the code to a colleague, and watch them be rejected. It is now reconciled
into a real invite row at boot: setting it issues, changing it rotates and
revokes the predecessor, and removing it revokes. Verified all three, plus that
a restart with an unchanged code does not duplicate.

Two bugs found while doing that:

- `uses_remaining` was jsonb, so the SQL decrement could never have worked.
  Now integer. The generated migration failed because Postgres has no implicit
  jsonb->integer cast, so the USING clause is hand-written.
- Redemption keyed off `redeemedAt`, which would have made every reusable
  invite single-use — a confusing way to lock a team out. Availability now
  comes from `usesRemaining`, and redemption records who used it most recently
  without consuming it.

Sign-in gains a password option alongside the magic link, defaulting to
password since that is the daily path. PIG stores neither; both are handled by
the identity provider and PIG only ever sees the resulting token.
autocomplete is set so password managers and iOS can fill.

Verified: full migration chain applies to a fresh Postgres, the CSP hash for
the inline theme script is unchanged by the rebuild.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-12 19:43:10 -07:00

126 lines
3.7 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<!--
Source for the social preview card. Rendered to PNG by `tools/render-assets.mjs`.
Kept as HTML rather than hand-drawn in a design tool so the wordmark, the
tagline and the mark stay in sync with the product when any of them changes —
and so regenerating is one command rather than an afternoon.
1200×630 is the size Twitter/X and most link unfurlers crop to. Anything
important is kept well inside the edges, because several clients crop to
roughly 1.91:1 and Slack shows a smaller centred slice.
-->
<html>
<head>
<meta charset="utf-8" />
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
width: 1200px;
height: 630px;
display: flex;
flex-direction: column;
justify-content: center;
padding: 0 88px;
background: #ffffff;
color: #09090b;
font-family: ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Inter, sans-serif;
position: relative;
overflow: hidden;
}
/* A faint grid, suggesting racked capacity without being literal about it. */
.grid {
position: absolute;
inset: 0;
background-image:
linear-gradient(to right, rgba(9, 9, 11, 0.045) 1px, transparent 1px),
linear-gradient(to bottom, rgba(9, 9, 11, 0.045) 1px, transparent 1px);
background-size: 48px 48px;
mask-image: radial-gradient(ellipse 80% 70% at 70% 40%, #000 20%, transparent 75%);
}
.row { display: flex; align-items: center; gap: 22px; position: relative; }
.mark { width: 92px; height: 92px; flex: none; }
.wordmark {
font-size: 84px;
font-weight: 650;
letter-spacing: -0.045em;
line-height: 1;
}
.expansion {
margin-top: 30px;
font-size: 27px;
font-weight: 500;
color: #52525b;
letter-spacing: -0.01em;
position: relative;
}
h1 {
margin-top: 22px;
font-size: 46px;
font-weight: 600;
letter-spacing: -0.028em;
line-height: 1.16;
max-width: 20ch;
position: relative;
}
.footer {
position: absolute;
left: 88px;
right: 88px;
bottom: 56px;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 22px;
color: #71717a;
}
.pill {
border: 1.5px solid #e4e4e7;
border-radius: 999px;
padding: 9px 20px;
font-size: 19px;
font-weight: 500;
color: #3f3f46;
}
</style>
</head>
<body>
<div class="grid"></div>
<div class="row">
<svg class="mark" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<path d="M7.4 8.6 5.1 3.9c-.2-.5.3-1 .8-.8l5.2 2.2z" fill="#09090b" />
<path d="M24.6 8.6 26.9 3.9c.2-.5-.3-1-.8-.8l-5.2 2.2z" fill="#09090b" />
<path
d="M16 5.2c6.3 0 11.2 4.3 11.2 10.4 0 6.5-5 11.2-11.2 11.2S4.8 22.1 4.8 15.6C4.8 9.5 9.7 5.2 16 5.2z"
fill="#09090b"
/>
<ellipse cx="11.6" cy="13.4" rx="1.5" ry="1.8" fill="#fff" />
<ellipse cx="20.4" cy="13.4" rx="1.5" ry="1.8" fill="#fff" />
<rect x="11.3" y="17.6" width="9.4" height="6.2" rx="3.1" fill="#fff" />
<ellipse cx="14.2" cy="20.7" rx="1.15" ry="1.5" fill="#09090b" />
<ellipse cx="17.8" cy="20.7" rx="1.15" ry="1.5" fill="#09090b" />
</svg>
<span class="wordmark">pig</span>
</div>
<div class="expansion">Prime Intellect Growth</div>
<h1>The CRM for companies that buy compute and sell it.</h1>
<div class="footer">
<span>primeintellectgrowth.com</span>
<span class="pill">Open source · Apache 2.0</span>
</div>
</body>
</html>