mirror of
https://github.com/melgarafael/DeskcommCRM.git
synced 2026-10-02 01:28:34 +08:00
feat(brand): social preview do repositório, com a fonte versionada
O repo estava com usesCustomOpenGraphImage=false: todo link compartilhado em X, LinkedIn, WhatsApp, Slack ou Discord saía com a arte cinza genérica do GitHub. Para um projeto que depende de descoberta, é o conserto de menor custo e retorno mais imediato da lista. A arte usa a identidade que já existe — paleta lida de app/globals.css e as fontes da aplicação (Atkinson Hyperlegible + IBM Plex Mono). Nada de gradiente roxo ou o visual genérico que qualquer gerador cospe: o card tem que parecer o produto, senão quem clica chega em outro lugar. O painel direito mostra o rastro de uma demanda atravessando o sistema e terminando no follow-up. É a doutrina do sistema vivo como imagem em vez de adjetivo — 'no lead dies unseen' é o argumento do produto, não uma frase de efeito. A FONTE (og-card.html) vai versionada junto, e é o ponto: card cuja origem se perde vira arte que ninguém atualiza quando o posicionamento muda — aí ou envelhece mentindo, ou é refeito do zero com outra identidade. docs/brand/README.md traz o comando de regeração. Aplicar é manual: Settings > General > Social preview. Não há endpoint público na API do GitHub para upload dessa imagem. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KMEbgy5YWXZimXQAN7oRMm
This commit is contained in:
co-authored by
Claude Opus 5
parent
94a5202cc6
commit
59eee853ee
@@ -0,0 +1,40 @@
|
||||
# Marca
|
||||
|
||||
## Social preview (Open Graph)
|
||||
|
||||
`og-social-preview.png` — 1280×640, é a imagem que aparece quando um link do
|
||||
repositório é compartilhado no X, LinkedIn, WhatsApp, Slack ou Discord.
|
||||
|
||||
**Como aplicar:** GitHub → Settings → General → *Social preview* → Upload.
|
||||
Não existe endpoint público na API para isso; é upload pela interface.
|
||||
|
||||
**Como regerar** (depois de mudar posicionamento, chips ou paleta):
|
||||
|
||||
```bash
|
||||
# edite docs/brand/og-card.html, depois:
|
||||
node -e '
|
||||
import("@playwright/test").then(async ({ chromium }) => {
|
||||
const b = await chromium.launch();
|
||||
const p = await b.newPage({ viewport: { width: 1280, height: 640 }, deviceScaleFactor: 2 });
|
||||
await p.goto("file://" + process.cwd() + "/docs/brand/og-card.html", { waitUntil: "networkidle" });
|
||||
await p.evaluate(() => document.fonts.ready);
|
||||
await p.screenshot({ path: "docs/brand/og-social-preview.png" });
|
||||
await b.close();
|
||||
});'
|
||||
```
|
||||
|
||||
A fonte fica versionada de propósito: card cuja origem se perde vira arte que
|
||||
ninguém consegue atualizar quando o posicionamento muda — e aí ou envelhece
|
||||
mentindo, ou é refeito do zero com outra identidade.
|
||||
|
||||
## Regras da arte
|
||||
|
||||
- Paleta lida de `app/globals.css` (creme `#faf9f6`, sage `#506d48`, texto
|
||||
`#1c1a16`). O card usa a identidade real do produto, não uma criada para ele.
|
||||
- Tipografia: Atkinson Hyperlegible (títulos) + IBM Plex Mono (rótulos), as
|
||||
mesmas da aplicação.
|
||||
- O painel direito é a doutrina do sistema vivo virando imagem: o rastro que uma
|
||||
demanda deixa ao atravessar o sistema, terminando no follow-up — o mecanismo
|
||||
anti-morte. É o argumento do produto mostrado, não adjetivado.
|
||||
- Card de compartilhamento **sempre** carrega o nome do produto. Sem wordmark,
|
||||
quem vê a imagem não sabe de quem ela é.
|
||||
@@ -0,0 +1,129 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Atkinson+Hyperlegible:wght@400;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||||
<style>
|
||||
/* Paleta lida de app/globals.css — a arte usa a identidade real do produto,
|
||||
não uma inventada para o card. */
|
||||
:root {
|
||||
--bg: #faf9f6;
|
||||
--surface: #ffffff;
|
||||
--text: #1c1a16;
|
||||
--muted: #5d594f;
|
||||
--border: #e7e3da;
|
||||
--accent: #506d48;
|
||||
--accent-300: #a4ba9a;
|
||||
--accent-100: #e4ebe0;
|
||||
}
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
body {
|
||||
width: 1280px; height: 640px;
|
||||
background: var(--bg);
|
||||
font-family: "Atkinson Hyperlegible", ui-sans-serif, system-ui, sans-serif;
|
||||
color: var(--text);
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 420px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* Faixa de acento no topo — âncora de marca sem ocupar área. */
|
||||
.rule { position: absolute; top: 0; left: 0; right: 0; height: 6px; background: var(--accent); }
|
||||
|
||||
.left { padding: 74px 0 66px 78px; display: flex; flex-direction: column; justify-content: space-between; }
|
||||
|
||||
.wordmark {
|
||||
font-size: 27px; font-weight: 700; letter-spacing: -.015em; margin-bottom: 26px;
|
||||
display: inline-flex; align-items: center; gap: 11px;
|
||||
}
|
||||
.wordmark::before {
|
||||
content: ""; width: 15px; height: 15px; border-radius: 4px;
|
||||
background: var(--accent);
|
||||
}
|
||||
.eyebrow {
|
||||
font-family: "IBM Plex Mono", ui-monospace, monospace;
|
||||
font-size: 17px; letter-spacing: .14em; text-transform: uppercase;
|
||||
color: var(--muted);
|
||||
}
|
||||
h1 {
|
||||
font-size: 63px; line-height: 1.06; font-weight: 700; letter-spacing: -.022em;
|
||||
margin-top: 20px; max-width: 15ch;
|
||||
}
|
||||
h1 .accent { color: var(--accent); }
|
||||
.sub {
|
||||
margin-top: 22px; font-size: 25px; line-height: 1.42; color: var(--muted); max-width: 30ch;
|
||||
}
|
||||
|
||||
.chips { display: flex; gap: 10px; flex-wrap: wrap; }
|
||||
.chip {
|
||||
font-family: "IBM Plex Mono", ui-monospace, monospace;
|
||||
font-size: 16px; padding: 9px 15px; border-radius: 999px;
|
||||
border: 1px solid var(--border); background: var(--surface); color: var(--muted);
|
||||
}
|
||||
.chip.on { border-color: var(--accent-300); background: var(--accent-100); color: var(--accent); }
|
||||
|
||||
/* Painel direito: o "rastro" que uma demanda deixa ao atravessar o sistema.
|
||||
É a doutrina do sistema vivo virando imagem, em vez de adjetivo na copy. */
|
||||
.right { position: relative; border-left: 1px solid var(--border); background: var(--surface);
|
||||
padding: 56px; display: flex; flex-direction: column; justify-content: center; }
|
||||
.right-title { font-family: "IBM Plex Mono", ui-monospace, monospace; font-size: 14px;
|
||||
letter-spacing: .13em; text-transform: uppercase; color: var(--muted); margin-bottom: 26px; }
|
||||
.trail { display: flex; flex-direction: column; gap: 0; }
|
||||
.node { display: grid; grid-template-columns: 26px 1fr; gap: 16px; }
|
||||
.rail { display: flex; flex-direction: column; align-items: center; }
|
||||
.dot {
|
||||
width: 13px; height: 13px; border-radius: 50%;
|
||||
border: 2.5px solid var(--accent); background: var(--surface); flex: none; margin-top: 5px;
|
||||
}
|
||||
.dot.fill { background: var(--accent); }
|
||||
.line { width: 2px; flex: 1; background: var(--border); min-height: 34px; }
|
||||
.label { font-size: 19px; line-height: 1.3; padding-bottom: 12px; }
|
||||
.label small {
|
||||
display: block; font-family: "IBM Plex Mono", ui-monospace, monospace;
|
||||
font-size: 14px; color: var(--muted); margin-top: 3px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="rule"></div>
|
||||
|
||||
<div class="left">
|
||||
<div>
|
||||
<div class="wordmark">DeskcommCRM</div>
|
||||
<div class="eyebrow">open source · self-hosted · mit</div>
|
||||
<h1>The open-source AI Sales OS for <span class="accent">WhatsApp</span></h1>
|
||||
<p class="sub">AI agents that answer, qualify and move deals — on a server you own.</p>
|
||||
</div>
|
||||
<div class="chips">
|
||||
<span class="chip on">No paid tier</span>
|
||||
<span class="chip">Multi-tenant RLS</span>
|
||||
<span class="chip">One-command install</span>
|
||||
<span class="chip">2 GB VPS</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="right">
|
||||
<div class="right-title">one lead, one trail</div>
|
||||
<div class="trail">
|
||||
<div class="node">
|
||||
<div class="rail"><div class="dot fill"></div><div class="line"></div></div>
|
||||
<div class="label">Lead arrives on WhatsApp<small>inbound · 09:41</small></div>
|
||||
</div>
|
||||
<div class="node">
|
||||
<div class="rail"><div class="dot fill"></div><div class="line"></div></div>
|
||||
<div class="label">Agent qualifies and replies<small>7 guardrails · audited</small></div>
|
||||
</div>
|
||||
<div class="node">
|
||||
<div class="rail"><div class="dot fill"></div><div class="line"></div></div>
|
||||
<div class="label">Moved down the pipeline<small>activity recorded</small></div>
|
||||
</div>
|
||||
<div class="node">
|
||||
<div class="rail"><div class="dot"></div></div>
|
||||
<div class="label">Follow-up scheduled<small>no lead dies unseen</small></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 183 KiB |
Reference in New Issue
Block a user