changelog-invaders 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kamil Banc
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,438 @@
1
+ # Changelog Invaders 🚀👾
2
+
3
+ > **Your changelog is boring. Let's fix that.**
4
+
5
+ ```
6
+ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
7
+ █ WHAT IF YOUR USERS ACTUALLY LOOKED FORWARD TO █
8
+ █ READING YOUR CHANGELOG? █
9
+ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
10
+ ```
11
+
12
+ Drop this React component into your app and watch your changelog transform into a **full arcade game** where users blast through bugs, collect power-ups, and fly through stargate portals representing your version milestones.
13
+
14
+ **8-bit chiptune soundtrack included.** đŸŽĩ
15
+
16
+ [![npm version](https://img.shields.io/npm/v/changelog-invaders.svg)](https://www.npmjs.com/package/changelog-invaders)
17
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
18
+
19
+ ---
20
+
21
+ ## đŸŽŦ See It In Action
22
+
23
+ ![Changelog Invaders Demo](assets/demo.gif)
24
+
25
+ *Blast through bugs, collect power-ups, fly through version stargates!*
26
+
27
+ ### đŸ•šī¸ [Play the Live Demo →](https://rightclickprompt.com/changelog)
28
+
29
+ Try it right now on the Right Click Prompt changelog page — no install needed!
30
+
31
+ ---
32
+
33
+ ## 🚀 Add to Your Project in 3 Steps
34
+
35
+ ### Step 1: Install the package
36
+
37
+ ```bash
38
+ npm install changelog-invaders
39
+ ```
40
+
41
+ ### Step 2: Create a changelog page (or add to existing one)
42
+
43
+ Create a new file like `app/changelog/page.tsx` (Next.js) or `src/pages/Changelog.tsx` (Vite/CRA):
44
+
45
+ ```tsx
46
+ import { ChangelogInvaders } from 'changelog-invaders'
47
+
48
+ export default function ChangelogPage() {
49
+ return (
50
+ <ChangelogInvaders
51
+ gameTitle="MY APP ODYSSEY"
52
+ versions={["v1.0.0", "v1.1.0", "v2.0.0"]}
53
+ />
54
+ )
55
+ }
56
+ ```
57
+
58
+ ### Step 3: There is no step 3. You're done! 🎉
59
+
60
+ Visit your changelog page and start playing. High scores save automatically.
61
+
62
+ ---
63
+
64
+ ### Why Add This to Your Changelog?
65
+
66
+ - 🎮 **Users will actually visit your changelog** — Nobody reads changelogs. Everyone plays games.
67
+ - 🏆 **Built-in engagement** — High scores make users come back
68
+ - 🚀 **Ship your versions as literal stargates** — v1.0 → v2.0 becomes an epic journey
69
+ - 🐛 **Make bug fixes satisfying** — Your users get to literally shoot the bugs you fixed
70
+ - ⚡ **5 minutes to integrate** — One component, zero config required
71
+
72
+ ---
73
+
74
+ Originally created by [Kamil Banc](https://x.com/kamilbanc) for [Right Click Prompt](https://rightclickprompt.com) and open-sourced for the community.
75
+
76
+ ## Features
77
+
78
+ - 🎮 **Full arcade experience** - Complete game with shooting, power-ups, and boss gates
79
+ - đŸŽĩ **Procedural chiptune audio** - Heavy metal-inspired 8-bit music and sound effects
80
+ - 🎨 **Retro pixel art** - CRT screen effects, scanlines, and pixel-perfect graphics
81
+ - 🌟 **Stargate portals** - Fly through version gates to progress
82
+ - 🏆 **High scores** - Works offline with localStorage, **no database required**
83
+ - âš™ī¸ **Fully customizable** - Colors, sprites, enemies, power-ups, and more
84
+ - 📱 **Responsive** - Works on any screen size
85
+ - 🔇 **Audio toggle** - Players can mute/unmute with M key
86
+ - 🔌 **Zero dependencies** - Only requires React, no database or backend needed
87
+
88
+ ## Quick Start
89
+
90
+ ```bash
91
+ npm install changelog-invaders
92
+ ```
93
+
94
+ ```tsx
95
+ import { ChangelogInvaders } from 'changelog-invaders'
96
+
97
+ export default function ChangelogPage() {
98
+ return (
99
+ <ChangelogInvaders
100
+ gameTitle="MY APP ODYSSEY"
101
+ versions={["v1.0.0", "v1.1.0", "v1.2.0", "v2.0.0"]}
102
+ />
103
+ )
104
+ }
105
+ ```
106
+
107
+ **That's literally it. Three lines of config.** Your changelog is now a game with:
108
+ - Generic spaceship sprite
109
+ - Default color palette (blue/green/purple/amber)
110
+ - localStorage high scores
111
+ - Full procedural audio engine
112
+ - All game mechanics
113
+
114
+ ## Configuration
115
+
116
+ ### Basic Props
117
+
118
+ ```tsx
119
+ <ChangelogInvaders
120
+ // Required
121
+ gameTitle="ACME ODYSSEY" // Title on the start screen
122
+ versions={["v1.0", "v2.0", "v3.0"]} // Version gates to fly through
123
+
124
+ // Optional branding
125
+ gameSubtitle="— JOURNEY TO V3 —" // Subtitle below title
126
+ />
127
+ ```
128
+
129
+ ### Custom Colors
130
+
131
+ ```tsx
132
+ <ChangelogInvaders
133
+ gameTitle="MY APP"
134
+ versions={["v1.0", "v2.0"]}
135
+ colors={{
136
+ bug: "#ff6b6b", // Blue enemies
137
+ feature: "#4ecdc4", // Green enemies
138
+ improvement: "#ffe66d", // Purple enemies
139
+ breaking: "#ff8c42", // Amber enemies
140
+ accent: "#6c5ce7" // UI accent (bullets, etc.)
141
+ }}
142
+ />
143
+ ```
144
+
145
+ ### Custom Enemies & Power-ups
146
+
147
+ ```tsx
148
+ <ChangelogInvaders
149
+ gameTitle="MY APP"
150
+ versions={["v1.0", "v2.0"]}
151
+ enemyItems={[
152
+ { type: "bug", text: "CRASH BUG" },
153
+ { type: "bug", text: "MEMORY LEAK" },
154
+ { type: "feature", text: "SCOPE CREEP" },
155
+ { type: "improvement", text: "TECH DEBT" },
156
+ { type: "breaking", text: "BREAKING!" },
157
+ ]}
158
+ powerUpItems={[
159
+ { type: "weapon", text: "SHIPPED!" },
160
+ { type: "weapon", text: "DEPLOYED!" },
161
+ { type: "shield", text: "TESTED!" },
162
+ ]}
163
+ />
164
+ ```
165
+
166
+ ### Backend Integration (100% Optional)
167
+
168
+ > **Note:** The game works perfectly fine without any backend. High scores are automatically saved to localStorage and persist across sessions. You only need a backend if you want a **global leaderboard** shared across all users.
169
+
170
+ If you want a global leaderboard, provide an API endpoint:
171
+
172
+ ```tsx
173
+ <ChangelogInvaders
174
+ gameTitle="MY APP"
175
+ versions={["v1.0", "v2.0"]}
176
+ highscoresEndpoint="/api/game/highscores" // Only if you want global scores
177
+ />
178
+ ```
179
+
180
+ Your API should implement:
181
+ - `GET /api/game/highscores` → Returns `{ highScores: HighScore[] }`
182
+ - `POST /api/game/highscores` → Accepts `{ playerName, score, gatesPassed, maxSpeed }`
183
+
184
+ See the [Backend Setup](#backend-setup) section for a Supabase example (or use any backend you prefer).
185
+
186
+ ### All Props
187
+
188
+ | Prop | Type | Default | Description |
189
+ |------|------|---------|-------------|
190
+ | `gameTitle` | `string` | **required** | Game title on start screen |
191
+ | `versions` | `string[]` | **required** | Version gates to fly through |
192
+ | `gameSubtitle` | `string` | `""` | Subtitle below title |
193
+ | `colors` | `Partial<ColorPalette>` | Default palette | Custom color scheme |
194
+ | `shipSprite` | `string[]` | Generic ship | Custom ship pixel art |
195
+ | `shipColors` | `ShipColors` | Default colors | Color mapping for ship |
196
+ | `enemyItems` | `EnemyItem[]` | Default items | Custom enemy definitions |
197
+ | `powerUpItems` | `PowerUpItem[]` | Default items | Custom power-up definitions |
198
+ | `highscoresEndpoint` | `string` | `undefined` | API endpoint for scores |
199
+ | `localStorageKey` | `string` | `"changelog-invaders-high-scores"` | Local storage key |
200
+ | `enableSound` | `boolean` | `true` | Enable/disable audio |
201
+ | `enableLeaderboard` | `boolean` | `true` | Show leaderboard panel |
202
+ | `height` | `number` | `280` | Canvas height in pixels |
203
+
204
+ ## Gameplay
205
+
206
+ ### Controls
207
+
208
+ | Key | Action |
209
+ |-----|--------|
210
+ | `←` / `A` | Move left |
211
+ | `→` / `D` | Move right |
212
+ | `Space` | Shoot |
213
+ | `M` | Toggle mute |
214
+ | `Esc` | Return to demo |
215
+
216
+ ### Mechanics
217
+
218
+ 1. **Shoot Bugs** - Destroy enemy bugs for points
219
+ 2. **Collect Power-ups** - Lightning bolts upgrade your weapons (up to level 5)
220
+ 3. **Fly Through Gates** - Pass through version stargates for speed bonuses
221
+ 4. **Don't Let Bugs Escape** - Penalties increase for each escaped bug
222
+ 5. **Reach the Final Version** - Complete the journey to win!
223
+
224
+ ### Scoring
225
+
226
+ - Bugs: 10-20 points (×weapon level)
227
+ - Power-ups: 100 points (×weapon level)
228
+ - Gates: 150 points (×speed multiplier)
229
+ - Time survival: 1 point every 0.5 seconds
230
+ - Movement multiplier: Up to 5× for continuous movement
231
+ - Victory bonus: 5000 points
232
+
233
+ ## Backend Setup (Optional)
234
+
235
+ > **You don't need this section unless you want a global leaderboard.** The game works completely offline with localStorage for high scores.
236
+
237
+ ### Supabase Example
238
+
239
+ 1. Create a migration file:
240
+
241
+ ```sql
242
+ -- supabase/migrations/001_high_scores.sql
243
+ CREATE TABLE game_high_scores (
244
+ id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
245
+ player_name VARCHAR(10) NOT NULL,
246
+ score INTEGER NOT NULL,
247
+ gates_passed INTEGER DEFAULT 0,
248
+ max_speed DECIMAL(4,2) DEFAULT 1.0,
249
+ created_at TIMESTAMPTZ DEFAULT NOW()
250
+ );
251
+
252
+ CREATE INDEX idx_high_scores_score ON game_high_scores(score DESC);
253
+
254
+ -- Row Level Security
255
+ ALTER TABLE game_high_scores ENABLE ROW LEVEL SECURITY;
256
+
257
+ CREATE POLICY "Anyone can read high scores"
258
+ ON game_high_scores FOR SELECT
259
+ TO anon, authenticated
260
+ USING (true);
261
+
262
+ CREATE POLICY "Anyone can insert high scores"
263
+ ON game_high_scores FOR INSERT
264
+ TO anon, authenticated
265
+ WITH CHECK (true);
266
+ ```
267
+
268
+ 2. Create API routes (Next.js example):
269
+
270
+ ```typescript
271
+ // app/api/game/highscores/route.ts
272
+ import { createClient } from '@supabase/supabase-js'
273
+
274
+ const supabase = createClient(
275
+ process.env.SUPABASE_URL!,
276
+ process.env.SUPABASE_SERVICE_KEY!
277
+ )
278
+
279
+ export async function GET() {
280
+ const { data, error } = await supabase
281
+ .from('game_high_scores')
282
+ .select('id, player_name, score, gates_passed, max_speed, created_at')
283
+ .order('score', { ascending: false })
284
+ .limit(10)
285
+
286
+ if (error) {
287
+ return Response.json({ error: error.message }, { status: 500 })
288
+ }
289
+
290
+ const highScores = data.map((row, index) => ({
291
+ ...row,
292
+ rank: index + 1
293
+ }))
294
+
295
+ return Response.json({ highScores })
296
+ }
297
+
298
+ export async function POST(request: Request) {
299
+ const body = await request.json()
300
+ const { playerName, score, gatesPassed, maxSpeed } = body
301
+
302
+ const { data, error } = await supabase
303
+ .from('game_high_scores')
304
+ .insert({
305
+ player_name: playerName.substring(0, 10),
306
+ score,
307
+ gates_passed: gatesPassed,
308
+ max_speed: maxSpeed
309
+ })
310
+ .select()
311
+ .single()
312
+
313
+ if (error) {
314
+ return Response.json({ error: error.message }, { status: 500 })
315
+ }
316
+
317
+ // Check if it's top 10
318
+ const { count } = await supabase
319
+ .from('game_high_scores')
320
+ .select('*', { count: 'exact', head: true })
321
+ .gt('score', score)
322
+
323
+ const rank = (count || 0) + 1
324
+ const isTop10 = rank <= 10
325
+
326
+ return Response.json({ success: true, isTop10, rank })
327
+ }
328
+ ```
329
+
330
+ ## Custom Ship Sprite
331
+
332
+ Create your own ship using pixel art strings:
333
+
334
+ ```tsx
335
+ const myShip = [
336
+ "........BB........", // B = Black outline
337
+ ".......BWWB.......", // W = White
338
+ "......BWWWWB......", // R = Red/accent
339
+ ".....BWWRRWWB.....", // G = Gray
340
+ "....BWWWWWWWWB....", // . = Transparent
341
+ "...BWWWWWWWWWWB...",
342
+ "..BWWWWWWWWWWWWB..",
343
+ ".BWWWWWWWWWWWWWWB.",
344
+ "BWWWWWWWWWWWWWWWWB",
345
+ "BWWWGWWWWWWWWGWWWB",
346
+ "BWWWGWWWWWWWWGWWWB",
347
+ ".BWWGWWWWWWWWGWWB.",
348
+ "..BWGGWWWWWWGGWB..",
349
+ "...BGGGWWWWGGGB...",
350
+ "....BGGGGGGGB.....",
351
+ ".....BBBBBBB......",
352
+ ]
353
+
354
+ <ChangelogInvaders
355
+ gameTitle="MY APP"
356
+ versions={["v1.0", "v2.0"]}
357
+ shipSprite={myShip}
358
+ shipColors={{
359
+ B: "#000000",
360
+ W: "#ffffff",
361
+ R: "#ff0000",
362
+ G: "#666666",
363
+ }}
364
+ />
365
+ ```
366
+
367
+ ## TypeScript
368
+
369
+ Full TypeScript support with exported types:
370
+
371
+ ```typescript
372
+ import {
373
+ ChangelogInvaders,
374
+ ChangelogInvadersConfig,
375
+ InvaderType,
376
+ PowerUpType,
377
+ ColorPalette,
378
+ EnemyItem,
379
+ PowerUpItem,
380
+ } from 'changelog-invaders'
381
+
382
+ const config: ChangelogInvadersConfig = {
383
+ gameTitle: "MY APP",
384
+ versions: ["v1.0", "v2.0"],
385
+ // ... fully typed
386
+ }
387
+ ```
388
+
389
+ ## Browser Support
390
+
391
+ - Chrome 80+
392
+ - Firefox 75+
393
+ - Safari 13+
394
+ - Edge 80+
395
+
396
+ Requires:
397
+ - Web Audio API (for sound)
398
+ - Canvas 2D API (for graphics)
399
+ - ResizeObserver (for responsive sizing)
400
+
401
+ ## Contributing
402
+
403
+ Contributions are welcome! Please read our contributing guidelines first.
404
+
405
+ ```bash
406
+ # Clone the repo
407
+ git clone https://github.com/kbanc85/changelog-invaders.git
408
+ cd changelog-invaders
409
+
410
+ # Install dependencies
411
+ npm install
412
+
413
+ # Start development
414
+ npm run dev
415
+
416
+ # Build
417
+ npm run build
418
+ ```
419
+
420
+ ## License
421
+
422
+ MIT Š [Kamil Banc](https://github.com/kbanc85)
423
+
424
+ ## Credits
425
+
426
+ Originally built for [Right Click Prompt](https://rightclickprompt.com) - a prompt management tool for AI workflows.
427
+
428
+ Created by **Kamil Banc** — follow for more developer tools:
429
+ - đŸĻ X/Twitter: [@kamilbanc](https://x.com/kamilbanc)
430
+ - đŸ’ģ GitHub: [@kbanc85](https://github.com/kbanc85)
431
+
432
+ ---
433
+
434
+ **Built with â¤ī¸ for developers who believe changelogs should be fun.**
435
+
436
+ ```
437
+ 👾 PEW PEW PEW 👾
438
+ ```