my website at ewancroft.uk
1# Configuration Guide 2 3This guide will walk you through configuring your AT Protocol-powered personal website. Follow these steps in order to set up your site correctly. 4 5## Table of Contents 6 71. [Prerequisites](#prerequisites) 82. [Environment Configuration](#environment-configuration) 93. [Publication Slug Mapping](#publication-slug-mapping) 104. [Static File Customization](#static-file-customization) 115. [Optional Features](#optional-features) 126. [Advanced Configuration](#advanced-configuration) 137. [Verification](#verification) 148. [Troubleshooting](#troubleshooting) 15 16--- 17 18## Prerequisites 19 20Before you begin configuration, ensure you have: 21 22- **Node.js 18+** installed 23- **npm** package manager 24- An **AT Protocol DID** (Decentralized Identifier) from Bluesky 25- Basic knowledge of environment variables and JSON configuration 26 27### Finding Your DID 28 29Your DID is your unique identifier in the AT Protocol network. 30 31#### Using PDSls (Recommended) 32 331. Visit [PDSls](https://pdsls.dev/) 342. Enter your Bluesky handle (e.g., `username.bsky.social`) 353. Look for the `Repository` field - your DID will be in the format `did:plc:...` or `did:web:...` 364. Click the arrow to the right if the full DID is not visible 37 38**Example DID**: `did:plc:abcdef123456xyz` 39 40--- 41 42## Environment Configuration 43 44### Step 1: Create Your Environment File 45 46Copy the example environment file: 47 48```bash 49cp .env.example .env.local 50``` 51 52**Important**: Use `.env.local` for your personal configuration. This file is ignored by git and keeps your settings private. 53 54### Step 2: Configure Required Variables 55 56Edit `.env.local` and set these **required** values: 57 58```ini 59# Your AT Protocol DID (Required) 60PUBLIC_ATPROTO_DID=did:plc:your-actual-did-here 61 62# Site Metadata (Required) 63PUBLIC_SITE_TITLE="Your Site Name" 64PUBLIC_SITE_DESCRIPTION="A brief description of your website" 65PUBLIC_SITE_KEYWORDS="keywords, about, your, site" 66PUBLIC_SITE_URL="https://yourdomain.com" 67``` 68 69**Critical**: Replace `your-actual-did-here` with your actual DID from the Prerequisites section. 70 71### Step 3: Configure Optional Variables 72 73Add these optional settings based on your needs: 74 75```ini 76# WhiteWind Support (Optional, default: false) 77# Set to "true" only if you use WhiteWind for blogging 78PUBLIC_ENABLE_WHITEWIND=false 79 80# Blog Fallback URL (Optional) 81# Where to redirect if a blog post isn't found 82# Leave empty to show a 404 error instead 83PUBLIC_BLOG_FALLBACK_URL="" 84 85# Slingshot Configuration (Optional) 86# For development with local Slingshot instance 87PUBLIC_LOCAL_SLINGSHOT_URL="http://localhost:3000" 88PUBLIC_SLINGSHOT_URL="https://slingshot.microcosm.blue" 89 90# CORS Configuration (Optional, but recommended) 91# Comma-separated list of domains allowed to access your API 92# Use "*" for development only (not secure for production) 93PUBLIC_CORS_ALLOWED_ORIGINS="https://yourdomain.com" 94``` 95 96### Environment Variable Reference 97 98| Variable | Required | Default | Purpose | 99|----------|----------|---------|---------| 100| `PUBLIC_ATPROTO_DID` | ✅ Yes | - | Your AT Protocol identifier | 101| `PUBLIC_SITE_TITLE` | ✅ Yes | - | Website title for SEO | 102| `PUBLIC_SITE_DESCRIPTION` | ✅ Yes | - | Website description for SEO | 103| `PUBLIC_SITE_KEYWORDS` | ✅ Yes | - | SEO keywords | 104| `PUBLIC_SITE_URL` | ✅ Yes | - | Your website's URL | 105| `PUBLIC_ENABLE_WHITEWIND` | ❌ No | `false` | Enable WhiteWind blog support | 106| `PUBLIC_BLOG_FALLBACK_URL` | ❌ No | `""` | Fallback URL for missing posts | 107| `PUBLIC_LOCAL_SLINGSHOT_URL` | ❌ No | `""` | Local Slingshot instance URL | 108| `PUBLIC_SLINGSHOT_URL` | ❌ No | Public URL | Public Slingshot instance | 109| `PUBLIC_CORS_ALLOWED_ORIGINS` | ❌ No | `"*"` | CORS allowed origins | 110 111--- 112 113## Publication Slug Mapping 114 115The slug mapping system allows you to access your Leaflet publications via friendly URLs. 116 117### Understanding Slugs 118 119- **Slug**: A friendly URL segment (e.g., `blog`, `essays`, `notes`) 120- **Publication Rkey**: The unique identifier of your Leaflet publication 121- **URL Format**: Your publications will be accessible at `https://yoursite.com/{slug}` 122 123### Step 1: Find Your Publication Rkeys 124 1251. Visit your Leaflet publication on [leaflet.pub](https://leaflet.pub/) 1262. Look at the URL format: `https://leaflet.pub/lish/{did}/{publication-rkey}` 1273. Copy the `{publication-rkey}` portion (e.g., `3m3x4bgbsh22k`) 128 129**Example URL**: `https://leaflet.pub/lish/did:plc:abc123/3m3x4bgbsh22k` 130 131- **Publication Rkey**: `3m3x4bgbsh22k` 132 133### Step 2: Configure Slugs 134 135Edit `src/lib/config/slugs.ts`: 136 137```typescript 138import type { SlugMapping } from '$lib/services/atproto'; 139 140/** 141 * Maps friendly URL slugs to Leaflet publication rkeys 142 * 143 * Example usage: 144 * - { slug: 'blog', publicationRkey: '3m3x4bgbsh22k' } 145 * Accessible at: /blog 146 * - { slug: 'essays', publicationRkey: 'xyz789abc' } 147 * Accessible at: /essays 148 */ 149export const slugMappings: SlugMapping[] = [ 150 { 151 slug: 'blog', 152 publicationRkey: '3m3x4bgbsh22k' // Replace with your actual rkey 153 } 154 // Add more mappings as needed: 155 // { 156 // slug: 'essays', 157 // publicationRkey: 'your-essays-rkey' 158 // }, 159 // { 160 // slug: 'notes', 161 // publicationRkey: 'your-notes-rkey' 162 // } 163]; 164``` 165 166### Step 3: Understand URL Structure 167 168Once configured, your publications are accessible via: 169 170- **Publication Homepage**: `/{slug}` → Redirects to Leaflet publication 171- **Individual Posts**: `/{slug}/{post-rkey}` → Redirects to specific post 172- **RSS Feed**: `/{slug}/rss` → RSS feed for the publication 173 174**Example**: 175 176- Configuration: `{ slug: 'blog', publicationRkey: '3m3x4bgbsh22k' }` 177- Homepage: `https://yoursite.com/blog` 178- Post: `https://yoursite.com/blog/3abc789xyz` 179- RSS: `https://yoursite.com/blog/rss` 180 181### Multiple Publications Example 182 183```typescript 184export const slugMappings: SlugMapping[] = [ 185 { 186 slug: 'blog', // Main blog 187 publicationRkey: '3m3x4bgbsh22k' 188 }, 189 { 190 slug: 'tech', // Tech articles 191 publicationRkey: 'xyz789tech' 192 }, 193 { 194 slug: 'personal', // Personal writing 195 publicationRkey: 'abc456personal' 196 } 197]; 198``` 199 200--- 201 202## Static File Customization 203 204Several static files need to be customized for your site. 205 206### Files to Update 207 208| File | Purpose | Action Required | 209|------|---------|-----------------| 210| `static/robots.txt` | SEO crawling rules | Update sitemap URL | 211| `static/sitemap.xml` | Site structure for SEO | Update with your pages | 212| `static/.well-known/*` | Domain verification | Replace or remove | 213| `static/favicon/*` | Site icons | Replace with your branding | 214 215### Step 1: Update robots.txt 216 217Edit `static/robots.txt`: 218 219```text 220User-agent: * 221Allow: / 222 223# Update this line with your actual domain 224Sitemap: https://yourdomain.com/sitemap.xml 225``` 226 227### Step 2: Update sitemap.xml 228 229Edit `static/sitemap.xml`: 230 231```xml 232<?xml version="1.0" encoding="UTF-8"?> 233<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"> 234 <!-- Homepage --> 235 <url> 236 <loc>https://yourdomain.com/</loc> 237 <changefreq>daily</changefreq> 238 <priority>1.0</priority> 239 </url> 240 241 <!-- Add your publication slugs --> 242 <url> 243 <loc>https://yourdomain.com/blog</loc> 244 <changefreq>weekly</changefreq> 245 <priority>0.8</priority> 246 </url> 247 248 <!-- Add other important pages --> 249 <url> 250 <loc>https://yourdomain.com/site/meta</loc> 251 <changefreq>monthly</changefreq> 252 <priority>0.5</priority> 253 </url> 254</urlset> 255``` 256 257### Step 3: Update Favicon 258 259Replace files in `static/favicon/`: 260 2611. Generate favicons using [RealFaviconGenerator](https://realfavicongenerator.net/) 2622. Replace all files in `static/favicon/` with your generated icons 2633. Ensure these files are present: 264 - `favicon.ico` 265 - `apple-touch-icon.png` 266 - `favicon-16x16.png` 267 - `favicon-32x32.png` 268 - `site.webmanifest` 269 270### Step 4: Update or Remove .well-known Files 271 272The `static/.well-known/` directory contains domain verification files. 273 274#### Option A: Replace with your own 275 276```bash 277rm -rf static/.well-known/* 278# Add your own verification files here 279``` 280 281#### Option B: Remove entirely (if you don't need verification) 282 283```bash 284rm -rf static/.well-known/ 285``` 286 287Common `.well-known` files: 288 289- `atproto-did` - AT Protocol domain verification 290- `security.txt` - Security contact information 291- Domain verification files for various services 292 293--- 294 295## Optional Features 296 297### WhiteWind Blog Support 298 299**When to enable**: If you publish blog posts on WhiteWind (`com.whtwnd.blog.entry` records). 300 301**Configuration**: 302 303```ini 304# In .env.local 305PUBLIC_ENABLE_WHITEWIND=true 306``` 307 308**Behavior**: 309 310- With WhiteWind **disabled** (default): 311 - Only Leaflet posts are fetched and displayed 312 - RSS feeds redirect to Leaflet's native feeds 313 - Post redirects only check Leaflet 314 315- With WhiteWind **enabled**: 316 - Both Leaflet and WhiteWind posts are displayed 317 - RSS feeds include links to WhiteWind posts 318 - Post redirects check Leaflet first, then WhiteWind 319 - Draft and non-public WhiteWind posts are filtered out 320 321**Note**: Most users should keep WhiteWind disabled unless they specifically use it. 322 323### Custom Blog Fallback 324 325Redirect users to an archive or external blog when posts aren't found. 326 327```ini 328# In .env.local 329PUBLIC_BLOG_FALLBACK_URL="https://archive.yourdomain.com" 330``` 331 332**Behavior**: 333 334- If a post isn't found on Leaflet (or WhiteWind) 335- AND `PUBLIC_BLOG_FALLBACK_URL` is set 336- Then redirect to: `{FALLBACK_URL}/{slug}/{rkey}` 337 338**Example**: 339 340- Missing post: `/blog/3abc789` 341- Redirects to: `https://archive.yourdomain.com/blog/3abc789` 342 343### CORS Configuration 344 345Control which domains can access your API endpoints. 346 347**Development** (allow all): 348 349```ini 350PUBLIC_CORS_ALLOWED_ORIGINS="*" 351``` 352 353**Production** (specific domains): 354 355```ini 356# Single domain 357PUBLIC_CORS_ALLOWED_ORIGINS="https://yourdomain.com" 358 359# Multiple domains 360PUBLIC_CORS_ALLOWED_ORIGINS="https://yourdomain.com,https://app.yourdomain.com,https://www.yourdomain.com" 361``` 362 363**Security Note**: Always use specific domain lists in production, never use `*`. 364 365--- 366 367## Advanced Configuration 368 369### Custom Lexicon Support 370 371The site automatically displays data from these AT Protocol lexicons: 372 373#### Site Information (`uk.ewancroft.site.info`) 374 375- Technology stack 376- Privacy statements 377- Credits and licenses 378- No configuration needed - automatically fetched 379 380#### Music Status (`fm.teal.alpha.*`) 381 382- Current playing status via teal.fm 383- Automatic album artwork from MusicBrainz 384- Scrobbles from Last.fm, Spotify, etc. 385- No configuration needed 386 387#### Mood Status (`social.kibun.status`) 388 389- Current mood/feeling via kibun.social 390- Emoji and text display 391- No configuration needed 392 393#### Link Board (`blue.linkat.board`) 394 395- Curated link collections from Linkat 396- Emoji icons for each link 397- No configuration needed 398 399#### Tangled Repositories (`sh.tangled.repo`) 400 401- Code repository display 402- Descriptions, labels, creation dates 403- No configuration needed 404 405**All lexicons are automatically fetched using your `PUBLIC_ATPROTO_DID`** 406 407### Slingshot Configuration 408 409Slingshot is an AT Protocol data aggregator for faster queries. 410 411```ini 412# Local development instance (optional) 413PUBLIC_LOCAL_SLINGSHOT_URL="http://localhost:3000" 414 415# Public instance (default fallback) 416PUBLIC_SLINGSHOT_URL="https://slingshot.microcosm.blue" 417``` 418 419**Default Behavior**: 420 4211. Try local Slingshot (if URL is set and reachable) 4222. Fallback to public Slingshot 4233. Fallback to user's PDS 4244. Fallback to Bluesky public API 425 426**Note**: Most users can leave these at their defaults. 427 428### Theme Customization 429 430The site uses Tailwind CSS with custom semantic colors. To customize: 431 4321. Edit `src/app.css` for global color scheme: 433 434```css 435@theme { 436 --color-canvas: /* Background color */; 437 --color-ink: /* Text color */; 438 --color-primary: /* Accent color */; 439} 440``` 441 4421. Dark mode colors are automatically adjusted via Tailwind's `dark:` variants 443 4441. Wolf mode and theme toggle work automatically with any color scheme 445 446--- 447 448## Verification 449 450After configuration, verify everything works: 451 452### Step 1: Install Dependencies 453 454```bash 455npm install 456``` 457 458### Step 2: Start Development Server 459 460```bash 461npm run dev 462``` 463 464Visit `http://localhost:5173` 465 466### Step 3: Check Core Features 467 468Verify these elements appear correctly: 469 470- [ ] **Profile Card**: Shows your Bluesky profile information 471 - Avatar and banner image 472 - Display name and handle 473 - Bio text 474 - Follower/following counts 475 476- [ ] **Site Metadata**: Check `http://localhost:5173/site/meta` 477 - Site information loads correctly 478 - Credits, tech stack, privacy info display 479 480- [ ] **Blog Access**: Test your slug configuration 481 - Visit `http://localhost:5173/{your-slug}` 482 - Should redirect to your Leaflet publication 483 - RSS feed works at `http://localhost:5173/{your-slug}/rss` 484 485- [ ] **Optional Features** (if enabled): 486 - Music status card (if you use teal.fm) 487 - Mood status card (if you use kibun.social) 488 - Link board (if you use Linkat) 489 - Repositories (if you use Tangled) 490 - Latest Bluesky post 491 492### Step 4: Check Browser Console 493 494Open browser DevTools (F12) and check for: 495 496- ✅ No error messages in Console tab 497- ✅ Successful API responses in Network tab 498- ✅ No 404 errors for static files 499 500### Step 5: Test Responsive Design 501 502Check the site at different screen sizes: 503 504- Mobile (375px width) 505- Tablet (768px width) 506- Desktop (1280px+ width) 507 508### Step 6: Verify SEO Metadata 509 510View page source and check for: 511 512- `<title>` tag with your site title 513- `<meta name="description">` with your description 514- Open Graph tags (`og:title`, `og:description`, etc.) 515- Twitter Card tags (`twitter:card`, `twitter:title`, etc.) 516 517--- 518 519## Troubleshooting 520 521### Profile Data Not Loading 522 523**Symptom**: Profile card shows "Profile not found" or loading state persists 524 525**Solutions**: 526 5271. Verify `PUBLIC_ATPROTO_DID` is correct in `.env.local` 5282. Check your DID format: should be `did:plc:...` or `did:web:...` 5293. Ensure your Bluesky account is active and public 5304. Check browser console for specific error messages 5315. Clear cache and hard refresh (Ctrl+Shift+R / Cmd+Shift+R) 532 533### Publications Not Found 534 535**Symptom**: Blog pages show 404 or "Not Found" errors 536 537**Solutions**: 538 5391. Verify publication rkey in `src/lib/config/slugs.ts` matches your Leaflet publication 5402. Visit your Leaflet publication URL and confirm the rkey is correct 5413. Ensure the publication is public (not draft/private) 5424. Check if documents exist in the publication 5435. If using WhiteWind, verify `PUBLIC_ENABLE_WHITEWIND=true` if needed 544 545### Music Status Not Showing 546 547**Symptom**: Music card doesn't appear or shows no data 548 549**Solutions**: 550 5511. Verify you have teal.fm configured with your Bluesky account 5522. Check if you have any scrobbles in your teal.fm history 5533. Ensure your scrobbler (e.g., piper) is running and connected 5544. Album artwork requires MusicBrainz IDs or blob storage 5555. Check browser console for MusicBrainz API errors 556 557### RSS Feeds Not Working 558 559**Symptom**: RSS feed shows errors or no posts 560 561**Solutions**: 562 5631. Check slug configuration in `src/lib/config/slugs.ts` 5642. Verify publication has published documents (not drafts) 5653. If using WhiteWind: 566 - Ensure `PUBLIC_ENABLE_WHITEWIND=true` 567 - Verify you have published WhiteWind posts 5684. Test feed URL directly: `http://localhost:5173/{slug}/rss` 5695. Check Content-Type header is `application/rss+xml` 570 571### Environment Variables Not Applied 572 573**Symptom**: Changes to `.env.local` don't take effect 574 575**Solutions**: 576 5771. Restart the development server (`npm run dev`) 5782. Verify variable names start with `PUBLIC_` for client-side access 5793. Check for typos in variable names 5804. Ensure `.env.local` is in the project root directory 5815. Clear `.svelte-kit` cache: `rm -rf .svelte-kit && npm run dev` 582 583### Build Errors 584 585**Symptom**: `npm run build` fails with errors 586 587**Solutions**: 588 589```bash 590# Clean build artifacts 591rm -rf .svelte-kit node_modules package-lock.json 592 593# Reinstall dependencies 594npm install 595 596# Try building again 597npm run build 598``` 599 600### CORS Errors in Production 601 602**Symptom**: API requests fail with CORS errors 603 604**Solutions**: 605 6061. Add your production domain to `PUBLIC_CORS_ALLOWED_ORIGINS` 6072. Ensure the domain includes the protocol (`https://`) 6083. For multiple domains, separate with commas (no spaces) 6094. Avoid using `*` in production for security 6105. Check that the origin header matches exactly (including www or non-www) 611 612### TypeScript Errors 613 614**Symptom**: Type errors in development 615 616**Solutions**: 617 618```bash 619# Run type checking 620npm run check 621 622# Watch mode for continuous checking 623npm run check:watch 624 625# Clear and rebuild 626rm -rf .svelte-kit && npm run dev 627``` 628 629### Dark Mode Not Working 630 631**Symptom**: Dark mode toggle doesn't change theme 632 633**Solutions**: 634 6351. Check if browser supports `prefers-color-scheme` 6362. Clear browser localStorage: `localStorage.clear()` in console 6373. Verify Tailwind's dark mode is configured in `tailwind.config.js` 6384. Check that dark mode classes are present in HTML (inspect element) 639 640### Wolf Mode Issues 641 642**Symptom**: Wolf mode toggle doesn't transform text 643 644**Solutions**: 645 6461. Ensure JavaScript is enabled in browser 6472. Check browser console for errors 6483. Verify the wolf mode store is imported correctly 6494. Test on different text elements to confirm it's working 6505. Remember: numbers and navigation are intentionally preserved 651 652--- 653 654## Getting Help 655 656If you encounter issues not covered here: 657 6581. **Check Browser Console**: Press F12 and look for error messages 6592. **Review README**: See [README.md](../README.md) for detailed feature documentation 6603. **GitHub Issues**: Search existing issues or create a new one 6614. **AT Protocol Docs**: Visit [atproto.com](https://atproto.com/) for protocol details 6625. **SvelteKit Docs**: Check [kit.svelte.dev](https://kit.svelte.dev/) for framework help 663 664### Useful Debugging Commands 665 666```bash 667# Check environment variables are loaded 668npm run dev -- --debug 669 670# View detailed build output 671npm run build -- --verbose 672 673# Type-check without building 674npm run check 675 676# Format code (may fix some issues) 677npm run format 678``` 679 680### Log Collection for Bug Reports 681 682When reporting issues, include: 683 6841. Browser console errors (F12 → Console tab) 6852. Network tab showing failed requests (F12 → Network tab) 6863. Your `.env.local` configuration (remove sensitive data like DIDs) 6874. Node.js and npm versions: `node --version && npm --version` 6885. Operating system and browser version 689 690--- 691 692## Next Steps 693 694After completing configuration: 695 6961. **Customize Content**: 697 - Update your Bluesky profile bio and banner 698 - Publish posts to your Leaflet publications 699 - Add site information via AT Protocol records 700 7012. **Deploy Your Site**: 702 - See [README.md](../README.md#-deployment) for deployment options 703 - Choose a platform (Vercel, Netlify, Cloudflare Pages, etc.) 704 - Configure production environment variables 705 - Set up custom domain 706 7073. **Enhance Your Site**: 708 - Add custom styling in `src/app.css` 709 - Create new components in `src/lib/components/` 710 - Extend functionality with new AT Protocol lexicons 711 - Customize layouts and pages 712 7134. **Monitor and Maintain**: 714 - Check RSS feeds regularly 715 - Update dependencies: `npm update` 716 - Monitor browser console for errors 717 - Keep AT Protocol records up to date 718 719--- 720 721## Configuration Checklist 722 723Use this checklist to track your configuration progress: 724 725### Required Configuration 726 727- [ ] Set `PUBLIC_ATPROTO_DID` in `.env.local` 728- [ ] Set `PUBLIC_SITE_TITLE` in `.env.local` 729- [ ] Set `PUBLIC_SITE_DESCRIPTION` in `.env.local` 730- [ ] Set `PUBLIC_SITE_KEYWORDS` in `.env.local` 731- [ ] Set `PUBLIC_SITE_URL` in `.env.local` 732- [ ] Configure slug mappings in `src/lib/config/slugs.ts` 733- [ ] Update `static/robots.txt` with your domain 734- [ ] Update `static/sitemap.xml` with your pages 735 736### Optional Configuration 737 738- [ ] Enable WhiteWind support (if needed) 739- [ ] Configure blog fallback URL (if desired) 740- [ ] Set CORS allowed origins for production 741- [ ] Replace favicon files with your branding 742- [ ] Update or remove `.well-known` files 743- [ ] Configure Slingshot URLs (if using local instance) 744 745### Verification (Checklist) 746 747- [ ] Development server starts without errors 748- [ ] Profile card loads correctly 749- [ ] Blog slug redirects work 750- [ ] RSS feeds generate successfully 751- [ ] Optional features display (if enabled) 752- [ ] SEO metadata is correct in page source 753- [ ] Site works on mobile, tablet, and desktop 754- [ ] Dark mode and wolf mode toggles work 755 756### Deployment Preparation 757 758- [ ] Test production build: `npm run build` 759- [ ] Preview production build: `npm run preview` 760- [ ] Configure production environment variables 761- [ ] Choose and configure deployment platform 762- [ ] Set up custom domain (if applicable) 763- [ ] Configure SSL certificate (handled by most platforms) 764 765--- 766 767**Configuration complete!** Your AT Protocol-powered personal website is ready to use. For detailed feature documentation, see [README.md](../README.md).