leaflet.pub astro loader
1# Leaflet Astro Loader
2
3This loader is for [leaflet.pub](https://leaflet.pub/). It fetches leaflet document records from your personal data server to then be used on your astro site.
4
5There are two different types of loaders you can use from this package:
6
7- **Static Loader:** Fetches data at build time and is served statically on your website
8- **Live Loader (experimental astro feature):** Fetches data on each request. **Note**: This package does not provide any caching mechanisms for the live loader. So to avoid slamming your PDS (or someone elses PDS) with requests it's probably a good idea to set up some sort of cache either using cache headers or some other means.
9
10## Installation
11
12```bash
13npm install @nulfrost/leaflet-loader-astro
14```
15
16## Usage
17
18<details>
19<summary>Build-time loader: leafletStaticLoader **(recommended)**</summary>
20
21```ts
22// src/content.config.ts
23import { defineCollection, z } from "astro:content";
24import { leafletStaticLoader } from "@nulfrost/leaflet-loader-astro";
25
26const documents = defineCollection({
27 loader: leafletStaticLoader({ repo: "did:plc:qttsv4e7pu2jl3ilanfgc3zn" }), // or repo: dane.is.extraordinarily.cool
28});
29
30export const collections = { documents };
31```
32
33```ts
34// src/pages/index.astro
35---
36import { getCollection } from "astro:content";
37
38const documents = await getCollection("documents");
39---
40
41<html lang="en">
42 <head>
43 <meta charset="utf-8" />
44 <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
45 <meta name="viewport" content="width=device-width" />
46 <meta name="generator" content={Astro.generator} />
47 <title>Astro</title>
48 </head>
49 <body>
50 <h1>Astro + Leaflet.pub</h1>
51 <ul>
52 {documents.map(document => <li>
53 <a href={`/blogs/${document.id}`}>{document.data.title}</a>
54 </li>)}
55 </ul>
56 </body>
57</html>
58```
59
60```ts
61// src/pages/blog/[blog].astro
62---
63import { getCollection, getEntry } from "astro:content";
64import { render } from "astro:content";
65
66export async function getStaticPaths() {
67 const documents = await getCollection("documents");
68 return documents.map((document) => ({
69 params: { blog: document.id },
70 props: document,
71 }));
72}
73
74const document = await getEntry("documents", Astro.params.blog);
75
76if (!document) {
77 throw new Error(`Document with id "${Astro.params.blog}" not found`);
78}
79
80const { Content } = await render(document);
81---
82
83<Content />
84```
85</details>
86
87<details>
88<summary>Live loader: leafletLiveLoader</summary>
89
90```ts
91// astro.config.mjs
92
93// @ts-check
94import { defineConfig } from "astro/config";
95
96// https://astro.build/config
97export default defineConfig({
98 experimental: {
99 liveContentCollections: true, // make sure to enable this
100 },
101});
102```
103
104```ts
105// src/live.config.ts
106import { defineLiveCollection, z } from "astro:content";
107import { leafletLiveLoader } from "@nulfrost/leaflet-loader-astro";
108
109const documents = defineLiveCollection({
110 loader: leafletLiveLoader({ repo: "did:plc:qttsv4e7pu2jl3ilanfgc3zn" }), // or repo: dane.is.extraordinarily.cool
111});
112
113export const collections = { documents };
114```
115
116```ts
117// src/pages/index.astro
118---
119import { getLiveCollection } from "astro:content";
120
121export const prerender = false;
122
123const documents = await getLiveCollection("documents");
124---
125
126<html lang="en">
127 <head>
128 <meta charset="utf-8" />
129 <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
130 <meta name="viewport" content="width=device-width" />
131 <meta name="generator" content={Astro.generator} />
132 <title>Astro</title>
133 </head>
134 <body>
135 <h1>Astro + Leaflet.pub</h1>
136 <ul>
137 {documents.map(document => <li>
138 <a href={`/blogs/${document.id}`}>{document.data.title}</a>
139 </li>)}
140 </ul>
141 </body>
142</html>
143```
144
145```ts
146// src/pages/blog/[blog].astro
147---
148import { getLiveEntry } from "astro:content";
149import { render } from "astro:content";
150
151export const prerender = false;
152
153const document = await getLiveEntry("documents", Astro.params.blog);
154
155if (!document) {
156 throw new Error(`Document with id "${Astro.params.blog}" not found`);
157}
158
159const { Content } = await render(document?.entry);
160---
161
162<Content />
163```
164
165</details>
166
167## Loader Options
168
169### Static Loader
170
171```ts
172leafletStaticLoader()
173```
174
175`repo`: This can be either your DID (did:plc:qttsv4e7pu2jl3ilanfgc3zn) or your handle (dane.is.extraordinarily.cool)
176
177`limit`: How many leaflet documents to return when calling `getCollection`. The default is 50 and the range is from 1 to 100.
178
179`reverse`: Whether or not to return the leaflet documents in reverse order. By default this is false.
180
181### Live Loader
182
183```ts
184leafletLiveLoader()
185```
186
187`repo`: This can be either your DID (did:plc:qttsv4e7pu2jl3ilanfgc3zn) or your handle (dane.is.extraordinarily.cool)
188
189> [!NOTE]
190> `getLiveCollection` supports a second argument where you can add additional filters, similar to the options you have access to for `leafletStaticLoader`
191
192```ts
193getLiveCollection()
194```
195
196`limit`: How many leaflet documents to return when calling `getCollection`. The default is 50 and the range is from 1 to 100.
197
198`reverse`: Whether or not to return the leaflet documents in reverse order. By default this is false.
199
200## Supported Leaflet Blocks
201
202- [ ] Bluesky post
203- [x] Iframe
204- [x] Horizontal Rule
205- [x] Unordered List
206- [x] Math
207- [x] Code
208- [ ] Website
209- [x] Image
210- [x] Blockquote
211- [x] Text
212- [x] Header
213- [x] List Item
214
215## License
216
217MIT
218
219For questions, contributions, and support, please open an issue on GitHub.