diff --git a/src/data/cv.ts b/src/data/cv.ts index 179d185..1327abc 100644 --- a/src/data/cv.ts +++ b/src/data/cv.ts @@ -1,4 +1,7 @@ -export interface Position { title: string; dates: string; note?: string } +// `note` is the one-line description shown on /cv/. `summary` (a paragraph) and +// `highlights` (bullet points) carry the longform version of a role, used only by the +// text exports: cv.txt, llms.txt, and llms-full.txt. +export interface Position { title: string; dates: string; note?: string; summary?: string; highlights?: string[] } // `icon` is a filename in src/assets/icons; omit it to fall back to an initial monogram. // `logo` is a full-wordmark filename in src/assets/logos; on the home page it replaces // the org name entirely. Omit it (e.g. while a logo is outstanding) to fall back to @@ -15,11 +18,35 @@ export interface Cv { experience: Org[]; education: Edu[]; languages: string[] } export const CV: Cv = { experience: [ - { org: 'Lineage Labs', logo: 'lineage-labs-logo-dark.svg', positions: [{ title: 'Co-Founder', dates: 'Feb 2026 – present', note: 'Building trust rails for AI agents.' }] }, - { org: 'Concordium', icon: 'Concordium Symbol_Black.svg', logo: 'Concordium_Logo_Black_full.svg', positions: [{ title: 'Director of Product', dates: 'Dec 2023 – Feb 2026' }] }, + { org: 'Lineage Labs', logo: 'lineage-labs-logo-dark.svg', positions: [{ + title: 'Co-Founder', dates: 'Feb 2026 – present', + note: 'Building trust rails for AI agents.', + summary: 'Designed, engineered and deployed WaySpace, an agentic knowledge architecture using LLM-based indexing and hybrid search (symbolic parsing + agentic web scraping). Designed an agent identity infrastructure (WayID) to secure human-to-agent interactions.', + }] }, + { org: 'Concordium', icon: 'Concordium Symbol_Black.svg', logo: 'Concordium_Logo_Black_full.svg', positions: [{ + title: 'Director of Product', dates: 'Dec 2023 – Feb 2026', + summary: 'Led product specification for protocol-level identity architectures and verifiable credentials, establishing an open standard for AI provenance and data authenticity using zero-knowledge proofs. Managed an 8-person product team alongside 50+ engineers to deliver low-latency core infrastructure, cross-platform SDKs, and consumer-facing wallet suite and ID app (for iOS, Android, browser).', + highlights: [ + 'Unified company product strategy of identity-first L1 blockchain.', + 'Oversaw the product specification, design, and rollout of flagship initiative for protocol-level tokens for stablecoin issuance.', + 'Revamped the outdated crypto wallet suite (iOS, Android, browser).', + 'Drove developer relations and ecosystem growth through keynote talks, technical documentation, and workshops.', + 'Oversaw product launches of: a novel Self-Sovereign Identity system for AI provenance certificates (using zero-knowledge proofs, DIDs, and Verifiable Credentials) and a standalone identity mobile app (Android, iOS).', + ], + }] }, { org: 'Pendulum', icon: 'Pendulum_logo.svg', logo: 'Pendulum_Logo_wordmark_full.svg', positions: [{ title: 'Head of Product', dates: 'Nov 2021 – Jun 2023', note: 'Headed product development of a forex-focused Polkadot parachain from idea to launch, including Spacewalk, the first bridge between Stellar and Polkadot.' }] }, { org: 'SatoshiPay', logo: 'satoshipay_full.svg', positions: [ - { title: 'Head of Product', dates: 'Nov 2021 – Jun 2023', note: 'Led product development of a cross-border money transfer app on decentralised ledger technology, including compliance (KYC/AML) and financial-services partnerships.' }, + // The longform covers the whole SatoshiPay/Pendulum tenure under its final title, + // so it sits on this position rather than being split across the two brands. + { title: 'Head of Product', dates: 'Nov 2021 – Jun 2023', + note: 'Led product development of a cross-border money transfer app on decentralised ledger technology, including compliance (KYC/AML) and financial-services partnerships.', + summary: 'Oversaw engineering for a novel, 1-click online payment mechanism, a forex-optimised blockchain, and automated ETL telemetry pipelines for real-time app and network diagnostics. Managed complex roadmap for multi-stakeholder projects, covering technical protocol design, tokenomics, and user-facing apps (such as Solar, an Electron-based Stellar wallet). Built KYC/AML compliance process from scratch. Served as part of working group defining protocol standards in collaboration with the Stellar Development Foundation.', + highlights: [ + 'Managed product team of 6 working with 15+ engineers.', + 'Worked in Bitcoin, Stellar, and Polkadot ecosystems.', + 'Oversaw product launches of: 1-click paywall system on Germany\'s biggest independent finance news website with 10k+ users joining within the first weeks, Pendulum blockchain (a Substrate-based parachain), which won the fastest parachain auction at the time, and the first payment channel implementations in Bitcoin.', + ], + }, { title: 'Product Lead', dates: 'Jun 2017 – Nov 2021', note: 'Led development of a 1-click payment mechanism, first on Bitcoin then Stellar, and product management of Solar Wallet for desktop, Android, and iOS.' }, { title: 'Product Consultant', dates: 'Apr 2015 – May 2017', note: 'Product and business strategy, product design, project management.' }, ] }, diff --git a/src/lib/txt.ts b/src/lib/txt.ts index 1d48afd..020f52e 100644 --- a/src/lib/txt.ts +++ b/src/lib/txt.ts @@ -1,5 +1,6 @@ import { getCollection, type CollectionEntry } from 'astro:content'; import { CREDITS, type Credit } from '../data/credits'; +import { CV } from '../data/cv'; // Shared plumbing for the plain-text endpoints (llms.txt, llms-full.txt, // cv.txt). All of them are generated from the same data that renders the @@ -23,6 +24,20 @@ export function publishedCredits(): Credit[] { return CREDITS.filter((c) => !c.title.startsWith('PLACEHOLDER')); } +// Experience as a markdown list, one item per position: the one-line note and the +// longform summary run together, with the highlights nested beneath. +export function experienceMarkdown(): string[] { + return CV.experience.flatMap((org) => + org.positions.flatMap((p) => { + const blurb = [p.note, p.summary].filter(Boolean).join(' '); + return [ + `- ${p.title}, ${org.org} (${p.dates})${blurb ? ` — ${blurb}` : ''}`, + ...(p.highlights ?? []).map((h) => ` - ${h}`), + ]; + }), + ); +} + export function postUrl(site: string, post: CollectionEntry<'posts'>): string { return `${site}/${post.data.date.getUTCFullYear()}/${post.id}/`; } diff --git a/src/pages/cv.txt.ts b/src/pages/cv.txt.ts index a5283c9..bc71da3 100644 --- a/src/pages/cv.txt.ts +++ b/src/pages/cv.txt.ts @@ -37,6 +37,8 @@ export async function GET(context: APIContext) { for (const p of org.positions) { lines.push(`${p.title}, ${org.org} (${p.dates})`); if (p.note) lines.push(` ${p.note}`); + if (p.summary) lines.push(` ${p.summary}`); + for (const h of p.highlights ?? []) lines.push(` - ${h}`); lines.push(''); } } diff --git a/src/pages/llms-full.txt.ts b/src/pages/llms-full.txt.ts index a1ca2ac..10f07bf 100644 --- a/src/pages/llms-full.txt.ts +++ b/src/pages/llms-full.txt.ts @@ -4,6 +4,7 @@ import { CV } from '../data/cv'; import { publishableBody, absolutize, + experienceMarkdown, isoDate, postUrl, projectUrl, @@ -52,11 +53,7 @@ export async function GET(context: APIContext) { '', ]; - for (const org of CV.experience) { - for (const p of org.positions) { - lines.push(`- ${p.title}, ${org.org} (${p.dates})${p.note ? ` — ${p.note}` : ''}`); - } - } + lines.push(...experienceMarkdown()); lines.push('', '### Education', ''); for (const e of CV.education) { diff --git a/src/pages/llms.txt.ts b/src/pages/llms.txt.ts index 20e353c..aa2e6f9 100644 --- a/src/pages/llms.txt.ts +++ b/src/pages/llms.txt.ts @@ -2,6 +2,7 @@ import type { APIContext } from 'astro'; import { SITE } from '../data/site'; import { CV } from '../data/cv'; import { + experienceMarkdown, isoDate, postUrl, projectUrl, @@ -12,7 +13,8 @@ import { } from '../lib/txt'; // Curated index following the llms.txt convention (https://llmstxt.org/): -// a short map of the site for agents. The complete content lives in +// a short map of the site for agents, plus the CV's experience section so a +// single fetch answers who this is. The complete content lives in // /llms-full.txt, and a plain-text CV in /cv.txt. export async function GET(context: APIContext) { const site = siteUrl(context.site); @@ -39,10 +41,14 @@ export async function GET(context: APIContext) { '## Docs', '', `- [Full site content](${site}/llms-full.txt): profile, CV, projects, and complete essay texts in one document`, - `- [CV](${site}/cv.txt): plain-text curriculum vitae`, + `- [CV](${site}/cv.txt): plain-text curriculum vitae with education and languages`, `- [RSS feed](${site}/feed.xml): essay feed`, `- [Sitemap](${site}/sitemap-index.xml)`, '', + '## Experience', + '', + ...experienceMarkdown(), + '', '## Projects', '', ...projects.map(