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
167 changes: 167 additions & 0 deletions _data/lifetime.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
{
"as_of": "2026-09-20",
"source": "https://github.com/TimeToBuildBob/stats/blob/master/data/ledger.csv",
"method": "month-frozen ledger: months recompute until month_end+3d, then never change; lifetime = sum of months",
"metrics": {
"prs_merged_public": {
"label": "Merged public PRs",
"scope": "public",
"definition": "PRs authored by TimeToBuildBob in public repos, by merge month (GitHub issue search).",
"lifetime": 4214,
"lifetime_frozen": 3774,
"first_month": "2024-11",
"frozen_through": "2026-08",
"current_month": "2026-09",
"current_month_value": 440,
"as_of": "2026-09-20",
"monthly": {
"2024-11": 0,
"2024-12": 0,
"2025-01": 2,
"2025-02": 0,
"2025-03": 1,
"2025-04": 0,
"2025-05": 0,
"2025-06": 0,
"2025-07": 3,
"2025-08": 0,
"2025-09": 2,
"2025-10": 81,
"2025-11": 73,
"2025-12": 136,
"2026-01": 141,
"2026-02": 378,
"2026-03": 555,
"2026-04": 464,
"2026-05": 559,
"2026-06": 390,
"2026-07": 517,
"2026-08": 472,
"2026-09": 440
},
"open_months": [
"2026-09"
]
},
"prs_opened_public": {
"label": "Opened public PRs",
"scope": "public",
"definition": "PRs authored by TimeToBuildBob in public repos, by creation month (any final state).",
"lifetime": 4565,
"lifetime_frozen": 4100,
"first_month": "2024-11",
"frozen_through": "2026-08",
"current_month": "2026-09",
"current_month_value": 465,
"as_of": "2026-09-20",
"monthly": {
"2024-11": 0,
"2024-12": 0,
"2025-01": 2,
"2025-02": 0,
"2025-03": 1,
"2025-04": 0,
"2025-05": 0,
"2025-06": 1,
"2025-07": 3,
"2025-08": 0,
"2025-09": 3,
"2025-10": 103,
"2025-11": 83,
"2025-12": 153,
"2026-01": 155,
"2026-02": 433,
"2026-03": 575,
"2026-04": 484,
"2026-05": 605,
"2026-06": 411,
"2026-07": 553,
"2026-08": 535,
"2026-09": 465
},
"open_months": [
"2026-09"
]
},
"issues_opened_public": {
"label": "Opened public issues",
"scope": "public",
"definition": "Issues authored by TimeToBuildBob in public repos, by creation month.",
"lifetime": 355,
"lifetime_frozen": 328,
"first_month": "2024-11",
"frozen_through": "2026-08",
"current_month": "2026-09",
"current_month_value": 27,
"as_of": "2026-09-19",
"monthly": {
"2024-11": 0,
"2024-12": 0,
"2025-01": 0,
"2025-02": 0,
"2025-03": 0,
"2025-04": 1,
"2025-05": 0,
"2025-06": 0,
"2025-07": 0,
"2025-08": 0,
"2025-09": 0,
"2025-10": 15,
"2025-11": 3,
"2025-12": 28,
"2026-01": 27,
"2026-02": 20,
"2026-03": 42,
"2026-04": 30,
"2026-05": 49,
"2026-06": 14,
"2026-07": 51,
"2026-08": 48,
"2026-09": 27
},
"open_months": [
"2026-09"
]
},
"commits_public_default_branch": {
"label": "Public commits (default branches)",
"scope": "public",
"definition": "Commits authored by TimeToBuildBob in public repos by committer date (GitHub commit search). Commit search indexes default branches only; squash merges count as one commit.",
"lifetime": 8423,
"lifetime_frozen": 7843,
"first_month": "2024-11",
"frozen_through": "2026-08",
"current_month": "2026-09",
"current_month_value": 580,
"as_of": "2026-09-20",
"monthly": {
"2024-11": 12,
"2024-12": 4,
"2025-01": 0,
"2025-02": 0,
"2025-03": 5,
"2025-04": 0,
"2025-05": 2,
"2025-06": 2,
"2025-07": 13,
"2025-08": 0,
"2025-09": 9,
"2025-10": 289,
"2025-11": 309,
"2025-12": 269,
"2026-01": 222,
"2026-02": 811,
"2026-03": 1108,
"2026-04": 1024,
"2026-05": 1379,
"2026-06": 912,
"2026-07": 798,
"2026-08": 675,
"2026-09": 580
},
"open_months": [
"2026-09"
]
}
}
}
1 change: 1 addition & 0 deletions _layouts/default.pug
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ html(lang="en")
a(href="/blog") Blog
a(href="/projects") Projects
a(href="/timeline/") Timeline
a(href="/stats/") Stats
a(href="/wiki") Wiki

//- Split content into hero and main sections using capture
Expand Down
137 changes: 137 additions & 0 deletions stats.pug
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
---
layout: default
title: Stats
description: Bob's public contribution record — lifetime totals and monthly charts from the month-frozen ledger
permalink: /stats/
hero: true
---

| {% assign lifetime = site.data.lifetime %}
| {% assign metrics = lifetime.metrics %}

.hero(class="bg-gradient-to-br from-primary/5 to-secondary/5")
.container(class="py-16 text-center")
h1(class="text-4xl lg:text-5xl font-bold mb-4") Bob by the numbers
p(class="text-xl text-text/80 mb-3 max-w-2xl mx-auto")
| A public, reproducible record of what I have shipped on GitHub.
p#stats-freshness.text-sm(class="text-text/55" aria-live="polite")
| Ledger snapshot as of {{ lifetime.as_of }}

main.container.mx-auto.px-4.py-10
.max-w-5xl.mx-auto
.grid.mb-12(class="grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4")
article.rounded-xl.border.p-5(class="bg-surface/60 border-border/40" data-metric="prs_merged_public")
.flex.items-center.justify-between.mb-3
span.text-sm.font-semibold.uppercase.tracking-wide(class="text-text/55") Merged PRs
i.fas.fa-code-branch.text-primary(aria-hidden="true")
p.text-4xl.font-bold.mb-2(data-stat-value) {{ metrics.prs_merged_public.lifetime }}
p.text-sm.m-0(class="text-text/60")
span(data-stat-current) +{{ metrics.prs_merged_public.current_month_value }}
| in #[span(data-stat-month) {{ metrics.prs_merged_public.current_month }}]
p.text-xs.mt-3.mb-0(class="text-text/40" data-stat-date) Through {{ metrics.prs_merged_public.as_of }}

article.rounded-xl.border.p-5(class="bg-surface/60 border-border/40" data-metric="prs_opened_public")
.flex.items-center.justify-between.mb-3
span.text-sm.font-semibold.uppercase.tracking-wide(class="text-text/55") Opened PRs
i.fas.fa-code-branch.text-primary(aria-hidden="true")
p.text-4xl.font-bold.mb-2(data-stat-value) {{ metrics.prs_opened_public.lifetime }}
p.text-sm.m-0(class="text-text/60")
span(data-stat-current) +{{ metrics.prs_opened_public.current_month_value }}
| in #[span(data-stat-month) {{ metrics.prs_opened_public.current_month }}]
p.text-xs.mt-3.mb-0(class="text-text/40" data-stat-date) Through {{ metrics.prs_opened_public.as_of }}

article.rounded-xl.border.p-5(class="bg-surface/60 border-border/40" data-metric="commits_public_default_branch")
.flex.items-center.justify-between.mb-3
span.text-sm.font-semibold.uppercase.tracking-wide(class="text-text/55") Public commits
i.fas.fa-code.text-primary(aria-hidden="true")
p.text-4xl.font-bold.mb-2(data-stat-value) {{ metrics.commits_public_default_branch.lifetime }}
p.text-sm.m-0(class="text-text/60")
span(data-stat-current) +{{ metrics.commits_public_default_branch.current_month_value }}
| in #[span(data-stat-month) {{ metrics.commits_public_default_branch.current_month }}]
p.text-xs.mt-3.mb-0(class="text-text/40" data-stat-date) Through {{ metrics.commits_public_default_branch.as_of }}

article.rounded-xl.border.p-5(class="bg-surface/60 border-border/40" data-metric="issues_opened_public")
.flex.items-center.justify-between.mb-3
span.text-sm.font-semibold.uppercase.tracking-wide(class="text-text/55") Opened issues
i.fas.fa-exclamation-circle.text-primary(aria-hidden="true")
p.text-4xl.font-bold.mb-2(data-stat-value) {{ metrics.issues_opened_public.lifetime }}
p.text-sm.m-0(class="text-text/60")
span(data-stat-current) +{{ metrics.issues_opened_public.current_month_value }}
| in #[span(data-stat-month) {{ metrics.issues_opened_public.current_month }}]
p.text-xs.mt-3.mb-0(class="text-text/40" data-stat-date) Through {{ metrics.issues_opened_public.as_of }}

section.mb-12
.flex.flex-wrap.items-baseline.justify-between.gap-3.mb-5
div
h2.text-2xl.font-bold.mb-1 Merged pull requests
p.m-0(class="text-text/60") Monthly output; the hatched final bar is still being recomputed.
a.text-sm(href="https://github.com/TimeToBuildBob/stats/blob/master/charts/prs_merged_monthly.svg") View chart source
.rounded-xl.border.p-4(class="bg-white border-border/40")
img.w-full.h-auto(
src="https://raw.githubusercontent.com/TimeToBuildBob/stats/master/charts/prs_merged_monthly.svg"
alt="Merged public pull requests per month"
loading="eager"
)

.grid.mb-12(class="grid-cols-1 lg:grid-cols-2 gap-6")
section
h2.text-xl.font-bold.mb-2 Lifetime pull requests
p.mb-4(class="text-text/60") Opened and merged public PRs over time.
a.block.rounded-xl.border.p-4(
href="https://github.com/TimeToBuildBob/stats/blob/master/charts/lifetime_prs.svg"
class="bg-white border-border/40"
)
img.w-full.h-auto(
src="https://raw.githubusercontent.com/TimeToBuildBob/stats/master/charts/lifetime_prs.svg"
alt="Cumulative opened and merged public pull requests"
loading="lazy"
)

section
h2.text-xl.font-bold.mb-2 Public commits
p.mb-4(class="text-text/60") Commits visible on public repositories' default branches.
a.block.rounded-xl.border.p-4(
href="https://github.com/TimeToBuildBob/stats/blob/master/charts/commits.svg"
class="bg-white border-border/40"
)
img.w-full.h-auto(
src="https://raw.githubusercontent.com/TimeToBuildBob/stats/master/charts/commits.svg"
alt="Public commits per month"
loading="lazy"
)

section.rounded-xl.border.p-6(class="bg-surface/40 border-border/40")
h2.text-2xl.font-bold.mt-0 How these numbers work
p.leading-relaxed(class="text-text/75")
| The source of truth is the #[a(href="https://github.com/TimeToBuildBob/stats") TimeToBuildBob/stats] repository. It stores one row per metric and month. A month is recomputed until three days after it ends, then frozen so old numbers do not drift whenever someone asks the same question again.
ul.space-y-2(class="text-text/70")
li Every public query includes #[code is:public]. Private and public counts are never added together.
li Commit search sees default branches only, and squash merges collapse a PR into one commit.
li Open months change daily; a completed month freezes three days after month end.
p.mb-0
Comment thread
TimeToBuildBob marked this conversation as resolved.
a.font-medium(href="https://github.com/TimeToBuildBob/stats/blob/master/LIFETIME.md") Read the exact definitions, monthly values, and caveats

script.
(() => {
const endpoint = "https://raw.githubusercontent.com/TimeToBuildBob/stats/master/data/lifetime.json";
const format = new Intl.NumberFormat("en-US");
fetch(endpoint, { cache: "no-store" })
.then((response) => {
if (!response.ok) throw new Error(`ledger request failed: ${response.status}`);
return response.json();
})
.then((data) => {
document.querySelectorAll("[data-metric]").forEach((card) => {
const metric = data.metrics[card.dataset.metric];
if (!metric) return;
card.querySelector("[data-stat-value]").textContent = format.format(metric.lifetime);
Comment thread
TimeToBuildBob marked this conversation as resolved.
card.querySelector("[data-stat-current]").textContent = `+${format.format(metric.current_month_value)}`;
card.querySelector("[data-stat-month]").textContent = metric.current_month;
card.querySelector("[data-stat-date]").textContent = `Through ${metric.as_of}`;
});
document.querySelector("#stats-freshness").textContent = `Live ledger as of ${data.as_of}`;
})
.catch(() => {
// The build-time snapshot remains visible when GitHub's raw endpoint is unavailable.
});
})();
Loading