+231
package-lock.json
+231
package-lock.json
···
11
"@astrojs/check": "^0.9.4",
12
"@atproto/api": "^0.16.2",
13
"@atproto/xrpc": "^0.7.1",
14
"@tailwindcss/typography": "^0.5.16",
15
"@tailwindcss/vite": "^4.1.11",
16
"@types/node": "^24.2.0",
···
177
"yaml": "^2.5.0"
178
}
179
},
180
"node_modules/@atproto/api": {
181
"version": "0.16.2",
182
"resolved": "https://registry.npmjs.org/@atproto/api/-/api-0.16.2.tgz",
···
334
},
335
"engines": {
336
"node": ">=6.9.0"
337
}
338
},
339
"node_modules/@capsizecss/unpack": {
···
1269
},
1270
"engines": {
1271
"node": ">= 8"
1272
}
1273
},
1274
"node_modules/@oslojs/encoding": {
···
2850
"url": "https://github.com/sponsors/wooorm"
2851
}
2852
},
2853
"node_modules/defu": {
2854
"version": "6.1.4",
2855
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
···
2932
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
2933
"license": "MIT"
2934
},
2935
"node_modules/dotenv": {
2936
"version": "17.2.1",
2937
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz",
···
3067
"funding": {
3068
"url": "https://github.com/sponsors/sindresorhus"
3069
}
3070
},
3071
"node_modules/estree-walker": {
3072
"version": "3.0.3",
···
3505
"url": "https://github.com/sponsors/wooorm"
3506
}
3507
},
3508
"node_modules/http-cache-semantics": {
3509
"version": "4.2.0",
3510
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
···
3621
"url": "https://github.com/sponsors/sindresorhus"
3622
}
3623
},
3624
"node_modules/is-wsl": {
3625
"version": "3.1.0",
3626
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
···
3674
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz",
3675
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
3676
"license": "MIT"
3677
},
3678
"node_modules/kleur": {
3679
"version": "4.1.5",
···
5089
"url": "https://github.com/sponsors/wooorm"
5090
}
5091
},
5092
"node_modules/parse5": {
5093
"version": "7.3.0",
5094
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
···
5598
"license": "MIT",
5599
"dependencies": {
5600
"queue-microtask": "^1.2.2"
5601
}
5602
},
5603
"node_modules/semver": {
···
11
"@astrojs/check": "^0.9.4",
12
"@atproto/api": "^0.16.2",
13
"@atproto/xrpc": "^0.7.1",
14
+
"@nulfrost/leaflet-loader-astro": "^1.1.0",
15
"@tailwindcss/typography": "^0.5.16",
16
"@tailwindcss/vite": "^4.1.11",
17
"@types/node": "^24.2.0",
···
178
"yaml": "^2.5.0"
179
}
180
},
181
+
"node_modules/@atcute/client": {
182
+
"version": "4.0.3",
183
+
"resolved": "https://registry.npmjs.org/@atcute/client/-/client-4.0.3.tgz",
184
+
"integrity": "sha512-RIOZWFVLca/HiPAAUDqQPOdOreCxTbL5cb+WUf5yqQOKIu5yEAP3eksinmlLmgIrlr5qVOE7brazUUzaskFCfw==",
185
+
"license": "MIT",
186
+
"dependencies": {
187
+
"@atcute/identity": "^1.0.2",
188
+
"@atcute/lexicons": "^1.0.3"
189
+
}
190
+
},
191
+
"node_modules/@atcute/identity": {
192
+
"version": "1.0.3",
193
+
"resolved": "https://registry.npmjs.org/@atcute/identity/-/identity-1.0.3.tgz",
194
+
"integrity": "sha512-mNMxbKHFGys03A8JXKk0KfMBzdd0vrYMzZZWjpw1nYTs0+ea6bo5S1hwqVUZxHdo1gFHSe/t63jxQIF4yL9aKw==",
195
+
"license": "0BSD",
196
+
"dependencies": {
197
+
"@atcute/lexicons": "^1.0.4",
198
+
"@badrap/valita": "^0.4.5"
199
+
}
200
+
},
201
+
"node_modules/@atcute/lexicons": {
202
+
"version": "1.1.0",
203
+
"resolved": "https://registry.npmjs.org/@atcute/lexicons/-/lexicons-1.1.0.tgz",
204
+
"integrity": "sha512-LFqwnria78xLYb62Ri/+WwQpUTgZp2DuyolNGIIOV1dpiKhFFFh//nscHMA6IExFLQRqWDs3tTjy7zv0h3sf1Q==",
205
+
"license": "0BSD",
206
+
"dependencies": {
207
+
"esm-env": "^1.2.2"
208
+
}
209
+
},
210
"node_modules/@atproto/api": {
211
"version": "0.16.2",
212
"resolved": "https://registry.npmjs.org/@atproto/api/-/api-0.16.2.tgz",
···
364
},
365
"engines": {
366
"node": ">=6.9.0"
367
+
}
368
+
},
369
+
"node_modules/@badrap/valita": {
370
+
"version": "0.4.6",
371
+
"resolved": "https://registry.npmjs.org/@badrap/valita/-/valita-0.4.6.tgz",
372
+
"integrity": "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg==",
373
+
"license": "MIT",
374
+
"engines": {
375
+
"node": ">= 18"
376
}
377
},
378
"node_modules/@capsizecss/unpack": {
···
1308
},
1309
"engines": {
1310
"node": ">= 8"
1311
+
}
1312
+
},
1313
+
"node_modules/@nulfrost/leaflet-loader-astro": {
1314
+
"version": "1.1.0",
1315
+
"resolved": "https://registry.npmjs.org/@nulfrost/leaflet-loader-astro/-/leaflet-loader-astro-1.1.0.tgz",
1316
+
"integrity": "sha512-A6ONOmds3/3pVFfa+YdpC5YMfOF1shvczAOnSWfVtUYz3bl3NRz26KieUrGW+26iVPgUtHPRLQOfygImrLrhYw==",
1317
+
"license": "MIT",
1318
+
"dependencies": {
1319
+
"@atcute/client": "^4.0.3",
1320
+
"@atcute/lexicons": "^1.1.0",
1321
+
"@atproto/api": "^0.16.2",
1322
+
"katex": "^0.16.22",
1323
+
"sanitize-html": "^2.17.0"
1324
}
1325
},
1326
"node_modules/@oslojs/encoding": {
···
2902
"url": "https://github.com/sponsors/wooorm"
2903
}
2904
},
2905
+
"node_modules/deepmerge": {
2906
+
"version": "4.3.1",
2907
+
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
2908
+
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
2909
+
"license": "MIT",
2910
+
"engines": {
2911
+
"node": ">=0.10.0"
2912
+
}
2913
+
},
2914
"node_modules/defu": {
2915
"version": "6.1.4",
2916
"resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz",
···
2993
"integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
2994
"license": "MIT"
2995
},
2996
+
"node_modules/dom-serializer": {
2997
+
"version": "2.0.0",
2998
+
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
2999
+
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
3000
+
"license": "MIT",
3001
+
"dependencies": {
3002
+
"domelementtype": "^2.3.0",
3003
+
"domhandler": "^5.0.2",
3004
+
"entities": "^4.2.0"
3005
+
},
3006
+
"funding": {
3007
+
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
3008
+
}
3009
+
},
3010
+
"node_modules/dom-serializer/node_modules/entities": {
3011
+
"version": "4.5.0",
3012
+
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
3013
+
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
3014
+
"license": "BSD-2-Clause",
3015
+
"engines": {
3016
+
"node": ">=0.12"
3017
+
},
3018
+
"funding": {
3019
+
"url": "https://github.com/fb55/entities?sponsor=1"
3020
+
}
3021
+
},
3022
+
"node_modules/domelementtype": {
3023
+
"version": "2.3.0",
3024
+
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
3025
+
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
3026
+
"funding": [
3027
+
{
3028
+
"type": "github",
3029
+
"url": "https://github.com/sponsors/fb55"
3030
+
}
3031
+
],
3032
+
"license": "BSD-2-Clause"
3033
+
},
3034
+
"node_modules/domhandler": {
3035
+
"version": "5.0.3",
3036
+
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
3037
+
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
3038
+
"license": "BSD-2-Clause",
3039
+
"dependencies": {
3040
+
"domelementtype": "^2.3.0"
3041
+
},
3042
+
"engines": {
3043
+
"node": ">= 4"
3044
+
},
3045
+
"funding": {
3046
+
"url": "https://github.com/fb55/domhandler?sponsor=1"
3047
+
}
3048
+
},
3049
+
"node_modules/domutils": {
3050
+
"version": "3.2.2",
3051
+
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
3052
+
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
3053
+
"license": "BSD-2-Clause",
3054
+
"dependencies": {
3055
+
"dom-serializer": "^2.0.0",
3056
+
"domelementtype": "^2.3.0",
3057
+
"domhandler": "^5.0.3"
3058
+
},
3059
+
"funding": {
3060
+
"url": "https://github.com/fb55/domutils?sponsor=1"
3061
+
}
3062
+
},
3063
"node_modules/dotenv": {
3064
"version": "17.2.1",
3065
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz",
···
3195
"funding": {
3196
"url": "https://github.com/sponsors/sindresorhus"
3197
}
3198
+
},
3199
+
"node_modules/esm-env": {
3200
+
"version": "1.2.2",
3201
+
"resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz",
3202
+
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==",
3203
+
"license": "MIT"
3204
},
3205
"node_modules/estree-walker": {
3206
"version": "3.0.3",
···
3639
"url": "https://github.com/sponsors/wooorm"
3640
}
3641
},
3642
+
"node_modules/htmlparser2": {
3643
+
"version": "8.0.2",
3644
+
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
3645
+
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
3646
+
"funding": [
3647
+
"https://github.com/fb55/htmlparser2?sponsor=1",
3648
+
{
3649
+
"type": "github",
3650
+
"url": "https://github.com/sponsors/fb55"
3651
+
}
3652
+
],
3653
+
"license": "MIT",
3654
+
"dependencies": {
3655
+
"domelementtype": "^2.3.0",
3656
+
"domhandler": "^5.0.3",
3657
+
"domutils": "^3.0.1",
3658
+
"entities": "^4.4.0"
3659
+
}
3660
+
},
3661
+
"node_modules/htmlparser2/node_modules/entities": {
3662
+
"version": "4.5.0",
3663
+
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
3664
+
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
3665
+
"license": "BSD-2-Clause",
3666
+
"engines": {
3667
+
"node": ">=0.12"
3668
+
},
3669
+
"funding": {
3670
+
"url": "https://github.com/fb55/entities?sponsor=1"
3671
+
}
3672
+
},
3673
"node_modules/http-cache-semantics": {
3674
"version": "4.2.0",
3675
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
···
3786
"url": "https://github.com/sponsors/sindresorhus"
3787
}
3788
},
3789
+
"node_modules/is-plain-object": {
3790
+
"version": "5.0.0",
3791
+
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz",
3792
+
"integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==",
3793
+
"license": "MIT",
3794
+
"engines": {
3795
+
"node": ">=0.10.0"
3796
+
}
3797
+
},
3798
"node_modules/is-wsl": {
3799
"version": "3.1.0",
3800
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
···
3848
"resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz",
3849
"integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==",
3850
"license": "MIT"
3851
+
},
3852
+
"node_modules/katex": {
3853
+
"version": "0.16.22",
3854
+
"resolved": "https://registry.npmjs.org/katex/-/katex-0.16.22.tgz",
3855
+
"integrity": "sha512-XCHRdUw4lf3SKBaJe4EvgqIuWwkPSo9XoeO8GjQW94Bp7TWv9hNhzZjZ+OH9yf1UmLygb7DIT5GSFQiyt16zYg==",
3856
+
"funding": [
3857
+
"https://opencollective.com/katex",
3858
+
"https://github.com/sponsors/katex"
3859
+
],
3860
+
"license": "MIT",
3861
+
"dependencies": {
3862
+
"commander": "^8.3.0"
3863
+
},
3864
+
"bin": {
3865
+
"katex": "cli.js"
3866
+
}
3867
+
},
3868
+
"node_modules/katex/node_modules/commander": {
3869
+
"version": "8.3.0",
3870
+
"resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
3871
+
"integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
3872
+
"license": "MIT",
3873
+
"engines": {
3874
+
"node": ">= 12"
3875
+
}
3876
},
3877
"node_modules/kleur": {
3878
"version": "4.1.5",
···
5288
"url": "https://github.com/sponsors/wooorm"
5289
}
5290
},
5291
+
"node_modules/parse-srcset": {
5292
+
"version": "1.0.2",
5293
+
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
5294
+
"integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==",
5295
+
"license": "MIT"
5296
+
},
5297
"node_modules/parse5": {
5298
"version": "7.3.0",
5299
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
···
5803
"license": "MIT",
5804
"dependencies": {
5805
"queue-microtask": "^1.2.2"
5806
+
}
5807
+
},
5808
+
"node_modules/sanitize-html": {
5809
+
"version": "2.17.0",
5810
+
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.17.0.tgz",
5811
+
"integrity": "sha512-dLAADUSS8rBwhaevT12yCezvioCA+bmUTPH/u57xKPT8d++voeYE6HeluA/bPbQ15TwDBG2ii+QZIEmYx8VdxA==",
5812
+
"license": "MIT",
5813
+
"dependencies": {
5814
+
"deepmerge": "^4.2.2",
5815
+
"escape-string-regexp": "^4.0.0",
5816
+
"htmlparser2": "^8.0.0",
5817
+
"is-plain-object": "^5.0.0",
5818
+
"parse-srcset": "^1.0.2",
5819
+
"postcss": "^8.3.11"
5820
+
}
5821
+
},
5822
+
"node_modules/sanitize-html/node_modules/escape-string-regexp": {
5823
+
"version": "4.0.0",
5824
+
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
5825
+
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
5826
+
"license": "MIT",
5827
+
"engines": {
5828
+
"node": ">=10"
5829
+
},
5830
+
"funding": {
5831
+
"url": "https://github.com/sponsors/sindresorhus"
5832
}
5833
},
5834
"node_modules/semver": {
+1
package.json
+1
package.json
+13
src/content.config.ts
+13
src/content.config.ts
···
···
1
+
import { defineCollection, z } from "astro:content";
2
+
import { leafletStaticLoader } from "@nulfrost/leaflet-loader-astro";
3
+
import { loadConfig } from "./lib/config/site";
4
+
5
+
const config = loadConfig();
6
+
7
+
const documents = defineCollection({
8
+
loader: leafletStaticLoader({
9
+
repo: config.atproto.did || config.atproto.handle || "did:plc:example"
10
+
}),
11
+
});
12
+
13
+
export const collections = { documents };
+1
src/pages/index.astro
+1
src/pages/index.astro
···
20
<a href="/" class="text-blue-600 dark:text-blue-400 hover:underline">Home</a>
21
<a href="/blog" class="text-blue-600 dark:text-blue-400 hover:underline">Blog</a>
22
<a href="/galleries" class="text-blue-600 dark:text-blue-400 hover:underline">Galleries</a>
23
+
<a href="/leaflets" class="text-blue-600 dark:text-blue-400 hover:underline">Leaflets</a>
24
</nav>
25
</header>
26
+101
src/pages/leaflets.astro
+101
src/pages/leaflets.astro
···
···
1
+
---
2
+
import Layout from '../layouts/Layout.astro';
3
+
import { getCollection } from "astro:content";
4
+
import { loadConfig } from '../lib/config/site';
5
+
6
+
const config = loadConfig();
7
+
const documents = await getCollection("documents");
8
+
9
+
// Sort documents by published date (newest first)
10
+
const sortedDocuments = documents.sort((a, b) => {
11
+
const dateA = a.data.publishedAt ? new Date(a.data.publishedAt).getTime() : 0;
12
+
const dateB = b.data.publishedAt ? new Date(b.data.publishedAt).getTime() : 0;
13
+
return dateB - dateA;
14
+
});
15
+
---
16
+
17
+
<Layout title="Leaflet Documents">
18
+
<div class="container mx-auto px-4 py-8">
19
+
<header class="text-center mb-12">
20
+
<h1 class="text-4xl font-bold text-gray-900 dark:text-white mb-4">
21
+
Leaflet Documents
22
+
</h1>
23
+
<p class="text-xl text-gray-600 dark:text-gray-400 max-w-2xl mx-auto">
24
+
A collection of my leaflet.pub documents
25
+
</p>
26
+
</header>
27
+
28
+
<main class="max-w-4xl mx-auto">
29
+
{config.atproto.handle && config.atproto.handle !== 'your-handle-here' ? (
30
+
sortedDocuments.length > 0 ? (
31
+
<div class="space-y-6">
32
+
{sortedDocuments.map((document) => (
33
+
<article class="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-6">
34
+
<header class="mb-4">
35
+
<h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-2">
36
+
<a href={`/leaflets/${document.id}`} class="hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
37
+
{document.data.title}
38
+
</a>
39
+
</h2>
40
+
41
+
{document.data.description && (
42
+
<p class="text-gray-600 dark:text-gray-400 mb-3">
43
+
{document.data.description}
44
+
</p>
45
+
)}
46
+
47
+
<div class="text-sm text-gray-500 dark:text-gray-400">
48
+
{document.data.publishedAt && (
49
+
<span class="mr-4">
50
+
Published: {new Date(document.data.publishedAt).toLocaleDateString('en-US', {
51
+
year: 'numeric',
52
+
month: 'long',
53
+
day: 'numeric',
54
+
})}
55
+
</span>
56
+
)}
57
+
{document.data.author && (
58
+
<span>Author: {document.data.author}</span>
59
+
)}
60
+
</div>
61
+
</header>
62
+
</article>
63
+
))}
64
+
</div>
65
+
) : (
66
+
<div class="text-center py-12">
67
+
<div class="bg-gray-50 dark:bg-gray-800 rounded-lg p-8">
68
+
<h3 class="text-xl font-semibold text-gray-900 dark:text-white mb-4">
69
+
No Leaflet Documents Found
70
+
</h3>
71
+
<p class="text-gray-600 dark:text-gray-400 mb-4">
72
+
No leaflet.pub documents were found for your account.
73
+
</p>
74
+
<p class="text-sm text-gray-500 dark:text-gray-500">
75
+
Make sure you have created documents using leaflet.pub and they are properly indexed.
76
+
</p>
77
+
</div>
78
+
</div>
79
+
)
80
+
) : (
81
+
<div class="text-center py-12">
82
+
<div class="bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-lg p-8">
83
+
<h3 class="text-xl font-semibold text-yellow-800 dark:text-yellow-200 mb-4">
84
+
Configuration Required
85
+
</h3>
86
+
<p class="text-yellow-700 dark:text-yellow-300 mb-4">
87
+
To display your Leaflet documents, please configure your Bluesky handle in the environment variables.
88
+
</p>
89
+
<div class="text-sm text-yellow-600 dark:text-yellow-400">
90
+
<p class="mb-2">Create a <code class="bg-yellow-100 dark:bg-yellow-800 px-1 rounded">.env</code> file with:</p>
91
+
<pre class="bg-yellow-100 dark:bg-yellow-800 p-3 rounded text-xs overflow-x-auto">
92
+
ATPROTO_HANDLE=your-handle.bsky.social
93
+
SITE_TITLE=Your Site Title
94
+
SITE_AUTHOR=Your Name</pre>
95
+
</div>
96
+
</div>
97
+
</div>
98
+
)}
99
+
</main>
100
+
</div>
101
+
</Layout>
+63
src/pages/leaflets/[leaflet].astro
+63
src/pages/leaflets/[leaflet].astro
···
···
1
+
---
2
+
import Layout from '../../layouts/Layout.astro';
3
+
import { getCollection, getEntry, render } from "astro:content";
4
+
5
+
export async function getStaticPaths() {
6
+
const documents = await getCollection("documents");
7
+
return documents.map((document) => ({
8
+
params: { leaflet: document.id },
9
+
props: document,
10
+
}));
11
+
}
12
+
13
+
const document = await getEntry("documents", Astro.params.leaflet);
14
+
15
+
if (!document) {
16
+
throw new Error(`Document with id "${Astro.params.leaflet}" not found`);
17
+
}
18
+
19
+
const { Content } = await render(document);
20
+
---
21
+
22
+
<Layout title={document.data.title}>
23
+
<div class="container mx-auto px-4 py-8">
24
+
<header class="mb-8">
25
+
<nav class="mb-6">
26
+
<a href="/leaflets" class="text-blue-600 dark:text-blue-400 hover:underline">
27
+
← Back to Leaflets
28
+
</a>
29
+
</nav>
30
+
31
+
<h1 class="text-4xl font-bold text-gray-900 dark:text-white mb-4">
32
+
{document.data.title}
33
+
</h1>
34
+
35
+
{document.data.description && (
36
+
<p class="text-xl text-gray-600 dark:text-gray-400 mb-6">
37
+
{document.data.description}
38
+
</p>
39
+
)}
40
+
41
+
<div class="text-sm text-gray-500 dark:text-gray-400 mb-6">
42
+
{document.data.publishedAt && (
43
+
<span class="mr-4">
44
+
Published: {new Date(document.data.publishedAt).toLocaleDateString('en-US', {
45
+
year: 'numeric',
46
+
month: 'long',
47
+
day: 'numeric',
48
+
})}
49
+
</span>
50
+
)}
51
+
{document.data.author && (
52
+
<span>Author: {document.data.author}</span>
53
+
)}
54
+
</div>
55
+
</header>
56
+
57
+
<main class="max-w-4xl mx-auto">
58
+
<article class="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 p-8">
59
+
<Content />
60
+
</article>
61
+
</main>
62
+
</div>
63
+
</Layout>