tunecamp 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.
Files changed (132) hide show
  1. package/.env.local +2 -0
  2. package/.vercel/README.txt +11 -0
  3. package/.vercel/project.json +1 -0
  4. package/LICENSE +22 -0
  5. package/README.md +554 -0
  6. package/dist/cli.d.ts +6 -0
  7. package/dist/cli.d.ts.map +1 -0
  8. package/dist/cli.js +172 -0
  9. package/dist/cli.js.map +1 -0
  10. package/dist/generator/embedGenerator.d.ts +38 -0
  11. package/dist/generator/embedGenerator.d.ts.map +1 -0
  12. package/dist/generator/embedGenerator.js +92 -0
  13. package/dist/generator/embedGenerator.js.map +1 -0
  14. package/dist/generator/feedGenerator.d.ts +50 -0
  15. package/dist/generator/feedGenerator.d.ts.map +1 -0
  16. package/dist/generator/feedGenerator.js +167 -0
  17. package/dist/generator/feedGenerator.js.map +1 -0
  18. package/dist/generator/podcastFeedGenerator.d.ts +54 -0
  19. package/dist/generator/podcastFeedGenerator.d.ts.map +1 -0
  20. package/dist/generator/podcastFeedGenerator.js +173 -0
  21. package/dist/generator/podcastFeedGenerator.js.map +1 -0
  22. package/dist/generator/proceduralCoverGenerator.d.ts +51 -0
  23. package/dist/generator/proceduralCoverGenerator.d.ts.map +1 -0
  24. package/dist/generator/proceduralCoverGenerator.js +228 -0
  25. package/dist/generator/proceduralCoverGenerator.js.map +1 -0
  26. package/dist/generator/siteGenerator.d.ts +55 -0
  27. package/dist/generator/siteGenerator.d.ts.map +1 -0
  28. package/dist/generator/siteGenerator.js +539 -0
  29. package/dist/generator/siteGenerator.js.map +1 -0
  30. package/dist/generator/templateEngine.d.ts +13 -0
  31. package/dist/generator/templateEngine.d.ts.map +1 -0
  32. package/dist/generator/templateEngine.js +146 -0
  33. package/dist/generator/templateEngine.js.map +1 -0
  34. package/dist/index.d.ts +12 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +32 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/parser/catalogParser.d.ts +13 -0
  39. package/dist/parser/catalogParser.d.ts.map +1 -0
  40. package/dist/parser/catalogParser.js +120 -0
  41. package/dist/parser/catalogParser.js.map +1 -0
  42. package/dist/tools/generate-codes.d.ts +14 -0
  43. package/dist/tools/generate-codes.d.ts.map +1 -0
  44. package/dist/tools/generate-codes.js +274 -0
  45. package/dist/tools/generate-codes.js.map +1 -0
  46. package/dist/tools/generate-sea-pair.d.ts +14 -0
  47. package/dist/tools/generate-sea-pair.d.ts.map +1 -0
  48. package/dist/tools/generate-sea-pair.js +111 -0
  49. package/dist/tools/generate-sea-pair.js.map +1 -0
  50. package/dist/types/index.d.ts +117 -0
  51. package/dist/types/index.d.ts.map +1 -0
  52. package/dist/types/index.js +5 -0
  53. package/dist/types/index.js.map +1 -0
  54. package/dist/utils/audioUtils.d.ts +9 -0
  55. package/dist/utils/audioUtils.d.ts.map +1 -0
  56. package/dist/utils/audioUtils.js +67 -0
  57. package/dist/utils/audioUtils.js.map +1 -0
  58. package/dist/utils/configUtils.d.ts +11 -0
  59. package/dist/utils/configUtils.d.ts.map +1 -0
  60. package/dist/utils/configUtils.js +50 -0
  61. package/dist/utils/configUtils.js.map +1 -0
  62. package/dist/utils/fileUtils.d.ts +14 -0
  63. package/dist/utils/fileUtils.d.ts.map +1 -0
  64. package/dist/utils/fileUtils.js +73 -0
  65. package/dist/utils/fileUtils.js.map +1 -0
  66. package/examples/artist-free/README.md +36 -0
  67. package/examples/artist-paycurtain/README.md +49 -0
  68. package/examples/label/README.md +33 -0
  69. package/gundb-keypair.json +8 -0
  70. package/logo.svg +30 -0
  71. package/package-lock.json +1176 -0
  72. package/package.json +42 -0
  73. package/public/assets/community-registry.js +291 -0
  74. package/public/assets/download-stats.js +263 -0
  75. package/public/assets/player.js +219 -0
  76. package/public/assets/style.css +1170 -0
  77. package/public/assets/theme-widget.js +353 -0
  78. package/public/assets/unlock-codes.js +225 -0
  79. package/public/atom.xml +22 -0
  80. package/public/catalog.m3u +3 -0
  81. package/public/feed.xml +22 -0
  82. package/public/image.png +0 -0
  83. package/public/index.html +249 -0
  84. package/public/logo.svg +30 -0
  85. package/public/releases/chirichetto/Homologo - Chirichetto.wav +0 -0
  86. package/public/releases/chirichetto/cover.png +0 -0
  87. package/public/releases/chirichetto/embed-code.txt +16 -0
  88. package/public/releases/chirichetto/embed-compact.txt +8 -0
  89. package/public/releases/chirichetto/embed.html +39 -0
  90. package/public/releases/chirichetto/index.html +389 -0
  91. package/public/releases/chirichetto/playlist.m3u +3 -0
  92. package/templates/dark/assets/community-registry.js +291 -0
  93. package/templates/dark/assets/download-stats.js +263 -0
  94. package/templates/dark/assets/player.js +219 -0
  95. package/templates/dark/assets/style.css +740 -0
  96. package/templates/dark/index.hbs +73 -0
  97. package/templates/dark/layout.hbs +84 -0
  98. package/templates/dark/release.hbs +212 -0
  99. package/templates/default/assets/community-registry.js +291 -0
  100. package/templates/default/assets/download-stats.js +263 -0
  101. package/templates/default/assets/player.js +219 -0
  102. package/templates/default/assets/style.css +1170 -0
  103. package/templates/default/assets/theme-widget.js +353 -0
  104. package/templates/default/assets/unlock-codes.js +225 -0
  105. package/templates/default/index.hbs +188 -0
  106. package/templates/default/layout.hbs +117 -0
  107. package/templates/default/release.hbs +553 -0
  108. package/templates/minimal/assets/community-registry.js +291 -0
  109. package/templates/minimal/assets/download-stats.js +263 -0
  110. package/templates/minimal/assets/player.js +219 -0
  111. package/templates/minimal/assets/style.css +796 -0
  112. package/templates/minimal/index.hbs +73 -0
  113. package/templates/minimal/layout.hbs +84 -0
  114. package/templates/minimal/release.hbs +212 -0
  115. package/templates/retro/assets/community-registry.js +291 -0
  116. package/templates/retro/assets/download-stats.js +263 -0
  117. package/templates/retro/assets/player.js +219 -0
  118. package/templates/retro/assets/style.css +872 -0
  119. package/templates/retro/index.hbs +73 -0
  120. package/templates/retro/layout.hbs +84 -0
  121. package/templates/retro/release.hbs +212 -0
  122. package/templates/translucent/assets/community-registry.js +291 -0
  123. package/templates/translucent/assets/download-stats.js +263 -0
  124. package/templates/translucent/assets/player.js +219 -0
  125. package/templates/translucent/assets/style.css +1352 -0
  126. package/templates/translucent/index.hbs +73 -0
  127. package/templates/translucent/layout.hbs +84 -0
  128. package/templates/translucent/release.hbs +212 -0
  129. package/website/community.html +492 -0
  130. package/website/index.html +195 -0
  131. package/website/styles.css +396 -0
  132. package/website/tunecamp.svg +30 -0
package/.env.local ADDED
@@ -0,0 +1,2 @@
1
+ # Created by Vercel CLI
2
+ VERCEL_OIDC_TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Im1yay00MzAyZWMxYjY3MGY0OGE5OGFkNjFkYWRlNGEyM2JlNyJ9.eyJpc3MiOiJodHRwczovL29pZGMudmVyY2VsLmNvbS9zY29icnUtcy10ZWFtIiwic3ViIjoib3duZXI6c2NvYnJ1LXMtdGVhbTpwcm9qZWN0OmhvbW9sb2dvbXVzaWM6ZW52aXJvbm1lbnQ6ZGV2ZWxvcG1lbnQiLCJzY29wZSI6Im93bmVyOnNjb2JydS1zLXRlYW06cHJvamVjdDpob21vbG9nb211c2ljOmVudmlyb25tZW50OmRldmVsb3BtZW50IiwiYXVkIjoiaHR0cHM6Ly92ZXJjZWwuY29tL3Njb2JydS1zLXRlYW0iLCJvd25lciI6InNjb2JydS1zLXRlYW0iLCJvd25lcl9pZCI6InRlYW1fUU1vUlcwTGY5OXpiQUZPdnlzaHdycE9HIiwicHJvamVjdCI6ImhvbW9sb2dvbXVzaWMiLCJwcm9qZWN0X2lkIjoicHJqX0JiNXVkV0NPUUI1ZUd6dHlyaXZ2bUFPU2V1aXIiLCJlbnZpcm9ubWVudCI6ImRldmVsb3BtZW50IiwicGxhbiI6ImhvYmJ5IiwidXNlcl9pZCI6IkpITk02UkMyN2lEMHMxQ1JSa3o2dEJQRSIsIm5iZiI6MTc2ODM5NzczOSwiaWF0IjoxNzY4Mzk3NzM5LCJleHAiOjE3Njg0NDA5Mzl9.hoIwo5r8MYxCSfq-jL0rZgFr1zaHI0qaks2JMBpjVQ3HbrdSJMitQ8dAdO0N9DwZVxRLF7j_tPozrf8BNje03Cg6rmEJMRZyfqvAIwUO3HBBIsxSs5hvh5L4L_jIZgz5pAHk_tgF7N8I4G0N8LCmpnEaRHRmdeaACxExGUQlkU9YkGYFWNcCyfo4YBY6_-Ej_HLBvv2Sfo0gg_AMpSv8mBkK701tAhwyCtDIhTTK9ORTUwnRU5CmYTVIARgWaW30W_52FrfimmNOBZz-qVbKp3rkCg6r1w0CVwGg3TUqI1T-IOkh98SRvvIRCjzEO-g-frIytT7T19Ab-pUy8Yv35A"
@@ -0,0 +1,11 @@
1
+ > Why do I have a folder named ".vercel" in my project?
2
+ The ".vercel" folder is created when you link a directory to a Vercel project.
3
+
4
+ > What does the "project.json" file contain?
5
+ The "project.json" file contains:
6
+ - The ID of the Vercel project that you linked ("projectId")
7
+ - The ID of the user or team your Vercel project is owned by ("orgId")
8
+
9
+ > Should I commit the ".vercel" folder?
10
+ No, you should not share the ".vercel" folder with anyone.
11
+ Upon creation, it will be automatically added to your ".gitignore" file.
@@ -0,0 +1 @@
1
+ {"projectId":"prj_Bb5udWCOQB5eGztyrivvmAOSeuir","orgId":"team_QMoRW0Lf99zbAFOvyshwrpOG","projectName":"homologomusic"}
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Tunecamp Contributors
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.
22
+
package/README.md ADDED
@@ -0,0 +1,554 @@
1
+ <img src="./logo.svg" alt="Tunecamp" width="200" height="200" style="display: block; margin-bottom: 20px; margin-top: 20px; align-items: center; justify-content: center; margin-left: auto; margin-right: auto;">
2
+
3
+ # Tunecamp
4
+
5
+ A modern static site generator for musicians and music labels, written in JavaScript/TypeScript.
6
+
7
+ Inspired by [Faircamp](https://simonrepp.com/faircamp/), this tool helps you create beautiful, fast static websites to showcase your music without the need for databases or complex hosting.
8
+
9
+ ## Features
10
+
11
+ - 🎵 **Audio-first**: Automatically reads metadata from your audio files
12
+ - 📦 **Zero database**: Pure static HTML generation
13
+ - 🎨 **Customizable**: Template-based theming system
14
+ - 🚀 **Fast**: Static sites that load instantly
15
+ - 📱 **Responsive**: Mobile-friendly out of the box
16
+ - 🔊 **Built-in player**: Modern HTML5 audio player
17
+ - 💿 **Multi-format**: Support for MP3, FLAC, OGG, WAV, and more
18
+ - 🏷️ **Flexible metadata**: YAML-based configuration files
19
+ - 📡 **RSS/Atom feeds**: Automatic feed generation for releases
20
+ - 🎙️ **Podcast support**: Generate podcast RSS feeds
21
+ - 📦 **Embed widgets**: Embeddable HTML widgets for releases
22
+ - 🎶 **M3U playlists**: Automatic playlist generation
23
+ - 🎨 **Procedural covers**: Auto-generate cover art if missing
24
+ - 🔐 **Unlock codes**: Decentralized download protection via GunDB
25
+ - 🏢 **Label mode**: Multi-artist catalog support
26
+
27
+ ## Quick Start
28
+
29
+ ### Installation
30
+
31
+ ```bash
32
+ npm install -g tunecamp
33
+ # or
34
+ yarn global add tunecamp
35
+ ```
36
+
37
+ ### Basic Usage
38
+
39
+ 1. **Create your catalog structure:**
40
+
41
+ ```
42
+ my-music/
43
+ ├── catalog.yaml
44
+ ├── artist.yaml
45
+ └── releases/
46
+ └── my-first-album/
47
+ ├── release.yaml
48
+ ├── cover.jpg
49
+ └── tracks/
50
+ ├── 01-track-one.mp3
51
+ ├── 02-track-two.mp3
52
+ └── track.yaml (optional)
53
+ ```
54
+
55
+ 2. **Configure your catalog:**
56
+
57
+ ```yaml
58
+ # catalog.yaml
59
+ title: "My Music Catalog"
60
+ description: "Independent music releases"
61
+ url: "https://mymusic.com"
62
+ ```
63
+
64
+ ```yaml
65
+ # artist.yaml
66
+ name: "Artist Name"
67
+ bio: "Artist biography goes here"
68
+ links:
69
+ - bandcamp: "https://artistname.bandcamp.com"
70
+ - spotify: "https://open.spotify.com/artist/..."
71
+ donationLinks:
72
+ - platform: "PayPal"
73
+ url: "https://paypal.me/artistname"
74
+ description: "Support the artist"
75
+ - platform: "Ko-fi"
76
+ url: "https://ko-fi.com/artistname"
77
+ description: "Buy me a coffee"
78
+ ```
79
+
80
+ ```yaml
81
+ # releases/my-first-album/release.yaml
82
+ title: "My First Album"
83
+ date: "2024-01-15"
84
+ description: "An amazing debut album"
85
+ download: free # Options: free, paycurtain, codes, none
86
+ price: 10.00
87
+ paypalLink: "https://paypal.me/artistname/10"
88
+ stripeLink: "https://buy.stripe.com/..."
89
+ license: "cc-by" # Options: copyright, cc-by, cc-by-sa, cc-by-nc, cc-by-nc-sa, cc-by-nc-nd, cc-by-nd, public-domain
90
+ unlisted: false # Set to true to hide from index but keep accessible via direct link
91
+ ```
92
+
93
+ 3. **Generate your site:**
94
+
95
+ ```bash
96
+ tunecamp build ./my-music --output ./public
97
+ ```
98
+
99
+ 4. **Deploy:**
100
+
101
+ Upload the `public` folder to any static hosting service (Netlify, Vercel, GitHub Pages, etc.)
102
+
103
+ ## Deployment
104
+
105
+ ### Deploying to Different Platforms
106
+
107
+ The `basePath` configuration is essential for correct asset loading when your site is deployed.
108
+
109
+ #### Root Domain Deployment
110
+
111
+ For deployments at the root of a domain (e.g., `mymusic.com`):
112
+
113
+ ```yaml
114
+ # catalog.yaml
115
+ basePath: "" # or omit the field
116
+ ```
117
+
118
+ #### Subdirectory Deployment
119
+
120
+ For deployments in a subdirectory (e.g., GitHub Pages at `username.github.io/my-music`):
121
+
122
+ ```yaml
123
+ # catalog.yaml
124
+ basePath: "/my-music"
125
+ ```
126
+
127
+ #### Platform-Specific Examples
128
+
129
+ **GitHub Pages (Project Site)**
130
+ ```yaml
131
+ basePath: "/repository-name"
132
+ ```
133
+
134
+ **Netlify/Vercel (Custom Domain)**
135
+ ```yaml
136
+ basePath: ""
137
+ ```
138
+
139
+ **Netlify/Vercel (Subdirectory)**
140
+ ```yaml
141
+ basePath: "/subfolder"
142
+ ```
143
+
144
+ You can also override the `basePath` at build time:
145
+ ```bash
146
+ tunecamp build ./my-music --output ./public --basePath /my-music
147
+ ```
148
+
149
+ ## Configuration Files
150
+
151
+ ### catalog.yaml
152
+
153
+ Global catalog configuration:
154
+
155
+ ```yaml
156
+ title: "Catalog Title"
157
+ description: "Catalog description"
158
+ url: "https://yoursite.com"
159
+ basePath: "" # Base path for deployment (empty for root, "/repo-name" for subdirectory)
160
+ theme: "default" # or custom theme name
161
+ language: "en"
162
+ headerImage: "header.png" # Optional: Image to replace title in header (Bandcamp-style)
163
+ customFont: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" # Optional: Custom font URL (Google Fonts, etc.) or local file path
164
+ customCSS: "custom.css" # Optional: Custom CSS file path (relative to input directory) or external URL
165
+ labelMode: false # Set to true for multi-artist label catalogs
166
+ podcast: # Optional podcast feed configuration
167
+ enabled: true
168
+ title: "My Podcast"
169
+ description: "Podcast description"
170
+ author: "Artist Name"
171
+ email: "email@example.com"
172
+ category: "Music"
173
+ image: "podcast-cover.jpg"
174
+ explicit: false
175
+ ```
176
+
177
+ **Important**: The `basePath` option is crucial when deploying to subdirectories (e.g., GitHub Pages). If your site will be at `username.github.io/my-music/`, set `basePath: "/my-music"`.
178
+
179
+ ### artist.yaml
180
+
181
+ Artist information:
182
+
183
+ ```yaml
184
+ name: "Artist Name"
185
+ bio: "Biography text"
186
+ photo: "artist.jpg"
187
+ links:
188
+ - website: "https://..."
189
+ - bandcamp: "https://..."
190
+ - spotify: "https://..."
191
+ - instagram: "https://..."
192
+ ```
193
+
194
+ ### release.yaml
195
+
196
+ Individual release configuration:
197
+
198
+ ```yaml
199
+ title: "Album Title"
200
+ date: "2024-01-15"
201
+ description: "Album description"
202
+ cover: "cover.jpg" # Optional, auto-detected (procedural cover generated if missing)
203
+ download: "free" # free, paycurtain, codes, none
204
+ price: 10.00 # For paycurtain mode
205
+ paypalLink: "https://paypal.me/artistname/10" # Optional PayPal link
206
+ stripeLink: "https://buy.stripe.com/..." # Optional Stripe link
207
+ license: "cc-by" # License type
208
+ genres:
209
+ - "Electronic"
210
+ - "Ambient"
211
+ credits:
212
+ - role: "Producer"
213
+ name: "Producer Name"
214
+ unlisted: false # Set to true to hide from index/feeds but keep accessible via direct link
215
+ artistSlug: "artist-name" # For label mode: associate release with an artist
216
+ unlockCodes: # For download: codes mode
217
+ enabled: true
218
+ namespace: tunecamp
219
+ peers: # Optional custom GunDB peers
220
+ - "https://your-relay.com/gun"
221
+ ```
222
+
223
+ ### track.yaml
224
+
225
+ Optional track-level metadata overrides:
226
+
227
+ ```yaml
228
+ tracks:
229
+ - file: "01-track.mp3"
230
+ title: "Custom Title"
231
+ description: "Track notes"
232
+ ```
233
+
234
+ ## CLI Commands
235
+
236
+ ```bash
237
+ # Build a catalog
238
+ tunecamp build <input-dir> --output <output-dir>
239
+
240
+ # Build with custom base path (overrides catalog.yaml)
241
+ tunecamp build <input-dir> --output <output-dir> --basePath /my-music
242
+
243
+ # Build with custom theme (overrides catalog.yaml)
244
+ tunecamp build <input-dir> --output <output-dir> --theme dark
245
+
246
+ # Serve locally
247
+ tunecamp serve <output-dir> --port 3000
248
+
249
+ # Initialize a new catalog
250
+ tunecamp init <directory>
251
+ ```
252
+
253
+ ## Development Modes
254
+
255
+ ### Free Downloads
256
+
257
+ ```yaml
258
+ download: free
259
+ ```
260
+
261
+ All tracks available for immediate download.
262
+
263
+ ### Soft Paycurtain (Honor System)
264
+
265
+ ```yaml
266
+ download: paycurtain
267
+ price: 10.00
268
+ paypalLink: "https://paypal.me/artistname/10"
269
+ stripeLink: "https://buy.stripe.com/..."
270
+ ```
271
+
272
+ Pay-what-you-want with suggested price. Users can download for free, but are encouraged to support the artist.
273
+
274
+ **⚠️ Important**: This is an **honor system** - all files remain technically downloadable. PayPal and Stripe links are simply displayed as buttons; there is no payment verification or gating. If you need real download protection, use the `codes` mode instead.
275
+
276
+ ### Unlock Codes (Decentralized Protection)
277
+
278
+ ```yaml
279
+ download: codes
280
+ unlockCodes:
281
+ enabled: true
282
+ namespace: tunecamp # Optional, default: tunecamp
283
+ ```
284
+
285
+ Protect downloads with unlock codes validated via GunDB (decentralized, no backend required). See [Unlock Codes Guide](./docs/unlock-codes-guida.md) for details.
286
+
287
+ **⚠️ Important - Self-Hosting Required**: The code generation tool (`generate-codes.ts`) must be run locally on your machine where you have access to the Tunecamp source code. If you deploy only the static HTML output (e.g., to Vercel, Netlify, GitHub Pages), you won't be able to generate new codes from the deployed site - it's just static HTML.
288
+
289
+ **Workflow:**
290
+ 1. Run `tunecamp build` locally
291
+ 2. Generate codes locally: `npx ts-node src/tools/generate-codes.ts <release-slug> --count 20`
292
+ 3. Deploy the static `public/` folder to your hosting
293
+ 4. Distribute the generated codes to your customers
294
+
295
+ Generate codes using:
296
+ ```bash
297
+ npx ts-node src/tools/generate-codes.ts <release-slug> --count 20
298
+ ```
299
+
300
+ ### Download Statistics (Public GunDB)
301
+
302
+ Tunecamp automatically tracks and displays download counts for your releases using a public GunDB space. This works out of the box with no configuration required:
303
+
304
+ - **Real-time counter**: Download counts update in real-time across all visitors
305
+ - **Decentralized**: No server required - data is stored on public GunDB peers
306
+ - **Anonymous**: No user tracking, just simple counters
307
+ - **Visible to all**: Download counts are shown on each release page
308
+
309
+ The download counter increments when users click "Download All" or individual track download buttons.
310
+
311
+ ### Community Registry (Decentralized Directory)
312
+
313
+ Tunecamp includes an automatic community registry powered by GunDB. When someone visits your Tunecamp site, it gets automatically registered in a decentralized directory of Tunecamp sites.
314
+
315
+ **Features:**
316
+ - **Automatic registration**: No sign-up needed - your site is discovered when visited
317
+ - **Decentralized**: Data stored on public GunDB peers, no central server
318
+ - **Real-time**: New sites appear instantly in the community directory
319
+ - **Privacy-respecting**: Only public info is shared (URL, title, artist name)
320
+
321
+ **How it works:**
322
+ 1. Build and deploy your Tunecamp site
323
+ 2. When a visitor loads your site, it registers automatically
324
+ 3. Your site appears in the [Tunecamp Community](https://tunecamp.dev/community.html) directory
325
+ 4. Discover other independent artists using Tunecamp!
326
+
327
+ You can disable auto-registration by removing the `community-registry.js` script from your build output.
328
+
329
+ ## Supported Audio Formats
330
+
331
+ - MP3
332
+ - FLAC
333
+ - OGG Vorbis
334
+ - WAV
335
+ - M4A/AAC
336
+ - OPUS
337
+
338
+ ## Themes
339
+
340
+ tunecamp includes 5 ready-to-use themes:
341
+
342
+ ### Available Themes
343
+
344
+ 1. **default** - Modern dark theme with purple/blue gradients
345
+ 2. **minimal** - Clean light theme with lots of white space
346
+ 3. **dark** - Aggressive dark theme with red accents (perfect for rock/metal)
347
+ 4. **retro** - 80s-inspired theme with neon colors (perfect for synthwave/vaporwave)
348
+ 5. **translucent** - Glassmorphism theme with blur effects and transparency (perfect for ambient/electronic)
349
+
350
+ ### Using a Theme
351
+
352
+ Specify the theme in your `catalog.yaml`:
353
+
354
+ ```yaml
355
+ catalog:
356
+ title: "My Music"
357
+ theme: "translucent" # Change to: default, minimal, dark, retro, or translucent
358
+ ```
359
+
360
+ Or use the `--theme` option when building:
361
+
362
+ ```bash
363
+ tunecamp build ./my-music --output ./public --theme translucent
364
+ ```
365
+
366
+ ### Creating Custom Themes
367
+
368
+ Create your own theme by adding a folder in the `templates/` directory:
369
+
370
+ ```
371
+ templates/my-theme/
372
+ ├── layout.hbs
373
+ ├── index.hbs
374
+ ├── release.hbs
375
+ └── assets/
376
+ ├── style.css
377
+ └── player.js
378
+ ```
379
+
380
+ For detailed information about themes, see [Theme Documentation](./docs/THEMES.md).
381
+
382
+ ## Generated Files
383
+
384
+ When you build a catalog, Tunecamp automatically generates:
385
+
386
+ - **HTML pages**: `index.html` and release pages
387
+ - **RSS/Atom feeds**: `feed.xml` (RSS 2.0) and `atom.xml`
388
+ - **Podcast feed**: `podcast.xml` (if enabled in config)
389
+ - **M3U playlists**: `playlist.m3u` for each release and `catalog.m3u` for the entire catalog
390
+ - **Embed widgets**: `embed.html`, `embed-code.txt`, and `embed-compact.txt` for each release
391
+ - **Procedural covers**: Auto-generated SVG covers if release has no cover art
392
+
393
+ ### Embed Widgets
394
+
395
+ Each release gets embeddable HTML widgets that you can use on other websites:
396
+
397
+ - **Full embed**: Complete widget with cover, info, and audio player
398
+ - **Compact embed**: Smaller inline widget
399
+ - **Iframe embed**: Standalone embed page for iframe embedding
400
+
401
+ Access embed codes at: `releases/<release-slug>/embed-code.txt`
402
+
403
+ **Share & Embed Section**: Each release page includes a "Share & Embed" section at the top with:
404
+ - **Catalog link**: Quick navigation back to the main catalog
405
+ - **RSS/Atom feeds**: Direct links to `feed.xml` (RSS 2.0) and `atom.xml` for feed readers
406
+ - **Copy link**: One-click button to copy the release URL to clipboard
407
+ - **Embed code**: Modal viewer with tabs for full and compact embed codes, with copy functionality
408
+ - All embed codes are accessible directly from the page without needing to navigate to text files
409
+
410
+ ### RSS/Atom Feeds
411
+
412
+ Automatic feed generation for:
413
+ - RSS 2.0 feed at `feed.xml`
414
+ - Atom feed at `atom.xml`
415
+ - Podcast RSS feed at `podcast.xml` (if enabled)
416
+
417
+ All feeds include proper metadata, cover images, and track information.
418
+
419
+ ### M3U Playlists
420
+
421
+ Playlists are generated for:
422
+ - Each individual release: `releases/<release-slug>/playlist.m3u`
423
+ - Entire catalog: `catalog.m3u`
424
+
425
+ Playlists include track metadata (duration, artist, title) and can be opened in any music player.
426
+
427
+ ## Examples
428
+
429
+ Check the `/examples` directory for complete catalog examples:
430
+
431
+ - **artist-free**: Simple artist catalog with free downloads
432
+ - **artist-paycurtain**: Artist with pay-what-you-want model
433
+ - **label**: Multi-artist label catalog
434
+
435
+ ## API Usage
436
+
437
+ You can also use tunecamp programmatically:
438
+
439
+ ```javascript
440
+ import { Tunecamp } from "tunecamp";
441
+
442
+ const generator = new Tunecamp({
443
+ inputDir: "./my-music",
444
+ outputDir: "./public",
445
+ theme: "default",
446
+ });
447
+
448
+ await generator.build();
449
+ ```
450
+
451
+ ## Contributing
452
+
453
+ Contributions are welcome! Please feel free to submit a Pull Request.
454
+
455
+ ## License
456
+
457
+ MIT License - see LICENSE file for details
458
+
459
+ ## Credits
460
+
461
+ Inspired by [Faircamp](https://simonrepp.com/faircamp/) by Simon Repp.
462
+
463
+ ## Advanced Features
464
+
465
+ ### Label Mode (Multi-Artist)
466
+
467
+ Enable label mode to create catalogs with multiple artists:
468
+
469
+ ```yaml
470
+ # catalog.yaml
471
+ labelMode: true
472
+ ```
473
+
474
+ Create `artists/` directory with artist YAML files. Each release can be associated with an artist using `artistSlug` in `release.yaml`.
475
+
476
+ ### Unlisted Releases
477
+
478
+ Hide releases from the main index and feeds while keeping them accessible via direct link:
479
+
480
+ ```yaml
481
+ # release.yaml
482
+ unlisted: true
483
+ ```
484
+
485
+ Useful for:
486
+ - Work-in-progress releases
487
+ - Exclusive content
488
+ - Testing releases before public launch
489
+
490
+ ### Procedural Cover Generation
491
+
492
+ If a release has no cover art, Tunecamp automatically generates a procedural SVG cover based on the release title and artist name. The cover uses deterministic algorithms (no AI) to create unique, consistent artwork.
493
+
494
+ ### Header Image (Bandcamp-style)
495
+
496
+ Replace the text title in the header with a custom image, similar to Bandcamp:
497
+
498
+ ```yaml
499
+ # catalog.yaml
500
+ headerImage: "header.png" # Path relative to catalog directory
501
+ ```
502
+
503
+ The header image will be displayed prominently at the top of all pages. If `headerImage` is set, the text title and description are hidden to avoid redundancy.
504
+
505
+ ### Custom Font
506
+
507
+ Add custom fonts from Google Fonts or other sources:
508
+
509
+ ```yaml
510
+ # catalog.yaml
511
+ customFont: "https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap"
512
+ ```
513
+
514
+ The font will be loaded before the theme CSS, allowing you to use it in your custom CSS.
515
+
516
+ ### Custom CSS
517
+
518
+ Add custom CSS to override or extend theme styles. You can use either a local file or an external URL:
519
+
520
+ ```yaml
521
+ # catalog.yaml
522
+ # Local file (copied to assets/ during build)
523
+ customCSS: "custom.css"
524
+
525
+ # Or external URL (CDN, etc.)
526
+ customCSS: "https://cdn.jsdelivr.net/npm/water.css@2/out/water.css"
527
+ ```
528
+
529
+ Local CSS files are copied to the `assets/` directory during build. The custom CSS is loaded after the theme CSS, so your styles will override the default theme.
530
+
531
+ **Example custom.css:**
532
+
533
+ ```css
534
+ /* Apply custom font to body */
535
+ body {
536
+ font-family: 'Inter', sans-serif;
537
+ }
538
+
539
+ /* Custom header image styling */
540
+ .header-image {
541
+ max-height: 300px;
542
+ border-radius: 8px;
543
+ }
544
+ ```
545
+
546
+ ## Links
547
+
548
+ - [Documentation](./docs)
549
+ - [Deployment Guide](./docs/DEPLOYMENT.md)
550
+ - [API Documentation](./docs/API.md)
551
+ - [Theme Showcase](./docs/THEME_SHOWCASE.md)
552
+ - [Unlock Codes Guide](./docs/unlock-codes-guida.md)
553
+ - [Examples](./examples)
554
+ - [Changelog](./CHANGELOG.md)
package/dist/cli.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Command-line interface for Tunecamp
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;GAEG"}