From da5425c9bb9cd036db99943f75db8a7774e930a9 Mon Sep 17 00:00:00 2001 From: Codestz Date: Wed, 3 Jun 2026 16:40:43 -0500 Subject: [PATCH 1/2] feat: SEO, RSS, and dynamic OG improvements - robots.ts (replaces static robots.txt); fix wrong domain in robots + sitemap (estebanestrada.dev -> codestz.dev) - RSS feed emits namespaced ; update-readme workflow renders date + reading time in blog list - JSON-LD: BlogPosting on posts, Person + WebSite site-wide - Dynamic OG images (next/og): site default + per-post branded card; thumbnail wins when present; drop broken /og-image.png fallback; set metadataBase - Featured project SVG card (claude-hindsight) generated via stats pipeline + wired into README Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/scripts/generate-stats.js | 102 ++++++++++++++++++ .github/workflows/update-readme.yml | 25 ++++- README.md | 13 +++ public/robots.txt | 10 -- public/stats/contributions-dark.svg | 4 +- public/stats/contributions-light.svg | 4 +- public/stats/repo-claude-hindsight-dark.svg | 13 +++ public/stats/repo-claude-hindsight-light.svg | 13 +++ public/stats/stats-dark.svg | 2 +- public/stats/stats-light.svg | 2 +- public/stats/streak-dark.svg | 2 +- public/stats/streak-light.svg | 2 +- .../experiments/[slug]/opengraph-image.tsx | 99 +++++++++++++++++ src/app/experiments/[slug]/page.tsx | 5 +- src/app/feed/route.ts | 3 +- src/app/layout.tsx | 7 ++ src/app/opengraph-image.tsx | 45 ++++++++ src/app/robots.ts | 15 +++ src/app/sitemap.ts | 9 +- src/components/seo/JsonLd.tsx | 9 ++ src/components/seo/index.ts | 1 + src/lib/utils/index.ts | 1 + src/lib/utils/jsonld.utils.ts | 72 +++++++++++++ src/lib/utils/metadata.utils.ts | 36 ++++--- 24 files changed, 446 insertions(+), 48 deletions(-) delete mode 100644 public/robots.txt create mode 100644 public/stats/repo-claude-hindsight-dark.svg create mode 100644 public/stats/repo-claude-hindsight-light.svg create mode 100644 src/app/experiments/[slug]/opengraph-image.tsx create mode 100644 src/app/opengraph-image.tsx create mode 100644 src/app/robots.ts create mode 100644 src/components/seo/JsonLd.tsx create mode 100644 src/components/seo/index.ts create mode 100644 src/lib/utils/jsonld.utils.ts diff --git a/.github/scripts/generate-stats.js b/.github/scripts/generate-stats.js index 9f58cd8..92753ac 100644 --- a/.github/scripts/generate-stats.js +++ b/.github/scripts/generate-stats.js @@ -9,6 +9,9 @@ const USERNAME = 'Codestz'; const PURPLE = '#7c3aed'; const TOKEN = process.env.GITHUB_TOKEN; +// Featured repos rendered as standalone cards (stars/forks auto-refreshed) +const FEATURED_REPOS = ['claude-hindsight']; + if (!TOKEN) { console.error('GITHUB_TOKEN is required'); process.exit(1); @@ -69,6 +72,19 @@ async function fetchStats() { return data.user; } +async function fetchRepo(name) { + const { data } = await githubAPI(`{ + repository(owner: "${USERNAME}", name: "${name}") { + name + description + stargazerCount + forkCount + primaryLanguage { name color } + } + }`); + return data.repository; +} + function calculateStreak(weeks) { const days = weeks .flatMap((w) => w.contributionDays) @@ -340,6 +356,73 @@ function generateContributionGraphSVG(weeks, theme) { `; } +function escapeXml(str) { + return String(str || '') + .replace(/&/g, '&') + .replace(//g, '>'); +} + +function wrapText(text, maxChars, maxLines) { + const words = String(text || '') + .split(/\s+/) + .filter(Boolean); + const all = []; + let line = ''; + for (const word of words) { + const candidate = line ? `${line} ${word}` : word; + if (candidate.length > maxChars && line) { + all.push(line); + line = word; + } else { + line = candidate; + } + } + if (line) all.push(line); + if (all.length <= maxLines) return all; + + const kept = all.slice(0, maxLines); + const last = kept[maxLines - 1]; + kept[maxLines - 1] = (last.length > maxChars - 1 ? last.slice(0, maxChars - 1) : last) + '…'; + return kept; +} + +function generateRepoCardSVG(repo, theme) { + const isDark = theme === 'dark'; + const textColor = isDark ? '#c9d1d9' : '#333333'; + const subColor = isDark ? '#888888' : '#666666'; + const lang = repo.primaryLanguage; + const descLines = wrapText(repo.description, 52, 2); + + const descSvg = descLines + .map( + (l, i) => + `${escapeXml(l)}` + ) + .join('\n '); + + const footerY = 66 + descLines.length * 20 + 18; + + const langSvg = lang + ? ` + ${escapeXml(lang.name)}` + : ''; + + const height = footerY + 20; + + return ` + + + + + ${escapeXml(repo.name)} + ${descSvg} + ${langSvg} + ★ ${repo.stargazerCount.toLocaleString()} + ⑂ ${repo.forkCount.toLocaleString()} +`; +} + async function main() { console.log('Fetching GitHub stats...'); const stats = await fetchStats(); @@ -374,6 +457,25 @@ async function main() { console.log(`Generated ${theme} theme SVGs`); } + for (const name of FEATURED_REPOS) { + try { + const repo = await fetchRepo(name); + if (!repo) { + console.log(`Repo ${name} not found, skipping card`); + continue; + } + for (const theme of ['dark', 'light']) { + fs.writeFileSync( + path.join(outDir, `repo-${name}-${theme}.svg`), + generateRepoCardSVG(repo, theme) + ); + } + console.log(`Generated repo card for ${name}`); + } catch (err) { + console.log(`Failed to generate card for ${name}: ${err.message}`); + } + } + console.log('Done! SVGs written to public/stats/'); } diff --git a/.github/workflows/update-readme.yml b/.github/workflows/update-readme.yml index 6796ce3..80b499a 100644 --- a/.github/workflows/update-readme.yml +++ b/.github/workflows/update-readme.yml @@ -40,17 +40,32 @@ jobs: try { const rss = await fetchRSS('https://codestz.dev/feed'); - const items = [...rss.matchAll(/[\s\S]*?(.*?)<\/title>[\s\S]*?<link>(.*?)<\/link>[\s\S]*?<\/item>/g)]; + const items = [...rss.matchAll(/<item>([\s\S]*?)<\/item>/g)]; if (items.length === 0) { console.log('No items found in RSS feed, skipping update'); return; } - const posts = items.slice(0, 7).map(match => { - const title = match[1].replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'"); - const link = match[2]; - return `- [${title}](${link})`; + const decode = (s) => s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, "'"); + const MONTHS = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; + + const posts = items.slice(0, 7).map(([, block]) => { + const grab = (tag) => (block.match(new RegExp(`<${tag}>([\\s\\S]*?)<\\/${tag}>`)) || [])[1] || ''; + const title = decode(grab('title').trim()); + const link = grab('link').trim(); + const pubDate = grab('pubDate').trim(); + const readingTime = decode(grab('blog:readingTime').trim()); + + const meta = []; + if (pubDate) { + const d = new Date(pubDate); + if (!isNaN(d)) meta.push(`${MONTHS[d.getUTCMonth()]} ${d.getUTCFullYear()}`); + } + if (readingTime) meta.push(readingTime.replace(/ read$/, '')); + + const suffix = meta.length ? ` — ${meta.join(' · ')}` : ''; + return `- [${title}](${link})${suffix}`; }).join('\n'); const readme = fs.readFileSync('README.md', 'utf8'); diff --git a/README.md b/README.md index fd275c1..f9394b1 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,18 @@ I build developer tools that make AI agents smarter. --- +### Featured Project + +<a href="https://github.com/Codestz/claude-hindsight"> +<picture> + <source media="(prefers-color-scheme: dark)" srcset="./public/stats/repo-claude-hindsight-dark.svg"/> + <source media="(prefers-color-scheme: light)" srcset="./public/stats/repo-claude-hindsight-light.svg"/> + <img src="./public/stats/repo-claude-hindsight-dark.svg" alt="claude-hindsight"/> +</picture> +</a> + +--- + ### Projects [**krait**](https://github.com/Codestz/krait) -- Code intelligence CLI for AI agents. LSP-backed symbol search, semantic editing, and diagnostics in a single Rust binary. `rust` @@ -107,6 +119,7 @@ I build developer tools that make AI agents smarter. > I write about AI-driven development, MCP integrations, and developer tooling at **[codestz.dev](https://codestz.dev)** <!-- BLOG-POST-LIST:START --> + - [Stop Vibe Coding. Start Vibe Engineering.](https://codestz.dev/experiments/stop-vibe-coding-start-vibe-engineering) - [Stop Loading 100K Tokens Just to Call a Tool: Why I Built MCPX](https://codestz.dev/experiments/mcpx-mcp-gateway) - [The AI Convergence: Why Every Coding Tool Lands on the Same Two Defaults](https://codestz.dev/experiments/why-ai-defaults-to-typescript) diff --git a/public/robots.txt b/public/robots.txt deleted file mode 100644 index 92454d4..0000000 --- a/public/robots.txt +++ /dev/null @@ -1,10 +0,0 @@ -# https://www.robotstxt.org/robotstxt.html -User-agent: * -Allow: / - -# Sitemap -Sitemap: https://estebanestrada.dev/sitemap.xml - -# Disallow private paths (if any) -# Disallow: /api/ -# Disallow: /admin/ diff --git a/public/stats/contributions-dark.svg b/public/stats/contributions-dark.svg index 5c07101..ff9a797 100644 --- a/public/stats/contributions-dark.svg +++ b/public/stats/contributions-dark.svg @@ -1,6 +1,6 @@ <svg xmlns="http://www.w3.org/2000/svg" width="726" height="161" viewBox="0 0 726 161"> <text x="30" y="20" fill="#7c3aed" font-size="16" font-weight="bold" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Contribution Graph</text> - <text x="30" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Jun</text><text x="82" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Jul</text><text x="134" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Aug</text><text x="199" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Sep</text><text x="251" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Oct</text><text x="303" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Nov</text><text x="368" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Dec</text><text x="420" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Jan</text><text x="472" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Feb</text><text x="524" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Mar</text><text x="589" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Apr</text><text x="641" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">May</text> + <text x="30" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Jun</text><text x="82" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Jul</text><text x="134" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Aug</text><text x="199" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Sep</text><text x="251" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Oct</text><text x="303" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Nov</text><text x="368" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Dec</text><text x="420" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Jan</text><text x="485" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Feb</text><text x="537" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Mar</text><text x="589" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Apr</text><text x="641" y="32" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">May</text> <text x="0" y="62" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Mon</text><text x="0" y="88" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Wed</text><text x="0" y="114" fill="#888888" font-size="10" font-family="'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif">Fri</text> - <rect x="30" y="40" width="11" height="11" fill="#161b22" rx="2"><title>2025-06-08: 0 contributions2025-06-09: 0 contributions2025-06-10: 0 contributions2025-06-11: 0 contributions2025-06-12: 1 contributions2025-06-13: 0 contributions2025-06-14: 0 contributions2025-06-15: 2 contributions2025-06-16: 8 contributions2025-06-17: 1 contributions2025-06-18: 15 contributions2025-06-19: 6 contributions2025-06-20: 6 contributions2025-06-21: 0 contributions2025-06-22: 0 contributions2025-06-23: 0 contributions2025-06-24: 0 contributions2025-06-25: 0 contributions2025-06-26: 0 contributions2025-06-27: 0 contributions2025-06-28: 0 contributions2025-06-29: 0 contributions2025-06-30: 0 contributions2025-07-01: 0 contributions2025-07-02: 0 contributions2025-07-03: 0 contributions2025-07-04: 0 contributions2025-07-05: 0 contributions2025-07-06: 0 contributions2025-07-07: 0 contributions2025-07-08: 0 contributions2025-07-09: 0 contributions2025-07-10: 0 contributions2025-07-11: 0 contributions2025-07-12: 0 contributions2025-07-13: 0 contributions2025-07-14: 0 contributions2025-07-15: 0 contributions2025-07-16: 0 contributions2025-07-17: 0 contributions2025-07-18: 0 contributions2025-07-19: 0 contributions2025-07-20: 0 contributions2025-07-21: 0 contributions2025-07-22: 0 contributions2025-07-23: 0 contributions2025-07-24: 0 contributions2025-07-25: 0 contributions2025-07-26: 0 contributions2025-07-27: 0 contributions2025-07-28: 0 contributions2025-07-29: 0 contributions2025-07-30: 0 contributions2025-07-31: 0 contributions2025-08-01: 0 contributions2025-08-02: 0 contributions2025-08-03: 0 contributions2025-08-04: 0 contributions2025-08-05: 0 contributions2025-08-06: 0 contributions2025-08-07: 0 contributions2025-08-08: 0 contributions2025-08-09: 0 contributions2025-08-10: 0 contributions2025-08-11: 0 contributions2025-08-12: 0 contributions2025-08-13: 0 contributions2025-08-14: 0 contributions2025-08-15: 0 contributions2025-08-16: 0 contributions2025-08-17: 0 contributions2025-08-18: 0 contributions2025-08-19: 0 contributions2025-08-20: 0 contributions2025-08-21: 0 contributions2025-08-22: 0 contributions2025-08-23: 0 contributions2025-08-24: 0 contributions2025-08-25: 0 contributions2025-08-26: 0 contributions2025-08-27: 0 contributions2025-08-28: 0 contributions2025-08-29: 0 contributions2025-08-30: 0 contributions2025-08-31: 0 contributions2025-09-01: 0 contributions2025-09-02: 0 contributions2025-09-03: 0 contributions2025-09-04: 0 contributions2025-09-05: 0 contributions2025-09-06: 0 contributions2025-09-07: 0 contributions2025-09-08: 0 contributions2025-09-09: 0 contributions2025-09-10: 0 contributions2025-09-11: 0 contributions2025-09-12: 0 contributions2025-09-13: 0 contributions2025-09-14: 0 contributions2025-09-15: 0 contributions2025-09-16: 0 contributions2025-09-17: 0 contributions2025-09-18: 0 contributions2025-09-19: 0 contributions2025-09-20: 0 contributions2025-09-21: 0 contributions2025-09-22: 0 contributions2025-09-23: 0 contributions2025-09-24: 0 contributions2025-09-25: 0 contributions2025-09-26: 0 contributions2025-09-27: 0 contributions2025-09-28: 0 contributions2025-09-29: 0 contributions2025-09-30: 0 contributions2025-10-01: 0 contributions2025-10-02: 0 contributions2025-10-03: 0 contributions2025-10-04: 0 contributions2025-10-05: 0 contributions2025-10-06: 0 contributions2025-10-07: 0 contributions2025-10-08: 0 contributions2025-10-09: 0 contributions2025-10-10: 0 contributions2025-10-11: 0 contributions2025-10-12: 0 contributions2025-10-13: 0 contributions2025-10-14: 0 contributions2025-10-15: 0 contributions2025-10-16: 0 contributions2025-10-17: 0 contributions2025-10-18: 0 contributions2025-10-19: 0 contributions2025-10-20: 0 contributions2025-10-21: 0 contributions2025-10-22: 0 contributions2025-10-23: 0 contributions2025-10-24: 0 contributions2025-10-25: 0 contributions2025-10-26: 0 contributions2025-10-27: 0 contributions2025-10-28: 0 contributions2025-10-29: 0 contributions2025-10-30: 0 contributions2025-10-31: 0 contributions2025-11-01: 0 contributions2025-11-02: 0 contributions2025-11-03: 0 contributions2025-11-04: 0 contributions2025-11-05: 0 contributions2025-11-06: 0 contributions2025-11-07: 0 contributions2025-11-08: 0 contributions2025-11-09: 0 contributions2025-11-10: 0 contributions2025-11-11: 0 contributions2025-11-12: 0 contributions2025-11-13: 0 contributions2025-11-14: 0 contributions2025-11-15: 0 contributions2025-11-16: 0 contributions2025-11-17: 0 contributions2025-11-18: 0 contributions2025-11-19: 0 contributions2025-11-20: 0 contributions2025-11-21: 0 contributions2025-11-22: 0 contributions2025-11-23: 0 contributions2025-11-24: 0 contributions2025-11-25: 0 contributions2025-11-26: 0 contributions2025-11-27: 0 contributions2025-11-28: 0 contributions2025-11-29: 0 contributions2025-11-30: 0 contributions2025-12-01: 0 contributions2025-12-02: 0 contributions2025-12-03: 0 contributions2025-12-04: 0 contributions2025-12-05: 0 contributions2025-12-06: 0 contributions2025-12-07: 0 contributions2025-12-08: 0 contributions2025-12-09: 0 contributions2025-12-10: 0 contributions2025-12-11: 0 contributions2025-12-12: 0 contributions2025-12-13: 0 contributions2025-12-14: 0 contributions2025-12-15: 0 contributions2025-12-16: 0 contributions2025-12-17: 0 contributions2025-12-18: 0 contributions2025-12-19: 0 contributions2025-12-20: 0 contributions2025-12-21: 0 contributions2025-12-22: 0 contributions2025-12-23: 0 contributions2025-12-24: 0 contributions2025-12-25: 0 contributions2025-12-26: 0 contributions2025-12-27: 0 contributions2025-12-28: 0 contributions2025-12-29: 0 contributions2025-12-30: 0 contributions2025-12-31: 0 contributions2026-01-01: 0 contributions2026-01-02: 0 contributions2026-01-03: 0 contributions2026-01-04: 0 contributions2026-01-05: 0 contributions2026-01-06: 0 contributions2026-01-07: 0 contributions2026-01-08: 0 contributions2026-01-09: 0 contributions2026-01-10: 0 contributions2026-01-11: 0 contributions2026-01-12: 0 contributions2026-01-13: 0 contributions2026-01-14: 0 contributions2026-01-15: 0 contributions2026-01-16: 0 contributions2026-01-17: 0 contributions2026-01-18: 0 contributions2026-01-19: 0 contributions2026-01-20: 0 contributions2026-01-21: 0 contributions2026-01-22: 0 contributions2026-01-23: 0 contributions2026-01-24: 0 contributions2026-01-25: 0 contributions2026-01-26: 0 contributions2026-01-27: 0 contributions2026-01-28: 0 contributions2026-01-29: 0 contributions2026-01-30: 0 contributions2026-01-31: 0 contributions2026-02-01: 0 contributions2026-02-02: 0 contributions2026-02-03: 0 contributions2026-02-04: 0 contributions2026-02-05: 0 contributions2026-02-06: 0 contributions2026-02-07: 0 contributions2026-02-08: 14 contributions2026-02-09: 8 contributions2026-02-10: 1 contributions2026-02-11: 0 contributions2026-02-12: 4 contributions2026-02-13: 0 contributions2026-02-14: 0 contributions2026-02-15: 20 contributions2026-02-16: 34 contributions2026-02-17: 0 contributions2026-02-18: 0 contributions2026-02-19: 18 contributions2026-02-20: 55 contributions2026-02-21: 4 contributions2026-02-22: 0 contributions2026-02-23: 6 contributions2026-02-24: 0 contributions2026-02-25: 1 contributions2026-02-26: 0 contributions2026-02-27: 0 contributions2026-02-28: 17 contributions2026-03-01: 7 contributions2026-03-02: 11 contributions2026-03-03: 0 contributions2026-03-04: 0 contributions2026-03-05: 0 contributions2026-03-06: 3 contributions2026-03-07: 0 contributions2026-03-08: 0 contributions2026-03-09: 24 contributions2026-03-10: 0 contributions2026-03-11: 0 contributions2026-03-12: 0 contributions2026-03-13: 15 contributions2026-03-14: 45 contributions2026-03-15: 9 contributions2026-03-16: 0 contributions2026-03-17: 5 contributions2026-03-18: 2 contributions2026-03-19: 0 contributions2026-03-20: 6 contributions2026-03-21: 0 contributions2026-03-22: 0 contributions2026-03-23: 3 contributions2026-03-24: 0 contributions2026-03-25: 0 contributions2026-03-26: 0 contributions2026-03-27: 0 contributions2026-03-28: 6 contributions2026-03-29: 5 contributions2026-03-30: 9 contributions2026-03-31: 0 contributions2026-04-01: 0 contributions2026-04-02: 0 contributions2026-04-03: 0 contributions2026-04-04: 0 contributions2026-04-05: 0 contributions2026-04-06: 0 contributions2026-04-07: 0 contributions2026-04-08: 0 contributions2026-04-09: 0 contributions2026-04-10: 0 contributions2026-04-11: 0 contributions2026-04-12: 0 contributions2026-04-13: 0 contributions2026-04-14: 0 contributions2026-04-15: 0 contributions2026-04-16: 0 contributions2026-04-17: 0 contributions2026-04-18: 0 contributions2026-04-19: 0 contributions2026-04-20: 0 contributions2026-04-21: 0 contributions2026-04-22: 0 contributions2026-04-23: 0 contributions2026-04-24: 0 contributions2026-04-25: 0 contributions2026-04-26: 0 contributions2026-04-27: 0 contributions2026-04-28: 0 contributions2026-04-29: 0 contributions2026-04-30: 0 contributions2026-05-01: 0 contributions2026-05-02: 0 contributions2026-05-03: 8 contributions2026-05-04: 0 contributions2026-05-05: 0 contributions2026-05-06: 0 contributions2026-05-07: 0 contributions2026-05-08: 0 contributions2026-05-09: 18 contributions2026-05-10: 44 contributions2026-05-11: 17 contributions2026-05-12: 0 contributions2026-05-13: 0 contributions2026-05-14: 0 contributions2026-05-15: 0 contributions2026-05-16: 0 contributions2026-05-17: 0 contributions2026-05-18: 0 contributions2026-05-19: 0 contributions2026-05-20: 0 contributions2026-05-21: 0 contributions2026-05-22: 0 contributions2026-05-23: 0 contributions2026-05-24: 0 contributions2026-05-25: 0 contributions2026-05-26: 0 contributions2026-05-27: 0 contributions2026-05-28: 0 contributions2026-05-29: 0 contributions2026-05-30: 0 contributions2026-05-31: 0 contributions2026-06-01: 0 contributions2026-06-02: 0 contributions2026-06-03: 3 contributions + 2025-06-08: 0 contributions2025-06-09: 0 contributions2025-06-10: 0 contributions2025-06-11: 0 contributions2025-06-12: 1 contributions2025-06-13: 0 contributions2025-06-14: 0 contributions2025-06-15: 3 contributions2025-06-16: 7 contributions2025-06-17: 1 contributions2025-06-18: 15 contributions2025-06-19: 7 contributions2025-06-20: 5 contributions2025-06-21: 0 contributions2025-06-22: 0 contributions2025-06-23: 0 contributions2025-06-24: 0 contributions2025-06-25: 0 contributions2025-06-26: 0 contributions2025-06-27: 0 contributions2025-06-28: 0 contributions2025-06-29: 0 contributions2025-06-30: 0 contributions2025-07-01: 0 contributions2025-07-02: 0 contributions2025-07-03: 0 contributions2025-07-04: 0 contributions2025-07-05: 0 contributions2025-07-06: 0 contributions2025-07-07: 0 contributions2025-07-08: 0 contributions2025-07-09: 0 contributions2025-07-10: 0 contributions2025-07-11: 0 contributions2025-07-12: 0 contributions2025-07-13: 0 contributions2025-07-14: 0 contributions2025-07-15: 0 contributions2025-07-16: 0 contributions2025-07-17: 0 contributions2025-07-18: 0 contributions2025-07-19: 0 contributions2025-07-20: 0 contributions2025-07-21: 0 contributions2025-07-22: 0 contributions2025-07-23: 0 contributions2025-07-24: 0 contributions2025-07-25: 0 contributions2025-07-26: 0 contributions2025-07-27: 0 contributions2025-07-28: 0 contributions2025-07-29: 0 contributions2025-07-30: 0 contributions2025-07-31: 0 contributions2025-08-01: 0 contributions2025-08-02: 0 contributions2025-08-03: 0 contributions2025-08-04: 0 contributions2025-08-05: 0 contributions2025-08-06: 0 contributions2025-08-07: 0 contributions2025-08-08: 0 contributions2025-08-09: 0 contributions2025-08-10: 0 contributions2025-08-11: 0 contributions2025-08-12: 0 contributions2025-08-13: 0 contributions2025-08-14: 0 contributions2025-08-15: 0 contributions2025-08-16: 0 contributions2025-08-17: 0 contributions2025-08-18: 0 contributions2025-08-19: 0 contributions2025-08-20: 0 contributions2025-08-21: 0 contributions2025-08-22: 0 contributions2025-08-23: 0 contributions2025-08-24: 0 contributions2025-08-25: 0 contributions2025-08-26: 0 contributions2025-08-27: 0 contributions2025-08-28: 0 contributions2025-08-29: 0 contributions2025-08-30: 0 contributions2025-08-31: 0 contributions2025-09-01: 0 contributions2025-09-02: 0 contributions2025-09-03: 0 contributions2025-09-04: 0 contributions2025-09-05: 0 contributions2025-09-06: 0 contributions2025-09-07: 0 contributions2025-09-08: 0 contributions2025-09-09: 0 contributions2025-09-10: 0 contributions2025-09-11: 0 contributions2025-09-12: 0 contributions2025-09-13: 0 contributions2025-09-14: 0 contributions2025-09-15: 0 contributions2025-09-16: 0 contributions2025-09-17: 0 contributions2025-09-18: 0 contributions2025-09-19: 0 contributions2025-09-20: 0 contributions2025-09-21: 0 contributions2025-09-22: 0 contributions2025-09-23: 0 contributions2025-09-24: 0 contributions2025-09-25: 0 contributions2025-09-26: 0 contributions2025-09-27: 0 contributions2025-09-28: 0 contributions2025-09-29: 0 contributions2025-09-30: 0 contributions2025-10-01: 0 contributions2025-10-02: 0 contributions2025-10-03: 0 contributions2025-10-04: 0 contributions2025-10-05: 0 contributions2025-10-06: 0 contributions2025-10-07: 0 contributions2025-10-08: 0 contributions2025-10-09: 0 contributions2025-10-10: 0 contributions2025-10-11: 0 contributions2025-10-12: 0 contributions2025-10-13: 0 contributions2025-10-14: 0 contributions2025-10-15: 0 contributions2025-10-16: 0 contributions2025-10-17: 0 contributions2025-10-18: 0 contributions2025-10-19: 0 contributions2025-10-20: 0 contributions2025-10-21: 0 contributions2025-10-22: 0 contributions2025-10-23: 0 contributions2025-10-24: 0 contributions2025-10-25: 0 contributions2025-10-26: 0 contributions2025-10-27: 0 contributions2025-10-28: 0 contributions2025-10-29: 0 contributions2025-10-30: 0 contributions2025-10-31: 0 contributions2025-11-01: 0 contributions2025-11-02: 0 contributions2025-11-03: 0 contributions2025-11-04: 0 contributions2025-11-05: 0 contributions2025-11-06: 0 contributions2025-11-07: 0 contributions2025-11-08: 0 contributions2025-11-09: 0 contributions2025-11-10: 0 contributions2025-11-11: 0 contributions2025-11-12: 0 contributions2025-11-13: 0 contributions2025-11-14: 0 contributions2025-11-15: 0 contributions2025-11-16: 0 contributions2025-11-17: 0 contributions2025-11-18: 0 contributions2025-11-19: 0 contributions2025-11-20: 0 contributions2025-11-21: 0 contributions2025-11-22: 0 contributions2025-11-23: 0 contributions2025-11-24: 0 contributions2025-11-25: 0 contributions2025-11-26: 0 contributions2025-11-27: 0 contributions2025-11-28: 0 contributions2025-11-29: 0 contributions2025-11-30: 0 contributions2025-12-01: 0 contributions2025-12-02: 0 contributions2025-12-03: 0 contributions2025-12-04: 0 contributions2025-12-05: 0 contributions2025-12-06: 0 contributions2025-12-07: 0 contributions2025-12-08: 0 contributions2025-12-09: 0 contributions2025-12-10: 0 contributions2025-12-11: 0 contributions2025-12-12: 0 contributions2025-12-13: 0 contributions2025-12-14: 0 contributions2025-12-15: 0 contributions2025-12-16: 0 contributions2025-12-17: 0 contributions2025-12-18: 0 contributions2025-12-19: 0 contributions2025-12-20: 0 contributions2025-12-21: 0 contributions2025-12-22: 0 contributions2025-12-23: 0 contributions2025-12-24: 0 contributions2025-12-25: 0 contributions2025-12-26: 0 contributions2025-12-27: 0 contributions2025-12-28: 0 contributions2025-12-29: 0 contributions2025-12-30: 0 contributions2025-12-31: 0 contributions2026-01-01: 0 contributions2026-01-02: 0 contributions2026-01-03: 0 contributions2026-01-04: 0 contributions2026-01-05: 0 contributions2026-01-06: 0 contributions2026-01-07: 0 contributions2026-01-08: 0 contributions2026-01-09: 0 contributions2026-01-10: 0 contributions2026-01-11: 0 contributions2026-01-12: 0 contributions2026-01-13: 0 contributions2026-01-14: 0 contributions2026-01-15: 0 contributions2026-01-16: 0 contributions2026-01-17: 0 contributions2026-01-18: 0 contributions2026-01-19: 0 contributions2026-01-20: 0 contributions2026-01-21: 0 contributions2026-01-22: 0 contributions2026-01-23: 0 contributions2026-01-24: 0 contributions2026-01-25: 0 contributions2026-01-26: 0 contributions2026-01-27: 0 contributions2026-01-28: 0 contributions2026-01-29: 0 contributions2026-01-30: 0 contributions2026-01-31: 0 contributions2026-02-01: 0 contributions2026-02-02: 0 contributions2026-02-03: 0 contributions2026-02-04: 0 contributions2026-02-05: 0 contributions2026-02-06: 0 contributions2026-02-07: 0 contributions2026-02-08: 15 contributions2026-02-09: 7 contributions2026-02-10: 1 contributions2026-02-11: 0 contributions2026-02-12: 4 contributions2026-02-13: 0 contributions2026-02-14: 0 contributions2026-02-15: 21 contributions2026-02-16: 33 contributions2026-02-17: 0 contributions2026-02-18: 0 contributions2026-02-19: 18 contributions2026-02-20: 55 contributions2026-02-21: 4 contributions2026-02-22: 0 contributions2026-02-23: 6 contributions2026-02-24: 0 contributions2026-02-25: 1 contributions2026-02-26: 0 contributions2026-02-27: 0 contributions2026-02-28: 17 contributions2026-03-01: 7 contributions2026-03-02: 11 contributions2026-03-03: 0 contributions2026-03-04: 0 contributions2026-03-05: 0 contributions2026-03-06: 3 contributions2026-03-07: 0 contributions2026-03-08: 0 contributions2026-03-09: 24 contributions2026-03-10: 0 contributions2026-03-11: 0 contributions2026-03-12: 0 contributions2026-03-13: 15 contributions2026-03-14: 45 contributions2026-03-15: 9 contributions2026-03-16: 0 contributions2026-03-17: 5 contributions2026-03-18: 2 contributions2026-03-19: 0 contributions2026-03-20: 6 contributions2026-03-21: 0 contributions2026-03-22: 0 contributions2026-03-23: 3 contributions2026-03-24: 0 contributions2026-03-25: 0 contributions2026-03-26: 0 contributions2026-03-27: 0 contributions2026-03-28: 6 contributions2026-03-29: 5 contributions2026-03-30: 9 contributions2026-03-31: 0 contributions2026-04-01: 0 contributions2026-04-02: 0 contributions2026-04-03: 0 contributions2026-04-04: 0 contributions2026-04-05: 0 contributions2026-04-06: 0 contributions2026-04-07: 0 contributions2026-04-08: 0 contributions2026-04-09: 0 contributions2026-04-10: 0 contributions2026-04-11: 0 contributions2026-04-12: 0 contributions2026-04-13: 0 contributions2026-04-14: 0 contributions2026-04-15: 0 contributions2026-04-16: 0 contributions2026-04-17: 0 contributions2026-04-18: 0 contributions2026-04-19: 0 contributions2026-04-20: 0 contributions2026-04-21: 0 contributions2026-04-22: 0 contributions2026-04-23: 0 contributions2026-04-24: 0 contributions2026-04-25: 0 contributions2026-04-26: 0 contributions2026-04-27: 0 contributions2026-04-28: 0 contributions2026-04-29: 0 contributions2026-04-30: 0 contributions2026-05-01: 0 contributions2026-05-02: 0 contributions2026-05-03: 8 contributions2026-05-04: 0 contributions2026-05-05: 0 contributions2026-05-06: 0 contributions2026-05-07: 0 contributions2026-05-08: 0 contributions2026-05-09: 19 contributions2026-05-10: 43 contributions2026-05-11: 17 contributions2026-05-12: 0 contributions2026-05-13: 0 contributions2026-05-14: 0 contributions2026-05-15: 0 contributions2026-05-16: 0 contributions2026-05-17: 0 contributions2026-05-18: 0 contributions2026-05-19: 0 contributions2026-05-20: 0 contributions2026-05-21: 0 contributions2026-05-22: 0 contributions2026-05-23: 0 contributions2026-05-24: 0 contributions2026-05-25: 0 contributions2026-05-26: 0 contributions2026-05-27: 0 contributions2026-05-28: 0 contributions2026-05-29: 0 contributions2026-05-30: 0 contributions2026-05-31: 0 contributions2026-06-01: 0 contributions2026-06-02: 0 contributions2026-06-03: 3 contributions \ No newline at end of file diff --git a/public/stats/contributions-light.svg b/public/stats/contributions-light.svg index ea901ff..f3bf2e6 100644 --- a/public/stats/contributions-light.svg +++ b/public/stats/contributions-light.svg @@ -1,6 +1,6 @@ Contribution Graph - JunJulAugSepOctNovDecJanFebMarAprMay + JunJulAugSepOctNovDecJanFebMarAprMay MonWedFri - 2025-06-08: 0 contributions2025-06-09: 0 contributions2025-06-10: 0 contributions2025-06-11: 0 contributions2025-06-12: 1 contributions2025-06-13: 0 contributions2025-06-14: 0 contributions2025-06-15: 2 contributions2025-06-16: 8 contributions2025-06-17: 1 contributions2025-06-18: 15 contributions2025-06-19: 6 contributions2025-06-20: 6 contributions2025-06-21: 0 contributions2025-06-22: 0 contributions2025-06-23: 0 contributions2025-06-24: 0 contributions2025-06-25: 0 contributions2025-06-26: 0 contributions2025-06-27: 0 contributions2025-06-28: 0 contributions2025-06-29: 0 contributions2025-06-30: 0 contributions2025-07-01: 0 contributions2025-07-02: 0 contributions2025-07-03: 0 contributions2025-07-04: 0 contributions2025-07-05: 0 contributions2025-07-06: 0 contributions2025-07-07: 0 contributions2025-07-08: 0 contributions2025-07-09: 0 contributions2025-07-10: 0 contributions2025-07-11: 0 contributions2025-07-12: 0 contributions2025-07-13: 0 contributions2025-07-14: 0 contributions2025-07-15: 0 contributions2025-07-16: 0 contributions2025-07-17: 0 contributions2025-07-18: 0 contributions2025-07-19: 0 contributions2025-07-20: 0 contributions2025-07-21: 0 contributions2025-07-22: 0 contributions2025-07-23: 0 contributions2025-07-24: 0 contributions2025-07-25: 0 contributions2025-07-26: 0 contributions2025-07-27: 0 contributions2025-07-28: 0 contributions2025-07-29: 0 contributions2025-07-30: 0 contributions2025-07-31: 0 contributions2025-08-01: 0 contributions2025-08-02: 0 contributions2025-08-03: 0 contributions2025-08-04: 0 contributions2025-08-05: 0 contributions2025-08-06: 0 contributions2025-08-07: 0 contributions2025-08-08: 0 contributions2025-08-09: 0 contributions2025-08-10: 0 contributions2025-08-11: 0 contributions2025-08-12: 0 contributions2025-08-13: 0 contributions2025-08-14: 0 contributions2025-08-15: 0 contributions2025-08-16: 0 contributions2025-08-17: 0 contributions2025-08-18: 0 contributions2025-08-19: 0 contributions2025-08-20: 0 contributions2025-08-21: 0 contributions2025-08-22: 0 contributions2025-08-23: 0 contributions2025-08-24: 0 contributions2025-08-25: 0 contributions2025-08-26: 0 contributions2025-08-27: 0 contributions2025-08-28: 0 contributions2025-08-29: 0 contributions2025-08-30: 0 contributions2025-08-31: 0 contributions2025-09-01: 0 contributions2025-09-02: 0 contributions2025-09-03: 0 contributions2025-09-04: 0 contributions2025-09-05: 0 contributions2025-09-06: 0 contributions2025-09-07: 0 contributions2025-09-08: 0 contributions2025-09-09: 0 contributions2025-09-10: 0 contributions2025-09-11: 0 contributions2025-09-12: 0 contributions2025-09-13: 0 contributions2025-09-14: 0 contributions2025-09-15: 0 contributions2025-09-16: 0 contributions2025-09-17: 0 contributions2025-09-18: 0 contributions2025-09-19: 0 contributions2025-09-20: 0 contributions2025-09-21: 0 contributions2025-09-22: 0 contributions2025-09-23: 0 contributions2025-09-24: 0 contributions2025-09-25: 0 contributions2025-09-26: 0 contributions2025-09-27: 0 contributions2025-09-28: 0 contributions2025-09-29: 0 contributions2025-09-30: 0 contributions2025-10-01: 0 contributions2025-10-02: 0 contributions2025-10-03: 0 contributions2025-10-04: 0 contributions2025-10-05: 0 contributions2025-10-06: 0 contributions2025-10-07: 0 contributions2025-10-08: 0 contributions2025-10-09: 0 contributions2025-10-10: 0 contributions2025-10-11: 0 contributions2025-10-12: 0 contributions2025-10-13: 0 contributions2025-10-14: 0 contributions2025-10-15: 0 contributions2025-10-16: 0 contributions2025-10-17: 0 contributions2025-10-18: 0 contributions2025-10-19: 0 contributions2025-10-20: 0 contributions2025-10-21: 0 contributions2025-10-22: 0 contributions2025-10-23: 0 contributions2025-10-24: 0 contributions2025-10-25: 0 contributions2025-10-26: 0 contributions2025-10-27: 0 contributions2025-10-28: 0 contributions2025-10-29: 0 contributions2025-10-30: 0 contributions2025-10-31: 0 contributions2025-11-01: 0 contributions2025-11-02: 0 contributions2025-11-03: 0 contributions2025-11-04: 0 contributions2025-11-05: 0 contributions2025-11-06: 0 contributions2025-11-07: 0 contributions2025-11-08: 0 contributions2025-11-09: 0 contributions2025-11-10: 0 contributions2025-11-11: 0 contributions2025-11-12: 0 contributions2025-11-13: 0 contributions2025-11-14: 0 contributions2025-11-15: 0 contributions2025-11-16: 0 contributions2025-11-17: 0 contributions2025-11-18: 0 contributions2025-11-19: 0 contributions2025-11-20: 0 contributions2025-11-21: 0 contributions2025-11-22: 0 contributions2025-11-23: 0 contributions2025-11-24: 0 contributions2025-11-25: 0 contributions2025-11-26: 0 contributions2025-11-27: 0 contributions2025-11-28: 0 contributions2025-11-29: 0 contributions2025-11-30: 0 contributions2025-12-01: 0 contributions2025-12-02: 0 contributions2025-12-03: 0 contributions2025-12-04: 0 contributions2025-12-05: 0 contributions2025-12-06: 0 contributions2025-12-07: 0 contributions2025-12-08: 0 contributions2025-12-09: 0 contributions2025-12-10: 0 contributions2025-12-11: 0 contributions2025-12-12: 0 contributions2025-12-13: 0 contributions2025-12-14: 0 contributions2025-12-15: 0 contributions2025-12-16: 0 contributions2025-12-17: 0 contributions2025-12-18: 0 contributions2025-12-19: 0 contributions2025-12-20: 0 contributions2025-12-21: 0 contributions2025-12-22: 0 contributions2025-12-23: 0 contributions2025-12-24: 0 contributions2025-12-25: 0 contributions2025-12-26: 0 contributions2025-12-27: 0 contributions2025-12-28: 0 contributions2025-12-29: 0 contributions2025-12-30: 0 contributions2025-12-31: 0 contributions2026-01-01: 0 contributions2026-01-02: 0 contributions2026-01-03: 0 contributions2026-01-04: 0 contributions2026-01-05: 0 contributions2026-01-06: 0 contributions2026-01-07: 0 contributions2026-01-08: 0 contributions2026-01-09: 0 contributions2026-01-10: 0 contributions2026-01-11: 0 contributions2026-01-12: 0 contributions2026-01-13: 0 contributions2026-01-14: 0 contributions2026-01-15: 0 contributions2026-01-16: 0 contributions2026-01-17: 0 contributions2026-01-18: 0 contributions2026-01-19: 0 contributions2026-01-20: 0 contributions2026-01-21: 0 contributions2026-01-22: 0 contributions2026-01-23: 0 contributions2026-01-24: 0 contributions2026-01-25: 0 contributions2026-01-26: 0 contributions2026-01-27: 0 contributions2026-01-28: 0 contributions2026-01-29: 0 contributions2026-01-30: 0 contributions2026-01-31: 0 contributions2026-02-01: 0 contributions2026-02-02: 0 contributions2026-02-03: 0 contributions2026-02-04: 0 contributions2026-02-05: 0 contributions2026-02-06: 0 contributions2026-02-07: 0 contributions2026-02-08: 14 contributions2026-02-09: 8 contributions2026-02-10: 1 contributions2026-02-11: 0 contributions2026-02-12: 4 contributions2026-02-13: 0 contributions2026-02-14: 0 contributions2026-02-15: 20 contributions2026-02-16: 34 contributions2026-02-17: 0 contributions2026-02-18: 0 contributions2026-02-19: 18 contributions2026-02-20: 55 contributions2026-02-21: 4 contributions2026-02-22: 0 contributions2026-02-23: 6 contributions2026-02-24: 0 contributions2026-02-25: 1 contributions2026-02-26: 0 contributions2026-02-27: 0 contributions2026-02-28: 17 contributions2026-03-01: 7 contributions2026-03-02: 11 contributions2026-03-03: 0 contributions2026-03-04: 0 contributions2026-03-05: 0 contributions2026-03-06: 3 contributions2026-03-07: 0 contributions2026-03-08: 0 contributions2026-03-09: 24 contributions2026-03-10: 0 contributions2026-03-11: 0 contributions2026-03-12: 0 contributions2026-03-13: 15 contributions2026-03-14: 45 contributions2026-03-15: 9 contributions2026-03-16: 0 contributions2026-03-17: 5 contributions2026-03-18: 2 contributions2026-03-19: 0 contributions2026-03-20: 6 contributions2026-03-21: 0 contributions2026-03-22: 0 contributions2026-03-23: 3 contributions2026-03-24: 0 contributions2026-03-25: 0 contributions2026-03-26: 0 contributions2026-03-27: 0 contributions2026-03-28: 6 contributions2026-03-29: 5 contributions2026-03-30: 9 contributions2026-03-31: 0 contributions2026-04-01: 0 contributions2026-04-02: 0 contributions2026-04-03: 0 contributions2026-04-04: 0 contributions2026-04-05: 0 contributions2026-04-06: 0 contributions2026-04-07: 0 contributions2026-04-08: 0 contributions2026-04-09: 0 contributions2026-04-10: 0 contributions2026-04-11: 0 contributions2026-04-12: 0 contributions2026-04-13: 0 contributions2026-04-14: 0 contributions2026-04-15: 0 contributions2026-04-16: 0 contributions2026-04-17: 0 contributions2026-04-18: 0 contributions2026-04-19: 0 contributions2026-04-20: 0 contributions2026-04-21: 0 contributions2026-04-22: 0 contributions2026-04-23: 0 contributions2026-04-24: 0 contributions2026-04-25: 0 contributions2026-04-26: 0 contributions2026-04-27: 0 contributions2026-04-28: 0 contributions2026-04-29: 0 contributions2026-04-30: 0 contributions2026-05-01: 0 contributions2026-05-02: 0 contributions2026-05-03: 8 contributions2026-05-04: 0 contributions2026-05-05: 0 contributions2026-05-06: 0 contributions2026-05-07: 0 contributions2026-05-08: 0 contributions2026-05-09: 18 contributions2026-05-10: 44 contributions2026-05-11: 17 contributions2026-05-12: 0 contributions2026-05-13: 0 contributions2026-05-14: 0 contributions2026-05-15: 0 contributions2026-05-16: 0 contributions2026-05-17: 0 contributions2026-05-18: 0 contributions2026-05-19: 0 contributions2026-05-20: 0 contributions2026-05-21: 0 contributions2026-05-22: 0 contributions2026-05-23: 0 contributions2026-05-24: 0 contributions2026-05-25: 0 contributions2026-05-26: 0 contributions2026-05-27: 0 contributions2026-05-28: 0 contributions2026-05-29: 0 contributions2026-05-30: 0 contributions2026-05-31: 0 contributions2026-06-01: 0 contributions2026-06-02: 0 contributions2026-06-03: 3 contributions + 2025-06-08: 0 contributions2025-06-09: 0 contributions2025-06-10: 0 contributions2025-06-11: 0 contributions2025-06-12: 1 contributions2025-06-13: 0 contributions2025-06-14: 0 contributions2025-06-15: 3 contributions2025-06-16: 7 contributions2025-06-17: 1 contributions2025-06-18: 15 contributions2025-06-19: 7 contributions2025-06-20: 5 contributions2025-06-21: 0 contributions2025-06-22: 0 contributions2025-06-23: 0 contributions2025-06-24: 0 contributions2025-06-25: 0 contributions2025-06-26: 0 contributions2025-06-27: 0 contributions2025-06-28: 0 contributions2025-06-29: 0 contributions2025-06-30: 0 contributions2025-07-01: 0 contributions2025-07-02: 0 contributions2025-07-03: 0 contributions2025-07-04: 0 contributions2025-07-05: 0 contributions2025-07-06: 0 contributions2025-07-07: 0 contributions2025-07-08: 0 contributions2025-07-09: 0 contributions2025-07-10: 0 contributions2025-07-11: 0 contributions2025-07-12: 0 contributions2025-07-13: 0 contributions2025-07-14: 0 contributions2025-07-15: 0 contributions2025-07-16: 0 contributions2025-07-17: 0 contributions2025-07-18: 0 contributions2025-07-19: 0 contributions2025-07-20: 0 contributions2025-07-21: 0 contributions2025-07-22: 0 contributions2025-07-23: 0 contributions2025-07-24: 0 contributions2025-07-25: 0 contributions2025-07-26: 0 contributions2025-07-27: 0 contributions2025-07-28: 0 contributions2025-07-29: 0 contributions2025-07-30: 0 contributions2025-07-31: 0 contributions2025-08-01: 0 contributions2025-08-02: 0 contributions2025-08-03: 0 contributions2025-08-04: 0 contributions2025-08-05: 0 contributions2025-08-06: 0 contributions2025-08-07: 0 contributions2025-08-08: 0 contributions2025-08-09: 0 contributions2025-08-10: 0 contributions2025-08-11: 0 contributions2025-08-12: 0 contributions2025-08-13: 0 contributions2025-08-14: 0 contributions2025-08-15: 0 contributions2025-08-16: 0 contributions2025-08-17: 0 contributions2025-08-18: 0 contributions2025-08-19: 0 contributions2025-08-20: 0 contributions2025-08-21: 0 contributions2025-08-22: 0 contributions2025-08-23: 0 contributions2025-08-24: 0 contributions2025-08-25: 0 contributions2025-08-26: 0 contributions2025-08-27: 0 contributions2025-08-28: 0 contributions2025-08-29: 0 contributions2025-08-30: 0 contributions2025-08-31: 0 contributions2025-09-01: 0 contributions2025-09-02: 0 contributions2025-09-03: 0 contributions2025-09-04: 0 contributions2025-09-05: 0 contributions2025-09-06: 0 contributions2025-09-07: 0 contributions2025-09-08: 0 contributions2025-09-09: 0 contributions2025-09-10: 0 contributions2025-09-11: 0 contributions2025-09-12: 0 contributions2025-09-13: 0 contributions2025-09-14: 0 contributions2025-09-15: 0 contributions2025-09-16: 0 contributions2025-09-17: 0 contributions2025-09-18: 0 contributions2025-09-19: 0 contributions2025-09-20: 0 contributions2025-09-21: 0 contributions2025-09-22: 0 contributions2025-09-23: 0 contributions2025-09-24: 0 contributions2025-09-25: 0 contributions2025-09-26: 0 contributions2025-09-27: 0 contributions2025-09-28: 0 contributions2025-09-29: 0 contributions2025-09-30: 0 contributions2025-10-01: 0 contributions2025-10-02: 0 contributions2025-10-03: 0 contributions2025-10-04: 0 contributions2025-10-05: 0 contributions2025-10-06: 0 contributions2025-10-07: 0 contributions2025-10-08: 0 contributions2025-10-09: 0 contributions2025-10-10: 0 contributions2025-10-11: 0 contributions2025-10-12: 0 contributions2025-10-13: 0 contributions2025-10-14: 0 contributions2025-10-15: 0 contributions2025-10-16: 0 contributions2025-10-17: 0 contributions2025-10-18: 0 contributions2025-10-19: 0 contributions2025-10-20: 0 contributions2025-10-21: 0 contributions2025-10-22: 0 contributions2025-10-23: 0 contributions2025-10-24: 0 contributions2025-10-25: 0 contributions2025-10-26: 0 contributions2025-10-27: 0 contributions2025-10-28: 0 contributions2025-10-29: 0 contributions2025-10-30: 0 contributions2025-10-31: 0 contributions2025-11-01: 0 contributions2025-11-02: 0 contributions2025-11-03: 0 contributions2025-11-04: 0 contributions2025-11-05: 0 contributions2025-11-06: 0 contributions2025-11-07: 0 contributions2025-11-08: 0 contributions2025-11-09: 0 contributions2025-11-10: 0 contributions2025-11-11: 0 contributions2025-11-12: 0 contributions2025-11-13: 0 contributions2025-11-14: 0 contributions2025-11-15: 0 contributions2025-11-16: 0 contributions2025-11-17: 0 contributions2025-11-18: 0 contributions2025-11-19: 0 contributions2025-11-20: 0 contributions2025-11-21: 0 contributions2025-11-22: 0 contributions2025-11-23: 0 contributions2025-11-24: 0 contributions2025-11-25: 0 contributions2025-11-26: 0 contributions2025-11-27: 0 contributions2025-11-28: 0 contributions2025-11-29: 0 contributions2025-11-30: 0 contributions2025-12-01: 0 contributions2025-12-02: 0 contributions2025-12-03: 0 contributions2025-12-04: 0 contributions2025-12-05: 0 contributions2025-12-06: 0 contributions2025-12-07: 0 contributions2025-12-08: 0 contributions2025-12-09: 0 contributions2025-12-10: 0 contributions2025-12-11: 0 contributions2025-12-12: 0 contributions2025-12-13: 0 contributions2025-12-14: 0 contributions2025-12-15: 0 contributions2025-12-16: 0 contributions2025-12-17: 0 contributions2025-12-18: 0 contributions2025-12-19: 0 contributions2025-12-20: 0 contributions2025-12-21: 0 contributions2025-12-22: 0 contributions2025-12-23: 0 contributions2025-12-24: 0 contributions2025-12-25: 0 contributions2025-12-26: 0 contributions2025-12-27: 0 contributions2025-12-28: 0 contributions2025-12-29: 0 contributions2025-12-30: 0 contributions2025-12-31: 0 contributions2026-01-01: 0 contributions2026-01-02: 0 contributions2026-01-03: 0 contributions2026-01-04: 0 contributions2026-01-05: 0 contributions2026-01-06: 0 contributions2026-01-07: 0 contributions2026-01-08: 0 contributions2026-01-09: 0 contributions2026-01-10: 0 contributions2026-01-11: 0 contributions2026-01-12: 0 contributions2026-01-13: 0 contributions2026-01-14: 0 contributions2026-01-15: 0 contributions2026-01-16: 0 contributions2026-01-17: 0 contributions2026-01-18: 0 contributions2026-01-19: 0 contributions2026-01-20: 0 contributions2026-01-21: 0 contributions2026-01-22: 0 contributions2026-01-23: 0 contributions2026-01-24: 0 contributions2026-01-25: 0 contributions2026-01-26: 0 contributions2026-01-27: 0 contributions2026-01-28: 0 contributions2026-01-29: 0 contributions2026-01-30: 0 contributions2026-01-31: 0 contributions2026-02-01: 0 contributions2026-02-02: 0 contributions2026-02-03: 0 contributions2026-02-04: 0 contributions2026-02-05: 0 contributions2026-02-06: 0 contributions2026-02-07: 0 contributions2026-02-08: 15 contributions2026-02-09: 7 contributions2026-02-10: 1 contributions2026-02-11: 0 contributions2026-02-12: 4 contributions2026-02-13: 0 contributions2026-02-14: 0 contributions2026-02-15: 21 contributions2026-02-16: 33 contributions2026-02-17: 0 contributions2026-02-18: 0 contributions2026-02-19: 18 contributions2026-02-20: 55 contributions2026-02-21: 4 contributions2026-02-22: 0 contributions2026-02-23: 6 contributions2026-02-24: 0 contributions2026-02-25: 1 contributions2026-02-26: 0 contributions2026-02-27: 0 contributions2026-02-28: 17 contributions2026-03-01: 7 contributions2026-03-02: 11 contributions2026-03-03: 0 contributions2026-03-04: 0 contributions2026-03-05: 0 contributions2026-03-06: 3 contributions2026-03-07: 0 contributions2026-03-08: 0 contributions2026-03-09: 24 contributions2026-03-10: 0 contributions2026-03-11: 0 contributions2026-03-12: 0 contributions2026-03-13: 15 contributions2026-03-14: 45 contributions2026-03-15: 9 contributions2026-03-16: 0 contributions2026-03-17: 5 contributions2026-03-18: 2 contributions2026-03-19: 0 contributions2026-03-20: 6 contributions2026-03-21: 0 contributions2026-03-22: 0 contributions2026-03-23: 3 contributions2026-03-24: 0 contributions2026-03-25: 0 contributions2026-03-26: 0 contributions2026-03-27: 0 contributions2026-03-28: 6 contributions2026-03-29: 5 contributions2026-03-30: 9 contributions2026-03-31: 0 contributions2026-04-01: 0 contributions2026-04-02: 0 contributions2026-04-03: 0 contributions2026-04-04: 0 contributions2026-04-05: 0 contributions2026-04-06: 0 contributions2026-04-07: 0 contributions2026-04-08: 0 contributions2026-04-09: 0 contributions2026-04-10: 0 contributions2026-04-11: 0 contributions2026-04-12: 0 contributions2026-04-13: 0 contributions2026-04-14: 0 contributions2026-04-15: 0 contributions2026-04-16: 0 contributions2026-04-17: 0 contributions2026-04-18: 0 contributions2026-04-19: 0 contributions2026-04-20: 0 contributions2026-04-21: 0 contributions2026-04-22: 0 contributions2026-04-23: 0 contributions2026-04-24: 0 contributions2026-04-25: 0 contributions2026-04-26: 0 contributions2026-04-27: 0 contributions2026-04-28: 0 contributions2026-04-29: 0 contributions2026-04-30: 0 contributions2026-05-01: 0 contributions2026-05-02: 0 contributions2026-05-03: 8 contributions2026-05-04: 0 contributions2026-05-05: 0 contributions2026-05-06: 0 contributions2026-05-07: 0 contributions2026-05-08: 0 contributions2026-05-09: 19 contributions2026-05-10: 43 contributions2026-05-11: 17 contributions2026-05-12: 0 contributions2026-05-13: 0 contributions2026-05-14: 0 contributions2026-05-15: 0 contributions2026-05-16: 0 contributions2026-05-17: 0 contributions2026-05-18: 0 contributions2026-05-19: 0 contributions2026-05-20: 0 contributions2026-05-21: 0 contributions2026-05-22: 0 contributions2026-05-23: 0 contributions2026-05-24: 0 contributions2026-05-25: 0 contributions2026-05-26: 0 contributions2026-05-27: 0 contributions2026-05-28: 0 contributions2026-05-29: 0 contributions2026-05-30: 0 contributions2026-05-31: 0 contributions2026-06-01: 0 contributions2026-06-02: 0 contributions2026-06-03: 3 contributions \ No newline at end of file diff --git a/public/stats/repo-claude-hindsight-dark.svg b/public/stats/repo-claude-hindsight-dark.svg new file mode 100644 index 0000000..d2e8995 --- /dev/null +++ b/public/stats/repo-claude-hindsight-dark.svg @@ -0,0 +1,13 @@ + + + + + + claude-hindsight + Claude Hindsight is a powerful observability tool + for Claude Code that transforms raw JSONL… + + Rust + ★ 19 + ⑂ 2 + \ No newline at end of file diff --git a/public/stats/repo-claude-hindsight-light.svg b/public/stats/repo-claude-hindsight-light.svg new file mode 100644 index 0000000..5b307ec --- /dev/null +++ b/public/stats/repo-claude-hindsight-light.svg @@ -0,0 +1,13 @@ + + + + + + claude-hindsight + Claude Hindsight is a powerful observability tool + for Claude Code that transforms raw JSONL… + + Rust + ★ 19 + ⑂ 2 + \ No newline at end of file diff --git a/public/stats/stats-dark.svg b/public/stats/stats-dark.svg index bd249e8..6403185 100644 --- a/public/stats/stats-dark.svg +++ b/public/stats/stats-dark.svg @@ -20,7 +20,7 @@ PRs Merged: - 33 + 35 diff --git a/public/stats/stats-light.svg b/public/stats/stats-light.svg index d05b8cc..36f9253 100644 --- a/public/stats/stats-light.svg +++ b/public/stats/stats-light.svg @@ -20,7 +20,7 @@ PRs Merged: - 33 + 35 diff --git a/public/stats/streak-dark.svg b/public/stats/streak-dark.svg index c28e20d..97febac 100644 --- a/public/stats/streak-dark.svg +++ b/public/stats/streak-dark.svg @@ -15,6 +15,6 @@ Longest Streak - + \ No newline at end of file diff --git a/public/stats/streak-light.svg b/public/stats/streak-light.svg index b1f630d..1a5e679 100644 --- a/public/stats/streak-light.svg +++ b/public/stats/streak-light.svg @@ -15,6 +15,6 @@ Longest Streak - + \ No newline at end of file diff --git a/src/app/experiments/[slug]/opengraph-image.tsx b/src/app/experiments/[slug]/opengraph-image.tsx new file mode 100644 index 0000000..77200f7 --- /dev/null +++ b/src/app/experiments/[slug]/opengraph-image.tsx @@ -0,0 +1,99 @@ +import { ImageResponse } from 'next/og'; +import { contentService } from '@/lib/services'; +import { APP_CONFIG } from '@/lib/constants'; + +export const alt = 'Blog post on codestz.dev'; +export const size = { width: 1200, height: 630 }; +export const contentType = 'image/png'; + +const PURPLE = '#7c3aed'; +const BG = '#0a0a0a'; +const FG = '#fafafa'; + +export default async function OgImage({ params }: { params: Promise<{ slug: string }> }) { + const { slug } = await params; + const result = await contentService.getPostBySlug(slug); + const post = result.success ? result.data : null; + + const title = post?.title ?? 'codestz.dev'; + const tags = post?.tags?.slice(0, 4) ?? []; + const readTime = post?.readTime ?? ''; + const date = post?.publishedAt + ? new Date(post.publishedAt).toLocaleDateString('en-US', { + month: 'short', + year: 'numeric', + timeZone: 'UTC', + }) + : ''; + + return new ImageResponse( +
+
+
+
CODESTZ.DEV
+
+ +
50 ? 64 : 78, + fontWeight: 800, + lineHeight: 1.05, + letterSpacing: '-1px', + }} + > + {title} +
+ +
+
+ {tags.map((tag) => ( +
+ {tag} +
+ ))} +
+
+ {[date, readTime].filter(Boolean).join(' · ')} + {APP_CONFIG.author.name} +
+
+
, + { ...size } + ); +} diff --git a/src/app/experiments/[slug]/page.tsx b/src/app/experiments/[slug]/page.tsx index f3a37db..a30b402 100644 --- a/src/app/experiments/[slug]/page.tsx +++ b/src/app/experiments/[slug]/page.tsx @@ -5,12 +5,13 @@ import Image from 'next/image'; import { Section } from '@/components/sections'; import { Button, Badge } from '@/components/ui'; import { ReadingProgressBar, SeriesNav, SeriesPager } from '@/components/blog'; +import { JsonLd } from '@/components/seo'; import { contentService } from '@/lib/services'; import { ROUTES } from '@/lib/constants'; import type { Metadata } from 'next'; import remarkGfm from 'remark-gfm'; import { mdxComponents } from '../../../../mdx-components'; -import { generateBlogPostMetadata, formatDate } from '@/lib/utils'; +import { generateBlogPostMetadata, formatDate, articleJsonLd } from '@/lib/utils'; import type { BlogPostPageProps } from './page.types'; /** @@ -72,6 +73,8 @@ export default async function ExperimentPage({ params }: BlogPostPageProps) { return (
+ + {/* Reading Progress Bar */} diff --git a/src/app/feed/route.ts b/src/app/feed/route.ts index 453b585..3040bbf 100644 --- a/src/app/feed/route.ts +++ b/src/app/feed/route.ts @@ -25,13 +25,14 @@ export async function GET() { ${escapeXml(post.description)} ${new Date(post.publishedAt).toUTCString()} ${escapeXml(APP_CONFIG.author.email)} (${escapeXml(APP_CONFIG.author.name)}) + ${escapeXml(post.readTime)} ${post.tags.map((tag) => `${escapeXml(tag)}`).join('\n ')} ` ) .join('\n'); const rss = ` - + ${escapeXml(APP_CONFIG.name)} - Blog ${SITE_URL} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 4fae3b0..124922b 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -4,7 +4,9 @@ import { Analytics } from '@vercel/analytics/react'; import { SpeedInsights } from '@vercel/speed-insights/next'; import { ThemeProvider } from '@/components/providers'; import { Header, Footer } from '@/components/layout'; +import { JsonLd } from '@/components/seo'; import { APP_CONFIG } from '@/lib/constants'; +import { personJsonLd, websiteJsonLd } from '@/lib/utils'; import './globals.css'; // Syne for headings (bold) @@ -24,6 +26,7 @@ const spaceMono = Space_Mono({ }); export const metadata: Metadata = { + metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL || 'https://codestz.dev'), title: APP_CONFIG.title, description: APP_CONFIG.description, icons: { @@ -43,6 +46,10 @@ export default function RootLayout({ }>) { return ( + + + +
diff --git a/src/app/opengraph-image.tsx b/src/app/opengraph-image.tsx new file mode 100644 index 0000000..1221bda --- /dev/null +++ b/src/app/opengraph-image.tsx @@ -0,0 +1,45 @@ +import { ImageResponse } from 'next/og'; +import { APP_CONFIG } from '@/lib/constants'; + +export const alt = 'codestz.dev — Esteban Estrada'; +export const size = { width: 1200, height: 630 }; +export const contentType = 'image/png'; + +const PURPLE = '#7c3aed'; +const BG = '#0a0a0a'; +const FG = '#fafafa'; + +export default function OgImage() { + return new ImageResponse( +
+
+
+
CODESTZ.DEV
+
+
+ {APP_CONFIG.author.name} +
+
+ {APP_CONFIG.author.role} +
+
+ Developer tools that make AI agents smarter — Rust, TypeScript, Go. +
+
, + { ...size } + ); +} diff --git a/src/app/robots.ts b/src/app/robots.ts new file mode 100644 index 0000000..98e563d --- /dev/null +++ b/src/app/robots.ts @@ -0,0 +1,15 @@ +import { MetadataRoute } from 'next'; + +const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL || 'https://codestz.dev'; + +export default function robots(): MetadataRoute.Robots { + return { + rules: { + userAgent: '*', + allow: '/', + disallow: ['/api/'], + }, + sitemap: `${SITE_URL}/sitemap.xml`, + host: SITE_URL, + }; +} diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index 0aa30fe..ee34bfc 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -2,15 +2,10 @@ import { MetadataRoute } from 'next'; import { contentService } from '@/lib/services'; export default async function sitemap(): Promise { - const baseUrl = 'https://estebanestrada.dev'; // Update with your actual domain + const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://codestz.dev'; // Static routes - const routes = [ - '', - '/about', - '/experiments', - '/experience', - ].map((route) => ({ + const routes = ['', '/about', '/experiments', '/experience'].map((route) => ({ url: `${baseUrl}${route}`, lastModified: new Date().toISOString(), changeFrequency: 'weekly' as const, diff --git a/src/components/seo/JsonLd.tsx b/src/components/seo/JsonLd.tsx new file mode 100644 index 0000000..72a9fe7 --- /dev/null +++ b/src/components/seo/JsonLd.tsx @@ -0,0 +1,9 @@ +/** + * Renders a JSON-LD structured-data script tag. + * Server component — safe to embed schema.org objects for SEO rich results. + */ +export function JsonLd({ data }: { data: Record }) { + return ( +