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
3 changes: 3 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ jobs:
- name: Regenerate milestones-data.js from YAML
run: npm run build:milestones

- name: Regenerate changelog-data.js from CHANGELOG.md
run: npm run build:changelog

- name: Deploy to GitHub Pages (gh-pages branch)
uses: peaceiris/actions-gh-pages@4f9cc6602d3f66b9c108549d475ec49e8ef4d45e # v4.0.0
with:
Expand Down
29 changes: 29 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
name: Release Please

on:
push:
branches: [main]

# Prevent concurrent release-please runs; a new push cancels the in-progress job.
concurrency:
group: release-please
cancel-in-progress: true

permissions:
contents: write
pull-requests: write

jobs:
release-please:
runs-on: ubuntu-latest
outputs:
release_created: ${{ steps.rp.outputs.release_created }}
tag_name: ${{ steps.rp.outputs.tag_name }}
steps:
- name: Run Release Please
id: rp
uses: googleapis/release-please-action@5792afc6b46e9bb55deda9eda973a18c226bc3fc # v4.1.5
with:
token: ${{ secrets.GITHUB_TOKEN }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
3 changes: 3 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
".": "1.0.0"
}
28 changes: 27 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,17 @@ a Chart.js growth chart with projections, and a prompt/PR quality scoring sectio
├── styles.css ← Dark/light theme, animations, responsive layout
├── death-clock-core.js ← Pure functions only — no DOM, safe to unit-test
├── script.js ← All DOM manipulation, Chart.js wiring, RAF loop
├── package.json ← Jest config & devDependencies (no runtime deps)
├── changelog-data.js ← AUTO-GENERATED from CHANGELOG.md — do not edit
├── milestones-data.js ← AUTO-GENERATED from milestones.yaml — do not edit
├── package.json ← version, Jest config & devDependencies (no runtime deps)
├── release-please-config.json ← release-please release automation config
├── .release-please-manifest.json ← release-please version manifest
├── tests/
│ └── death-clock.test.js ← 75 Jest unit tests for death-clock-core.js
└── .github/
└── workflows/
├── deploy.yml ← Deploys site to gh-pages branch (production) on push to main
├── release-please.yml ← Creates release PRs + GitHub Releases via release-please
├── preview.yml ← Deploys PR preview to previews/pr-N/ and posts URL comment
├── preview-cleanup.yml ← Removes preview directory when a PR is closed
├── unit-tests.yml ← Runs `npm run test:ci` + uploads coverage to Codecov
Expand Down Expand Up @@ -103,6 +108,25 @@ Merging to `main` triggers the `deploy.yml` workflow automatically. It pushes th
**One-time repo setup required** (only needs to be done once by a maintainer):
> Settings → Pages → Source → **Deploy from a branch** → Branch: `gh-pages` / `(root)` → Save.

### Releasing a new version

This repo uses [release-please](https://github.com/googleapis/release-please) for automated semantic versioning and GitHub Releases.

**How it works:**
1. Merge PRs to `main` using [Conventional Commits](https://www.conventionalcommits.org/) in the commit/PR title:
- `feat: …` → bumps **minor** version (e.g. `1.0.0` → `1.1.0`)
- `fix: …` → bumps **patch** version (e.g. `1.0.0` → `1.0.1`)
- `feat!: …` or `BREAKING CHANGE:` footer → bumps **major** version
2. `release-please.yml` automatically creates or updates a **Release PR** that:
- bumps `"version"` in `package.json`
- updates `CHANGELOG.md` with the new release section
3. When the Release PR is merged, release-please creates a **GitHub Release** + git tag (e.g. `v1.1.0`).
4. The `deploy.yml` workflow then re-deploys, regenerating `changelog-data.js` from the updated `CHANGELOG.md` so the site's **Changelog tab** reflects the new release.

**Key files:**
- `release-please-config.json` — maps commit types to CHANGELOG sections, sets `release-type: node`
- `.release-please-manifest.json` — tracks the current released version; updated automatically by release-please

### PR Preview URLs
Every pull request automatically gets a live preview URL:
- Triggered by `preview.yml` on `pull_request` (opened / synchronize / reopened)
Expand Down Expand Up @@ -143,3 +167,5 @@ uses: actions/checkout@v6
- Do **not** skip tests when adding new pure functions to the core module.
- Do **not** change `BASE_TOKENS` / `TOKENS_PER_SECOND` / `BASE_DATE_ISO` independently — update all three as a set with a comment explaining the source.
- Do **not** use mutable tags (e.g. `@v6`) in `uses:` — always pin to a commit SHA with a full semver comment (e.g. `@abc1234... # v6.0.2`).
- Do **not** edit `changelog-data.js` or `milestones-data.js` directly — they are auto-generated; edit `CHANGELOG.md` / `milestones.yaml` and run the corresponding build script.
- Do **not** bump the version in `package.json` manually — let release-please handle it via Conventional Commits.
46 changes: 46 additions & 0 deletions changelog-data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use strict';
// AUTO-GENERATED from CHANGELOG.md — do not edit directly.
// Run `npm run build:changelog` to regenerate from CHANGELOG.md.

const SITE_VERSION = "1.0.0";

const CHANGELOG_RELEASES = [
{
version: "Unreleased",
date: null,
sections: [
{ heading: "Added", items: [
"`.nvmrc` to pin Node.js version to 20 LTS (matching CI)",
"`.editorconfig` for consistent editor formatting across contributors",
"`\"homepage\"` field in `package.json` pointing to the live GitHub Pages site",
"`CHANGELOG.md` to track releases going forward",
] }
],
},
{
version: "1.0.0",
date: "2025-04-14",
sections: [
{ heading: "Added", items: [
"Live global AI token counter anchored to `BASE_DATE_ISO` (not page-load time)",
"Session counter showing tokens consumed since the page was opened",
"7 environmental milestone cards (trees → bees → water → coral → glaciers → ocean → extinction)",
"Chart.js growth chart with 18-month log-scale projection",
"Predictions table with estimated dates for each milestone",
"Dark / light theme toggle (dark default)",
"Prompt & PR scoring section with collapsible rubric",
"Jest test suite with 75 tests and ≥ 80 % coverage thresholds",
"GitHub Actions CI workflow (`test.yml`) running on every push and PR",
"GitHub Actions deploy workflow (`deploy.yml`) publishing to GitHub Pages on merge to `main`",
"`AGENTS.md` with architecture rules and contributor guidance",
] }
],
},
];

/* istanbul ignore next */
if (typeof module !== 'undefined' && module.exports) {
module.exports = { SITE_VERSION, CHANGELOG_RELEASES };
} else if (typeof window !== 'undefined') {
window.ChangelogData = { SITE_VERSION, CHANGELOG_RELEASES };
}
33 changes: 32 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ <h1 class="site-title glow-text">AI DEATH CLOCK</h1>
aria-selected="false" aria-controls="tab-about" data-tab="about">
ℹ️ About
</button>
<button class="tab-btn" role="tab" id="tab-btn-changelog"
aria-selected="false" aria-controls="tab-changelog" data-tab="changelog">
📋 Changelog
</button>
</nav>

<!-- ════════════════════════════════════════════════════════ -->
Expand Down Expand Up @@ -658,10 +662,35 @@ <h2>What You Can Do</h2>

</div><!-- /tab-about -->

<!-- ════════════════════════════════════════════════════════ -->
<!-- TAB: Changelog -->
<!-- ════════════════════════════════════════════════════════ -->
<div id="tab-changelog" role="tabpanel" aria-labelledby="tab-btn-changelog" hidden>

<section class="about-section">
<div class="container">
<p class="section-label">&#x25A0; Release History</p>
<h2>Changelog</h2>
<p class="about-body">
All notable changes to this project are documented here.
The format follows <a href="https://keepachangelog.com/en/1.0.0/" target="_blank" rel="noopener noreferrer">Keep a Changelog</a>
and this project adheres to
<a href="https://semver.org/spec/v2.0.0.html" target="_blank" rel="noopener noreferrer">Semantic Versioning</a>.
View all official releases on
<a href="https://github.com/nitrocode/token-deathclock/releases" target="_blank" rel="noopener noreferrer">GitHub Releases</a>.
</p>
<div id="changelogList" class="changelog-list" aria-live="polite">
<!-- populated by renderChangelog() in script.js -->
</div>
</div>
</section>

</div><!-- /tab-changelog -->

<!-- ── Footer ─────────────────────────────────────────────── -->
<footer>
<div class="container">
<p>Created by <strong>RB</strong> &mdash; AI Death Clock &mdash; 2026</p>
<p>Created by <strong>RB</strong> &mdash; AI Death Clock &mdash; 2026 &mdash; <a id="siteVersionLink" href="https://github.com/nitrocode/token-deathclock/releases" target="_blank" rel="noopener noreferrer"><span id="siteVersion">v1.0.0</span></a></p>
<p class="footer-disclaimer">
💬 <a href="https://bit.ly/2K7e76D" target="_blank" rel="noopener noreferrer">Feedback &amp; Contact</a> — questions, ideas, or data corrections welcome.
</p>
Expand Down Expand Up @@ -741,6 +770,8 @@ <h2 id="receipt-heading" class="sr-only">Session Receipt</h2>
</div>
</div>

<!-- Changelog & version data (auto-generated from CHANGELOG.md) -->
<script src="changelog-data.js"></script>
<!-- Milestone data (auto-generated from milestones.yaml) -->
<script src="milestones-data.js"></script>
<!-- Core logic (no DOM deps — loaded first so script.js can use it) -->
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"test:ci": "jest --ci --coverage",
"test:e2e": "playwright test",
"test:e2e:ui": "playwright test --ui",
"build:milestones": "node scripts/build-milestones.js"
"build:milestones": "node scripts/build-milestones.js",
"build:changelog": "node scripts/build-changelog.js"
},
"devDependencies": {
"@playwright/test": "^1.59.1",
Expand Down
20 changes: 20 additions & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"release-type": "node",
"changelog-sections": [
{ "type": "feat", "section": "Added" },
{ "type": "fix", "section": "Fixed" },
{ "type": "perf", "section": "Changed" },
{ "type": "refactor", "section": "Changed" },
{ "type": "docs", "section": "Documentation", "hidden": false },
{ "type": "chore", "section": "Miscellaneous", "hidden": true },
{ "type": "ci", "section": "Miscellaneous", "hidden": true },
{ "type": "test", "section": "Miscellaneous", "hidden": true }
],
"extra-files": [
"changelog-data.js"
],
"packages": {
".": {}
}
}
59 changes: 58 additions & 1 deletion script.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* global Chart, DeathClockCore */
/* global Chart, DeathClockCore, ChangelogData */
'use strict';

// ============================================================
Expand Down Expand Up @@ -43,6 +43,12 @@
getSimulatedViewerCount,
} = window.DeathClockCore;

// ---- Unpack changelog data ----------------------------------
const {
SITE_VERSION = '',
CHANGELOG_RELEASES = [],
} = (typeof window !== 'undefined' && window.ChangelogData) || {};

// ---- State -----------------------------------------------
const BASE_DATE_MS = new Date(BASE_DATE_ISO).getTime();
const pageLoadTime = Date.now();
Expand Down Expand Up @@ -1102,6 +1108,56 @@
});
}

// ---- Render changelog tab -----------------------------------
function renderChangelog() {
const list = document.getElementById('changelogList');
if (!list) return;

const versionEl = document.getElementById('siteVersion');
if (versionEl && SITE_VERSION) {
versionEl.textContent = 'v' + SITE_VERSION;
}

if (!CHANGELOG_RELEASES || CHANGELOG_RELEASES.length === 0) {
list.innerHTML = '<p class="about-body">No changelog entries found.</p>';
return;
}

let html = '';
CHANGELOG_RELEASES.forEach((release) => {
const isUnreleased = release.version === 'Unreleased';
const dateStr = release.date
? `<span class="changelog-date">${escHtml(release.date)}</span>`
: '';
const ghUrl = isUnreleased
? 'https://github.com/nitrocode/token-deathclock/compare/v' +
escHtml(SITE_VERSION) + '...HEAD'
: 'https://github.com/nitrocode/token-deathclock/releases/tag/v' +
escHtml(release.version);
html += `<div class="changelog-release${isUnreleased ? ' changelog-release--unreleased' : ''}">`;
html += `<div class="changelog-release-header">`;
html += `<a class="changelog-version" href="${ghUrl}" target="_blank" rel="noopener noreferrer">`;
html += isUnreleased ? '🔧 Unreleased' : escHtml('v' + release.version);
html += `</a>${dateStr}`;
html += `</div>`;
if (release.sections.length === 0) {
html += `<p class="changelog-empty">No entries yet.</p>`;
}
release.sections.forEach((sec) => {
html += `<div class="changelog-section">`;
html += `<h4 class="changelog-section-heading">${escHtml(sec.heading)}</h4>`;
html += `<ul class="changelog-items">`;
sec.items.forEach((item) => {
html += `<li class="changelog-item">${escHtml(item)}</li>`;
});
html += `</ul></div>`;
});
html += `</div>`;
});

list.innerHTML = html;
}

// ============================================================
// FUN FEATURES
// ============================================================
Expand Down Expand Up @@ -2867,6 +2923,7 @@
renderMilestones();
renderPredictionsTable();
renderTips();
renderChangelog();

// Chart init is isolated so a missing date-adapter or other chart error
// cannot prevent the counters and life-blocks from running.
Expand Down
Loading
Loading