this repo has no description
1# sitebase
2
3Export content from [standard.site](https://standard.site) publications to markdown files.
4
5Sitebase connects to ATProto Personal Data Servers (PDS) to fetch documents from `site.standard.publication` collections and exports them as markdown files with configurable templates and filtering.
6
7## Installation
8
9```bash
10bun install
11```
12
13## Packages
14
15This is a monorepo with three packages:
16
17- **@sitebase/core** - Library for exporting publications and template utilities
18- **@sitebase/cli** - Command-line interface for running exports
19- **@sitebase/web** - Web UI for managing publications and documents
20
21## CLI Usage
22
23```bash
24# Auto-discover sitebase.config.ts in current directory
25sitebase export
26
27# Specify a config file
28sitebase export --config ./my-config.ts
29```
30
31The CLI looks for `sitebase.config.ts` or `sitebase.config.js` in the current directory. Use `-c` or `--config` to specify a different path.
32
33## Configuration
34
35Create a `sitebase.config.ts` file in your project root:
36
37```typescript
38import type { ExportConfig } from "@sitebase/core";
39import { slugify } from "@sitebase/core";
40
41const config: ExportConfig = {
42 // AT URI of your publication
43 publicationUri: "at://did:plc:xyz/site.standard.publication/rkey",
44
45 // One or more export targets
46 exports: [
47 {
48 outputDir: "./content/posts",
49 includeTags: ["post"],
50 excludeTags: ["draft"],
51 filename: (data) => {
52 const date = data.publishedAt?.slice(0, 10) || "undated";
53 return `${date}_${slugify(data.title)}.md`;
54 },
55 contentTemplate: "./templates/post.hbs",
56 },
57 ],
58};
59
60export default config;
61```
62
63### Config Reference
64
65#### `ExportConfig`
66
67| Field | Type | Description |
68|-------|------|-------------|
69| `publicationUri` | `string` | AT URI of the publication (`at://did:plc:.../site.standard.publication/rkey`) |
70| `exports` | `ExportTarget[]` | Array of export targets |
71
72#### `ExportTarget`
73
74| Field | Type | Required | Description |
75|-------|------|----------|-------------|
76| `outputDir` | `string` | Yes | Directory to write output files |
77| `filename` | `(data: TemplateData) => string` | Yes | Function to generate filename |
78| `includeTags` | `string[]` | No | Only include documents with ANY of these tags |
79| `excludeTags` | `string[]` | No | Exclude documents with ANY of these tags |
80| `contentTemplate` | `string` | No | Path to Handlebars template file |
81| `content` | `(data: TemplateData) => string` | No | Function to generate content (overrides `contentTemplate`) |
82
83### Template Data
84
85Both `filename` and `content` functions receive a `TemplateData` object:
86
87```typescript
88interface TemplateData {
89 title: string;
90 path?: string;
91 description?: string;
92 content: string; // Markdown content
93 tags: string[];
94 publishedAt?: string; // ISO 8601 date
95 updatedAt?: string; // ISO 8601 date
96 publication: {
97 name: string;
98 url: string;
99 description?: string;
100 };
101}
102```
103
104### Tag Filtering
105
106- **includeTags**: Only documents with at least one matching tag are included
107- **excludeTags**: Documents with any matching tag are excluded
108- When neither is specified, documents tagged "draft" are excluded by default
109
110### Handlebars Templates
111
112Content templates use [Handlebars](https://handlebarsjs.com/) with these custom helpers:
113
114| Helper | Usage | Description |
115|--------|-------|-------------|
116| `slug` | `{{slug text}}` | Convert text to URL-safe slug |
117| `dateFormat` | `{{dateFormat date "YYYY-MM-DD"}}` | Format date (supports YYYY, MM, DD) |
118| `default` | `{{default value fallback}}` | Use fallback if value is empty |
119
120Example template (`templates/post.hbs`):
121
122```handlebars
123---
124title: "{{title}}"
125date: {{publishedAt}}
126slug: {{slug (default path title)}}
127{{#if tags.length}}
128tags:
129{{#each tags}}
130 - {{this}}
131{{/each}}
132{{/if}}
133---
134
135{{content}}
136```
137
138### Using the Content Function
139
140For full control, use a `content` function instead of a template:
141
142```typescript
143{
144 outputDir: "./content",
145 filename: (data) => `${slugify(data.title)}.md`,
146 content: (data) => {
147 return [
148 "---",
149 `title: "${data.title}"`,
150 `date: ${data.publishedAt}`,
151 "---",
152 "",
153 data.content,
154 ].join("\n");
155 },
156}
157```
158
159### Multiple Export Targets
160
161Export the same publication to different locations with different filters:
162
163```typescript
164export default {
165 publicationUri: "at://did:plc:xyz/site.standard.publication/rkey",
166 exports: [
167 {
168 outputDir: "./content/notes",
169 includeTags: ["note"],
170 filename: (data) => `${slugify(data.title)}.md`,
171 },
172 {
173 outputDir: "./content/posts",
174 includeTags: ["post"],
175 excludeTags: ["draft"],
176 filename: (data) => `${data.publishedAt?.slice(0, 10)}_${slugify(data.title)}.md`,
177 contentTemplate: "./templates/post.hbs",
178 },
179 ],
180} as ExportConfig;
181```
182
183## Core Library
184
185Use `@sitebase/core` directly in your own scripts:
186
187```typescript
188import { exportPublication, slugify, createHandlebars } from "@sitebase/core";
189
190const result = await exportPublication({
191 publicationUri: "at://did:plc:xyz/site.standard.publication/rkey",
192 outputDir: "./output",
193 filename: (data) => `${slugify(data.title)}.md`,
194});
195
196console.log(`Wrote ${result.filesWritten.length} files`);
197```
198
199### Exports
200
201- `exportPublication(options)` - Export a publication to markdown files
202- `exportFromConfig(config, baseDir)` - Export using a config object
203- `findConfigFile(dir)` - Find `sitebase.config.{ts,js}` in directory
204- `loadExportConfig(path)` - Load and validate a config file
205- `slugify(text)` - Convert text to URL-safe slug
206- `createHandlebars()` - Create Handlebars instance with helpers registered
207- `generateContent(hbs, template, data)` - Render a Handlebars template
208
209## Web UI
210
211The web package provides a management interface for publications and documents with ATProto OAuth authentication.
212
213```bash
214cd packages/web
215bun run dev
216```
217
218See `packages/web/CLAUDE.md` for web package details.
219
220## License
221
222MIT