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
Binary file added assets/og-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
<title>memex — local memory for coding agents</title>
<meta name="description" content="The local memory layer for Claude Code and Codex. Powered by Qdrant 1.18 with five named vectors, sparse IDF, and ColBERT MaxSim multivectors." />
<!-- Open Graph / social share unfurl -->
<meta property="og:type" content="website" />
<meta property="og:site_name" content="memex" />
<meta property="og:url" content="https://memex.quest/" />
<meta property="og:title" content="memex — local memory for coding agents" />
<meta property="og:description" content="Coding agents forget. memex remembers — the local memory layer for Claude Code and Codex, powered by Qdrant 1.18 with five named vectors, sparse IDF, and ColBERT MaxSim multivectors." />
<meta property="og:image" content="https://memex.quest/assets/og-image.png" />

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Point social images at the deployed Pages host

If the landing page is still shared from the current public URL, this absolute memex.quest image URL prevents unfurls from showing the new card: the repo still documents the live landing as https://two-weeks-team.github.io/memex/, and a repo-wide search shows no CNAME or deploy config that publishes memex.quest. In that context, crawlers reading the GitHub Pages page will try to fetch the image from a different, unconfigured host; use the deployed Pages URL (or add the custom-domain deployment in the same change) so the OG/Twitter images are actually reachable.

Useful? React with 👍 / 👎.

<meta property="og:image:secure_url" content="https://memex.quest/assets/og-image.png" />
<meta property="og:image:type" content="image/png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:image:alt" content="memex — “Coding agents forget. memex remembers.” Local memory for coding agents, powered by Qdrant." />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="memex — local memory for coding agents" />
<meta name="twitter:description" content="Coding agents forget. memex remembers — the local memory layer for Claude Code and Codex, powered by Qdrant." />
<meta name="twitter:image" content="https://memex.quest/assets/og-image.png" />
Comment on lines +21 to +23

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Twitter's crawler automatically falls back to Open Graph tags (og:title, og:image) if the corresponding twitter:* tags are not specified. Since twitter:title and twitter:image are identical to og:title and og:image, they are redundant. Removing them simplifies the <head> section and avoids potential desynchronization in the future.

Suggested change
<meta name="twitter:title" content="memex — local memory for coding agents" />
<meta name="twitter:description" content="Coding agents forget. memex remembers — the local memory layer for Claude Code and Codex, powered by Qdrant." />
<meta name="twitter:image" content="https://memex.quest/assets/og-image.png" />
<meta name="twitter:description" content="Coding agents forget. memex remembers — the local memory layer for Claude Code and Codex, powered by Qdrant." />

<link rel="icon" href="assets/favicon.ico" sizes="any" />
<link rel="icon" type="image/png" sizes="32x32" href="assets/favicon-32.png" />
<link rel="apple-touch-icon" sizes="180x180" href="assets/apple-touch-icon.png" />
Expand Down
270 changes: 270 additions & 0 deletions scripts/og/og-image.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,270 @@
<!--
Source template for the social-share image at assets/og-image.png
(Open Graph / Twitter unfurl). Build tooling — NOT served by the site.

Regenerate (macOS, Google Chrome headless), from repo root:
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--headless=new --disable-gpu --hide-scrollbars --force-device-scale-factor=1 \
--virtual-time-budget=5000 --window-size=1200,630 \
--screenshot=assets/og-image.png \
"file://$PWD/scripts/og/og-image.html"

Output: 1200x630 PNG. Fonts (Fraunces + JetBrains Mono) load from Google
Fonts at render time, so a network connection is needed to regenerate.
-->
<!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=Fraunces:ital,opsz,wght,SOFT,WONK@0,9..144,400..900,0..100,0..1;1,9..144,400..900,0..100,0..1&family=JetBrains+Mono:ital,wght@0,100..800;1,100..800&display=swap" rel="stylesheet" />
<style>
:root {
--ink: #f4ece0;
--ink-dim: rgba(244, 236, 224, 0.62);
--ink-faint:rgba(244, 236, 224, 0.32);
--line: rgba(244, 236, 224, 0.08);
--line-2: rgba(244, 236, 224, 0.14);
--paper: #0a0c10;
--paper-1: #0d1117;
--amber: #e6c069;
--amber-dim:rgba(230, 192, 105, 0.5);
--ribbon: #c8392a;
--display: "Fraunces", "Iowan Old Style", Georgia, serif;
--mono: "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;
}

html, body { margin: 0; padding: 0; background: var(--paper); }
*, *::before, *::after { box-sizing: border-box; }

.frame {
width: 1200px;
height: 630px;
position: relative;
overflow: hidden;
background: var(--paper);
color: var(--ink);
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
font-feature-settings: "ss01", "ss02", "cv01";
}

/* Paper grain / vignette — amber bloom rises from the lower-left where the
enlarged signature now sits. */
.frame::before {
content: "";
position: absolute;
inset: 0;
background:
radial-gradient(1000px 660px at 84% 118%, rgba(230, 192, 105, 0.12), transparent 58%),
radial-gradient(1100px 760px at 8% -12%, rgba(244, 236, 224, 0.05), transparent 56%),
linear-gradient(176deg, var(--paper-1) 0%, var(--paper) 62%);
z-index: 0;
}
.frame::after {
content: "";
position: absolute;
inset: 0;
box-shadow: inset 0 0 240px rgba(0, 0, 0, 0.55);
z-index: 0;
pointer-events: none;
}

/* hairline editorial frame inset with amber registration ticks */
.plate {
position: absolute;
inset: 28px;
border: 1px solid var(--line);
z-index: 1;
pointer-events: none;
}
.plate::before,
.plate::after {
content: "";
position: absolute;
background: var(--amber-dim);
}
.plate::before { top: -1px; left: -1px; width: 24px; height: 1px; }
.plate::after { bottom: -1px; right: -1px; width: 24px; height: 1px; }

.stage {
position: absolute;
inset: 0;
z-index: 3;
padding: 70px 76px;
display: flex;
flex-direction: column;
justify-content: center;
}

/* ===== top kicker line (corner anchor, decorative) ===== */
.kicker {
position: absolute;
top: 64px;
left: 76px;
display: inline-flex;
align-items: center;
gap: 16px;
font-family: var(--mono);
font-size: 14px;
font-weight: 600;
letter-spacing: 0.24em;
text-transform: uppercase;
color: var(--ink-faint);
}
.kicker::before {
content: "";
width: 46px; height: 1px; background: var(--amber-dim);
}
.kicker em { font-style: normal; color: var(--amber); }

/* ===== hero hook — the text IS the design ===== */
.hook-block { max-width: 940px; }
h1.hook {
margin: 0;
font-family: var(--display);
font-style: italic;
font-variation-settings: "SOFT" 28, "WONK" 0, "opsz" 144;
font-weight: 580;
font-size: 108px;
line-height: 0.96;
letter-spacing: -0.03em;
color: var(--ink);
text-shadow: 0 2px 44px rgba(230, 192, 105, 0.10);
}
h1.hook .dim {
color: var(--ink-dim);
font-weight: 460;
}
h1.hook .turn {
display: block;
color: var(--amber);
}
.lineage {
margin: 30px 0 0;
font-family: var(--display);
font-style: italic;
font-variation-settings: "opsz" 60;
font-weight: 440;
font-size: 28px;
line-height: 1.3;
letter-spacing: -0.008em;
color: var(--ink-dim);
}

/* ===== bottom signature (wordmark + logo) — enlarged, bottom-right
so the mark anchors the corner diagonally opposite the top-left kicker ===== */
.signature {
position: absolute;
right: 76px;
bottom: 58px;
display: inline-flex;
align-items: center;
gap: 24px;
}
/* logo treatment — raised lighter panel + amber halo so the near-black
blocks read clearly even at thumbnail size */
.mark {
position: relative;
flex: 0 0 auto;
width: 104px;
height: 104px;
display: grid;
place-items: center;
}
.mark .halo {
position: absolute;
inset: -24px;
border-radius: 50%;
background: radial-gradient(circle at 50% 52%, rgba(230, 192, 105, 0.40), rgba(230, 192, 105, 0.12) 46%, transparent 72%);
filter: blur(7px);
z-index: 0;
}
.mark .panel {
position: relative;
z-index: 1;
width: 104px;
height: 104px;
border-radius: 22px;
background:
radial-gradient(120% 120% at 50% 16%, rgba(244, 236, 224, 0.10), rgba(244, 236, 224, 0.025) 58%, transparent),
linear-gradient(168deg, rgba(30, 35, 44, 0.97), rgba(13, 16, 22, 0.97));
border: 1px solid var(--line-2);
box-shadow:
0 1px 0 rgba(244, 236, 224, 0.12) inset,
0 18px 44px rgba(0, 0, 0, 0.55),
0 0 0 1px rgba(0, 0, 0, 0.4);
display: grid;
place-items: center;
}
.mark img {
width: 78px;
height: 78px;
display: block;
filter:
drop-shadow(0 0 1px rgba(244, 236, 224, 0.6))
drop-shadow(0 0 18px rgba(230, 192, 105, 0.5))
drop-shadow(0 6px 12px rgba(0, 0, 0, 0.6));
}
.signature .names {
display: flex;
flex-direction: column;
align-items: flex-end;
gap: 5px;
text-align: right;
}
.signature .wordmark {
font-family: var(--display);
font-style: italic;
font-variation-settings: "SOFT" 30, "WONK" 0, "opsz" 96;
font-weight: 560;
font-size: 56px;
line-height: 0.9;
letter-spacing: -0.022em;
color: var(--ink);
}
.signature .url {
font-family: var(--mono);
font-size: 16px;
font-weight: 600;
letter-spacing: 0.08em;
color: var(--ink-dim);
}
.signature .url em { font-style: normal; color: var(--amber); }
</style>
</head>
<body>
<div class="frame">
<div class="plate"></div>

<div class="stage">
<!-- top kicker (corner anchor) -->
<span class="kicker"><em>local memory</em> · for coding agents</span>

<!-- hero hook -->
<div class="hook-block">
<h1 class="hook">
Coding agents <span class="dim">forget.</span>
<span class="turn">memex remembers.</span>
</h1>
<p class="lineage">As we may think — and at last, as we may remember.</p>
</div>

<!-- enlarged signature — names then mark, anchored bottom-right -->
<span class="signature">
<span class="names">
<span class="wordmark">memex</span>
<span class="url">memex.quest</span>
</span>
<span class="mark">
<span class="halo"></span>
<span class="panel">
<img src="../../assets/memex-logo.png" alt="memex logo" />
</span>
</span>
</span>
</div>
</div>
</body>
</html>