Skip to content

Commit d04829d

Browse files
Merge pull request #15 from dotsystemsdevs/main
Main
2 parents 401e57e + 0405799 commit d04829d

File tree

18 files changed

+820
-246
lines changed

18 files changed

+820
-246
lines changed

README.md

Lines changed: 115 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,72 @@
44

55
Your abandoned repos deserve a proper funeral.
66

7-
**Live:** [commitmentissues.dev](https://commitmentissues.dev)
7+
**Live:** [commitmentissues.dev](https://commitmentissues.dev)  ·  Built by [Dot Systems](https://github.com/dotsystemsdevs)
88

9-
![MIT License](https://img.shields.io/github/license/dotsystemsdevs/commitmentissues?style=flat-square)
10-
![Vercel Deploy](https://img.shields.io/badge/deployed%20on-Vercel-black?style=flat-square&logo=vercel)
9+
[![MIT License](https://img.shields.io/github/license/dotsystemsdevs/commitmentissues?style=flat-square)](LICENSE)
10+
[![Deployed on Vercel](https://img.shields.io/badge/deployed%20on-Vercel-black?style=flat-square&logo=vercel)](https://commitmentissues.dev)
11+
[![Next.js](https://img.shields.io/badge/Next.js-14-black?style=flat-square&logo=next.js)](https://nextjs.org)
1112

12-
Paste a public GitHub URL. Get a shareable **Certificate of Death** — cause of death, last words, repo age, exportable graphics. No account required.
13+
---
1314

14-
## Screenshots
15+
Paste a public GitHub URL. Get a shareable **Certificate of Death** — algorithmic cause of death, last commit as last words, repo age, and exportable graphics. No signup. No account. Completely free.
16+
17+
## Embed your dead repo
1518

16-
Home:
19+
Got a dead repo? Add the badge to your README:
1720

18-
![Homepage screenshot](docs/screenshots/homepage.png)
21+
[![commitmentissues](https://img.shields.io/badge/%E2%9A%B0%20commitmentissues-declared%20dead-cc0000?style=for-the-badge&labelColor=1a0f06)](https://commitmentissues.dev)
1922

20-
Certificate:
23+
```markdown
24+
[![commitmentissues](https://img.shields.io/badge/%E2%9A%B0%20commitmentissues-declared%20dead-cc0000?style=for-the-badge&labelColor=1a0f06)](https://commitmentissues.dev/?repo=YOUR_OWNER/YOUR_REPO)
25+
```
2126

22-
![Certificate screenshot](docs/screenshots/certificate.png)
27+
Or embed the full certificate image:
2328

24-
About:
29+
```markdown
30+
[![Certificate of Death](https://commitmentissues.dev/api/certificate-image/YOUR_OWNER/YOUR_REPO)](https://commitmentissues.dev/?repo=YOUR_OWNER/YOUR_REPO)
31+
```
32+
33+
Both are generated automatically on the certificate page — just hit **Copy** after analyzing your repo.
34+
35+
## Screenshots
2536

26-
![About page screenshot](docs/screenshots/about.png)
37+
![Homepage](docs/screenshots/homepage.png)
38+
39+
![Certificate of Death](docs/screenshots/certificate.png)
40+
41+
![The Mortician — About page](docs/screenshots/about.png)
2742

2843
## Features
2944

30-
- **Certificate of Death** — A4-style layout with cause, last words, repo age, and derived stats
31-
- **Exports** — Multiple aspect ratios (feed, square, story-style) for Instagram, X, Facebook
32-
- **Mobile share** — Native share sheet on mobile with story-friendly format
33-
- **Hall of Shame** — Curated leaderboard of famously abandoned repos
34-
- **Recently Buried** — Live feed of the latest public burials
35-
- **Chrome extension** — Tombstone badge injected on any GitHub repo page (MVP)
45+
- **Certificate of Death** — A4 layout with cause of death, last words, repo age, stars, forks, and language
46+
- **Algorithmic scoring**`src/lib/scoring.ts` computes a death index from commit activity, archive status, issue count, and time since last push
47+
- **Export** — PNG downloads in multiple aspect ratios: A4, Instagram (4:5 and 1:1), X/Twitter (16:9), Facebook feed, and Stories (9:16)
48+
- **Mobile share** — Native share sheet on iOS/Android with a story-formatted image
49+
- **README badge** — Embed a `⚰ DECLARED DEAD` shields.io badge linking back to the certificate
50+
- **Certificate embed** — Full certificate image via `/api/certificate-image/[owner]/[repo]` for GitHub READMEs
51+
- **Recently Buried** — Live scrolling feed of the latest public burials
52+
- **Famous Casualties** — Curated graveyard of famously abandoned repos
53+
- **Rate limiting** — Redis-backed per-IP limiting with graceful fallback
54+
- **Timeout + race condition handling** — AbortController on every GitHub API call
3655

3756
## Tech stack
3857

3958
| | |
4059
|---|---|
4160
| Framework | Next.js 14 (App Router) |
61+
| Styling | Tailwind CSS + inline styles |
4262
| Fonts | UnifrakturMaguntia, Courier Prime, Inter |
63+
| Export | `html-to-image`, Canvas API |
64+
| Certificate image | `next/og` (Satori, Node.js runtime) |
4365
| Hosting | Vercel |
44-
| Storage | Upstash Redis (counters + recent burials) |
66+
| Storage | Upstash Redis (rate limiting + recent burials + stats) |
4567
| Data | GitHub public API |
68+
| Analytics | Vercel Analytics + Plausible |
4669

4770
## Getting started
4871

49-
Prerequisites: Node 18+
72+
**Prerequisites:** Node 18+
5073

5174
```bash
5275
git clone https://github.com/dotsystemsdevs/commitmentissues.git
@@ -57,92 +80,110 @@ npm run dev
5780

5881
Open [http://localhost:3000](http://localhost:3000).
5982

60-
### Environment
83+
### Environment variables
6184

62-
Add a GitHub token to raise API rate limits (optional but recommended):
85+
Create a `.env.local` in the project root:
6386

6487
```env
88+
# GitHub — optional but strongly recommended (raises API rate limits from 60 to 5000 req/hr)
6589
GITHUB_TOKEN=ghp_yourtoken
90+
91+
# Upstash Redis — optional (enables Recently Buried feed, rate limiting, and buried counter)
92+
KV_REST_API_URL=https://your-instance.upstash.io
93+
KV_REST_API_TOKEN=your_token
6694
```
6795

68-
Generate one at **GitHub → Settings → Developer settings → Personal access tokens**. Fine-grained or classic tokens both work.
96+
**Without any env vars** the app still works fully — you just get GitHub's unauthenticated rate limits (60 req/hr) and the Recently Buried feed is hidden.
6997

70-
> **Note:** The Recently Buried feed requires Upstash Redis (`KV_REST_API_URL` + `KV_REST_API_TOKEN`). Without it, the feed is hidden and the buried counter falls back to the historical baseline.
98+
Generate a GitHub token at **Settings → Developer settings → Personal access tokens**. Fine-grained or classic both work; no special scopes needed for public repo access.
7199

72100
## How we pronounce repos dead
73101

74102
| Step | What happens |
75-
|------|----------------|
76-
| Input | You submit a public GitHub URL |
77-
| Data | The app fetches public metadata via the GitHub API |
78-
| Score | A death index and narrative are computed in `src/lib/scoring.ts` |
79-
| Output | Certificate rendered on-screen, exportable as PNG |
80-
81-
Hall of Shame entries are hand-curated; Recently Buried reflects real usage.
82-
83-
## Testing
84-
85-
```bash
86-
npm test
87-
```
103+
|------|-------------|
104+
| Input | User submits a public GitHub URL |
105+
| Fetch | App fetches repo metadata + latest commit via GitHub API |
106+
| Score | `computeDeathIndex()` in `src/lib/scoring.ts` produces a 0–10 death index |
107+
| Narrative | `determineCauseOfDeath()` picks a cause based on the index and repo signals |
108+
| Output | Certificate rendered client-side, exportable as high-res PNG |
88109

89-
## Contributing
90-
91-
- Read `.github/CONTRIBUTING.md` before opening a PR
92-
- Use the issue and PR templates
93-
- CI runs lint, tests, and build on pull requests to `master`
110+
The scoring algorithm weighs: time since last commit, archive status, open issues, fork ratio, star count, and whether the last commit message reads like a final sigh.
94111

95112
## Project structure
96113

97-
```text
114+
```
98115
src/
99116
├── app/
100-
│ ├── page.tsx
101-
│ ├── about/
117+
│ ├── page.tsx ← homepage
118+
│ ├── about/page.tsx ← /about
119+
│ ├── layout.tsx ← root layout, fonts, analytics, JSON-LD
102120
│ └── api/
103-
│ ├── repo/
104-
│ ├── stats/
105-
│ └── recent/
121+
│ ├── repo/route.ts ← main analysis endpoint
122+
│ ├── recent/route.ts ← recently buried feed
123+
│ ├── random/route.ts ← random dead repo picker
124+
│ ├── stats/route.ts ← buried counter
125+
│ ├── badge/[owner]/[repo]/ ← shields.io-compatible badge SVG
126+
│ └── certificate-image/[owner]/[repo]/ ← OG image for README embeds
106127
├── components/
107-
│ ├── CertificateCard.tsx
108-
│ ├── Leaderboard.tsx
109-
│ ├── SearchForm.tsx
110-
│ └── LoadingState.tsx
128+
│ ├── CertificateCard.tsx ← certificate view + all export/share logic
129+
│ ├── CertificateFixed.tsx ← the actual certificate layout (A4)
130+
│ ├── SearchForm.tsx ← URL input + random button
131+
│ ├── RecentlyBuried.tsx ← scrolling marquee feed
132+
│ ├── Leaderboard.tsx ← Famous Casualties graveyard
133+
│ ├── LoadingState.tsx ← loading skeleton
134+
│ ├── ErrorDisplay.tsx ← error + retry UI
135+
│ ├── PageHero.tsx ← shared hero (emoji, title, subtitle)
136+
│ ├── SubpageShell.tsx ← shell for /about and future subpages
137+
│ └── SiteFooter.tsx ← footer
111138
└── lib/
112-
├── scoring.ts
113-
├── rateLimit.ts
114-
├── recentStore.ts
115-
── types.ts
116-
extension/ ← Chrome extension (MV3, load unpacked)
139+
├── scoring.ts ← death index + cause of death logic
140+
├── scoring.test.ts ← scoring unit tests
141+
├── rateLimit.ts ← Redis-backed rate limiting
142+
── recentStore.ts ← recently buried Redis store
143+
└── types.ts ← shared TypeScript types
117144
```
118145

119-
## Chrome extension (MVP)
146+
## Running tests
120147

121-
A MV3 extension lives under `extension/`. It injects a tombstone badge on GitHub repo pages and links to the full certificate.
148+
```bash
149+
npm test
150+
```
151+
152+
Tests cover the scoring algorithm in `src/lib/scoring.test.ts`.
122153

123-
### Load unpacked in Chrome
154+
## Contributing
155+
156+
Contributions are welcome. Please read [`.github/CONTRIBUTING.md`](.github/CONTRIBUTING.md) before opening a PR.
124157

125-
1. Open `chrome://extensions/`
126-
2. Enable **Developer mode**
127-
3. Click **Load unpacked** and select the `extension/` subfolder
158+
- Use the issue templates for bugs and feature requests
159+
- CI runs lint, tests, and build on every pull request to `master`
160+
- Keep PRs focused — one thing at a time
128161

129-
### Test flow
162+
## Roadmap
130163

131-
1. Open a GitHub repo page (e.g. `https://github.com/vercel/next.js`)
132-
2. Verify a tombstone badge appears near the repo header
133-
3. Click the badge to open the full certificate on `commitmentissues.dev`
134-
4. Navigate to another repo without a full reload; verify no duplicate badge appears
164+
Items are loosely prioritized. Community PRs welcome on anything marked **good first issue**.
135165

136-
If the API is rate-limited or unavailable, the badge falls back to `Reaper busy`.
166+
### Near-term
167+
- [ ] Upgrade to Next.js 16 (planned within one month of launch)
168+
- [ ] Dark mode
169+
- [ ] `/api/certificate-image` caching layer (currently no Redis cache)
170+
- [ ] Repo comparison — bury two repos side by side
137171

138-
## Docs
172+
### Longer-term
173+
- [ ] Chrome extension — tombstone badge injected on GitHub repo pages
174+
- [ ] Language-specific causes of death ("Died of PHP fatigue", "Last seen in CoffeeScript")
175+
- [ ] Death anniversary emails — opt-in reminders on the date of last commit
176+
- [ ] API for third-party integrations
139177

140-
- Release notes: `docs/releases/`
141-
- Screenshots: `docs/screenshots/`
142-
- Repository conventions: `docs/repository-conventions.md`
178+
### Won't do (by design)
179+
- Private repo support — we don't break into houses
180+
- Accounts / login — the funeral is free and anonymous
181+
- Monetization — coffee button stays, paywalls don't
143182

144183
## License
145184

146-
MIT — see repository license file.
185+
MIT — see [`LICENSE`](LICENSE).
186+
187+
---
147188

148-
Built by [Dot Systems](https://github.com/dotsystemsdevs).
189+
Built with too much free time by [Dot Systems](https://github.com/dotsystemsdevs). If it made you laugh, [keep us alive](https://buymeacoffee.com/commitmentissues).

ROADMAP.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ Living document. Completed work at the top, upcoming at the bottom. Add new entr
4343
- OG image aligned with live hero (light theme, correct fonts)
4444
- Custom roast line for commitmentissues repo itself
4545

46+
### Bug fixes
47+
- Fixed "bury something else →" on error screen — was retrying same broken URL instead of resetting to the form
48+
4649
### Data integrity
4750
- Audited all 28 Famous Casualties graveyard entries against live GitHub API
4851
- Fixed `angularjs/angular.js``angular/angular.js` (org transferred, old path 404)

next.config.mjs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,18 @@ const nextConfig = {
1818
{ key: 'X-XSS-Protection', value: '1; mode=block' },
1919
{ key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' },
2020
{ key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' },
21+
{
22+
key: 'Content-Security-Policy',
23+
value: [
24+
"default-src 'self'",
25+
"script-src 'self' 'unsafe-inline' 'unsafe-eval' https://va.vercel-scripts.com",
26+
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
27+
"font-src 'self' https://fonts.gstatic.com",
28+
"img-src 'self' data: blob: https://img.shields.io https://avatars.githubusercontent.com",
29+
"connect-src 'self' https://vitals.vercel-insights.com https://va.vercel-scripts.com",
30+
"frame-ancestors 'none'",
31+
].join('; '),
32+
},
2133
],
2234
},
2335
]

package-lock.json

Lines changed: 15 additions & 15 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/about/page.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@ import type { Metadata } from 'next'
22
import SubpageShell from '@/components/SubpageShell'
33

44
export const metadata: Metadata = {
5-
title: 'About — commitmentissues',
6-
description: 'How commitmentissues works: real GitHub data, a death score algorithm, and a healthy dose of dark humor for your abandoned repos.',
5+
title: 'About — Commitment Issues | How It Works',
6+
description: 'How Commitment Issues works: we analyze your GitHub repo\'s commit history, activity decay, and open issues to assign a cause of death and generate a printable death certificate.',
77
alternates: { canonical: 'https://commitmentissues.dev/about' },
88
openGraph: {
9-
title: 'About — commitmentissues',
10-
description: 'How commitmentissues works: real GitHub data, a death score algorithm, and a healthy dose of dark humor for your abandoned repos.',
9+
title: 'About — Commitment Issues | How It Works',
10+
description: 'How Commitment Issues works: we analyze your GitHub repo\'s commit history, activity decay, and open issues to assign a cause of death and generate a printable death certificate.',
1111
url: 'https://commitmentissues.dev/about',
1212
},
1313
}
@@ -62,7 +62,7 @@ export default function AboutPage() {
6262
padding: '20px 18px',
6363
border: '2px solid #1a1a1a',
6464
borderRadius: '0',
65-
background: '#f2f2f2',
65+
background: '#EDE8E1',
6666
}}
6767
>
6868
<p style={{ fontFamily: UI, fontSize: 'clamp(16px, 4.2vw, 17px)', fontWeight: 700, color: '#160A06', margin: '0 0 10px 0' }}>

0 commit comments

Comments
 (0)