my website at ewancroft.uk
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs(readme): localise to British English and improve formatting

- Replaced straight quotes with curly ones (Ewan’s Corner)
- Localised spelling to en-GB (e.g. “optimisation”, “licence”, “prioritised”)
- Improved markdown formatting with trailing spaces for consistent line breaks
- Updated feature list for clarity and added missing config options
- Expanded blog system documentation with prioritisation and RSS details
- Added minor consistency fixes across sections (hyphenation, grammar, tone)

+145 -100
+145 -100
README.md
··· 1 - # Ewan's Corner 1 + # Ewan’s Corner 2 2 3 3 A modern, AT Protocol-powered personal website built with SvelteKit 2 and Tailwind CSS 4. 4 4 5 5 ## 🌟 Features 6 6 7 - - **AT Protocol Integration**: Fetch and display content from your AT Protocol repository 8 - - **Multi-Platform Blog**: Seamlessly aggregate blog posts from WhiteWind and Leaflet 9 - - **Dynamic Profile**: Automatically display your Bluesky profile information 10 - - **Custom Status**: Show real-time status updates using custom AT Protocol lexicons 11 - - **Link Board**: Display a Linkat board with emoji-styled link cards 12 - - **Bluesky Posts**: Showcase your latest non-reply Bluesky posts with rich media support 13 - - **Smart Blog Redirects**: Intelligent redirection system for blog post URLs 14 - - **Responsive Design**: Mobile-first design with dark mode support 15 - - **RSS Feed**: Intelligent RSS feed handling WhiteWind and Leaflet posts 16 - - **Type-Safe**: Full TypeScript support throughout the application 7 + - **AT Protocol Integration**: Fetch and display content from your AT Protocol repository 8 + - **Multi-Platform Blog**: Seamlessly aggregate blog posts from WhiteWind and/or Leaflet (configurable) 9 + - **Dynamic Profile**: Automatically display your Bluesky profile information 10 + - **Custom Status**: Show real-time status updates using custom AT Protocol lexicons 11 + - **Link Board**: Display a Linkat board with emoji-styled link cards 12 + - **Bluesky Posts**: Showcase your latest non-reply Bluesky posts with rich media support 13 + - **Smart Blog Redirects**: Intelligent redirection system for blog-post URLs with platform prioritisation 14 + - **Responsive Design**: Mobile-first layout with dark-mode support 15 + - **RSS Feed**: Intelligent RSS-feed handling for WhiteWind and/or Leaflet posts 16 + - **Type-Safe**: Full TypeScript support throughout the application 17 17 18 18 ## 🚀 Getting Started 19 19 20 20 ### Prerequisites 21 21 22 - - Node.js 18+ and npm 23 - - An AT Protocol DID (Decentralized Identifier) from Bluesky 22 + - Node.js 18+ and npm 23 + - An AT Protocol DID (Decentralised Identifier) from Bluesky 24 24 25 25 ### Installation 26 26 ··· 31 31 cd website-redesign 32 32 ``` 33 33 34 - 1. Install dependencies: 34 + 2. Install dependencies: 35 35 36 36 ```bash 37 37 npm install 38 38 ``` 39 39 40 - 1. Configure environment variables: 40 + 3. Configure environment variables: 41 41 42 - Copy the example environment file and update it with your information: 42 + Copy the example environment file and update it with your own information: 43 43 44 44 ```bash 45 45 cp .env .env.local ··· 56 56 57 57 # Optional: Specific Leaflet publication rkey for blog posts 58 58 PUBLIC_LEAFLET_BLOG_PUBLICATION= 59 + 60 + # Optional: Enable WhiteWind blog support (default: false) 61 + PUBLIC_ENABLE_WHITEWIND=false 59 62 60 63 # Optional: Fallback URL for missing blog posts 61 64 PUBLIC_BLOG_FALLBACK_URL= ··· 67 70 PUBLIC_SITE_URL="https://example.com" 68 71 ``` 69 72 70 - 1. Start the development server: 73 + 4. Start the development server: 71 74 72 75 ```bash 73 76 npm run dev 74 77 ``` 75 78 76 - Visit `http://localhost:5173` to see your site. 79 + Visit `http://localhost:5173` to view your site. 77 80 78 81 ## 📁 Project Structure 79 82 ··· 92 95 │ │ └── utils/ # Utility functions 93 96 │ ├── routes/ # SvelteKit routes 94 97 │ │ ├── blog/ # Blog redirect handlers 95 - │ │ ├── now/ # Status feed endpoints 96 - │ │ └── site/ # Site metadata pages 98 + │ │ ├── now/ # Status-feed endpoints 99 + │ │ └── site/ # Site-metadata pages 97 100 │ ├── app.css # Global styles 98 101 │ └── app.html # HTML template 99 102 ├── static/ # Static files (favicon, etc.) ··· 106 109 107 110 ### Core Services 108 111 109 - - **agents.ts**: Agent management with automatic PDS resolution and fallback to Bluesky public API 110 - - **fetch.ts**: Profile, status, site info, and links fetching 111 - - **posts.ts**: Blog posts, Leaflet publications, and Bluesky posts 112 - - **media.ts**: Image and blob URL handling 113 - - **cache.ts**: In-memory caching with TTL support 114 - - **types.ts**: TypeScript definitions for all data structures 112 + - **agents.ts**: Agent management with automatic PDS resolution and fallback to the Bluesky public API 113 + - **fetch.ts**: Profile, status, site info, and links fetching 114 + - **posts.ts**: Blog posts, Leaflet publications, and Bluesky posts 115 + - **media.ts**: Image and blob-URL handling 116 + - **cache.ts**: In-memory caching with TTL support 117 + - **types.ts**: TypeScript definitions for all data structures 115 118 116 119 ### Usage Example 117 120 ··· 130 133 131 134 ## 📝 Blog System 132 135 133 - The blog system supports multiple platforms and provides intelligent URL redirects: 136 + The blog system supports multiple platforms with configurable prioritisation and intelligent URL redirects. 134 137 135 138 ### Supported Platforms 136 139 137 - 1. **WhiteWind** (`com.whtwnd.blog.entry`) 138 - - Format: `https://whtwnd.com/{did}/{rkey}` 139 - - Automatically filters out drafts and non-public posts 140 + 1. **Leaflet** (`pub.leaflet.document`) – **Prioritised by default** 141 + - Format: Custom domain or `https://leaflet.pub/lish/{did}/{publication}/{rkey}` 142 + - Supports multiple publications 143 + - Respects `base_path` configuration 144 + - Always checked first 140 145 141 - 1. **Leaflet** (`pub.leaflet.document`) 142 - - Format: Custom domain or `https://leaflet.pub/lish/{did}/{publication}/{rkey}` 143 - - Supports multiple publications 144 - - Respects `base_path` configuration 146 + 2. **WhiteWind** (`com.whtwnd.blog.entry`) – **Optional, disabled by default** 147 + - Format: `https://whtwnd.com/{did}/{rkey}` 148 + - Automatically filters out drafts and non-public posts 149 + - Only checked if `PUBLIC_ENABLE_WHITEWIND=true` 145 150 146 151 ### Blog Routes 147 152 148 - - `/blog/{rkey}` - Smart redirect to the correct platform 149 - - `/blog/rss` - Intelligent RSS feed (WhiteWind posts or redirect to Leaflet RSS) 150 - - `/blog/atom` - Deprecated (returns 410 Gone, use RSS instead) 153 + - `/blog` – Redirects to your blog homepage (Leaflet by default, WhiteWind if configured) 154 + - `/blog/{rkey}` – Smart redirect to the correct platform (checks Leaflet first, then WhiteWind if enabled) 155 + - `/blog/rss` – Intelligent RSS feed (redirects to Leaflet RSS by default, or generates WhiteWind RSS if enabled) 156 + - `/blog/atom` – Deprecated (returns *410 Gone*, use RSS instead) 151 157 152 158 ### How It Works 153 159 154 - When a user visits `/blog/{rkey}`: 160 + **Priority Order:** 161 + 162 + 1. **Leaflet** is always checked first for blog posts 163 + 2. **WhiteWind** is only checked if `PUBLIC_ENABLE_WHITEWIND=true` 164 + 3. If neither platform has the post, it falls back to `PUBLIC_BLOG_FALLBACK_URL` if configured 165 + 4. Returns *404* if the post isn’t found and no fallback is set 166 + 167 + **When a user visits `/blog/{rkey}`:** 168 + 169 + 1. The system checks Leaflet for the post (with optional publication filtering) 170 + 2. If not found and WhiteWind is enabled, it checks WhiteWind 171 + 3. Redirects to the appropriate platform URL 172 + 4. Falls back to `PUBLIC_BLOG_FALLBACK_URL` if configured 173 + 5. Returns 404 if no post is found and no fallback exists 155 174 156 - 1. The system checks WhiteWind for the post 157 - 2. If not found, checks all Leaflet publications 158 - 3. Redirects to the appropriate platform URL 159 - 4. Falls back to `PUBLIC_BLOG_FALLBACK_URL` if configured 160 - 5. Returns 404 if post not found and no fallback 175 + **RSS Feed Behaviour:** 176 + 177 + - **WhiteWind disabled** (default): Redirects to Leaflet’s native RSS feed (includes full content) 178 + - **WhiteWind enabled with posts**: Generates an RSS feed with WhiteWind post links 179 + - **No posts found**: Returns 404 161 180 162 181 ### Configuration 163 182 164 - Control blog behavior with environment variables: 183 + Control blog behaviour with environment variables: 165 184 166 185 ```ini 167 - # Use a custom domain for Leaflet posts 186 + # Use a custom domain for Leaflet posts (recommended) 168 187 PUBLIC_LEAFLET_BASE_PATH=https://blog.example.com 169 188 170 189 # Only check a specific Leaflet publication 171 190 PUBLIC_LEAFLET_BLOG_PUBLICATION=3kzcijpj2z2a 191 + 192 + # Enable WhiteWind support (set to "true" to enable, default: "false") 193 + PUBLIC_ENABLE_WHITEWIND=false 172 194 173 195 # Fallback for missing posts 174 196 PUBLIC_BLOG_FALLBACK_URL=https://archive.example.com/blog 175 197 ``` 176 198 199 + ### Why Leaflet is Prioritised 200 + 201 + - **Better Performance**: Leaflet’s RSS feeds include full post content 202 + - **Custom Domains**: Native support for custom domains (e.g. `blog.example.com`) 203 + - **Rich Features**: Better media handling and publication management 204 + - **Active Development**: Leaflet is actively maintained and improved 205 + 206 + ### Enabling WhiteWind 207 + 208 + If you still use WhiteWind or want to support both platforms: 209 + 210 + ```ini 211 + PUBLIC_ENABLE_WHITEWIND=true 212 + ``` 213 + 214 + With WhiteWind enabled: 215 + 216 + - Blog posts are checked on both platforms (Leaflet first, then WhiteWind) 217 + - RSS feed includes WhiteWind posts if they exist 218 + - `/blog` redirects to WhiteWind if no Leaflet configuration is set 219 + 177 220 ## 🎨 Styling 178 221 179 222 The project uses: 180 223 181 - - **Tailwind CSS 4**: Latest Tailwind with new features 182 - - **@tailwindcss/typography**: Beautiful prose styling 183 - - **@tailwindcss/vite**: Vite plugin for Tailwind 184 - - **Custom Components**: Pre-built UI components with consistent styling 224 + - **Tailwind CSS 4**: Latest Tailwind with new features 225 + - **@tailwindcss/typography**: Beautiful prose styling 226 + - **@tailwindcss/vite**: Vite plugin for Tailwind 227 + - **Custom Components**: Pre-built UI components with consistent styling 185 228 186 229 ## 🏗️ Building for Production 187 230 ··· 199 242 200 243 This project uses `@sveltejs/adapter-auto`, which automatically selects the best adapter for your deployment platform: 201 244 202 - - **Vercel**: Automatic detection and optimization 203 - - **Netlify**: Automatic detection and optimization 204 - - **Cloudflare Pages**: Automatic detection and optimization 205 - - **Node.js**: Fallback option 245 + - **Vercel**: Automatic detection and optimisation 246 + - **Netlify**: Automatic detection and optimisation 247 + - **Cloudflare Pages**: Automatic detection and optimisation 248 + - **Node.js**: Fallback option 206 249 207 250 For other platforms, see the [SvelteKit adapters documentation](https://kit.svelte.dev/docs/adapters). 208 251 ··· 218 261 219 262 Store detailed site metadata including: 220 263 221 - - Technology stack 222 - - Privacy statement 223 - - Open source information 224 - - Credits and licenses 264 + - Technology stack 265 + - Privacy statement 266 + - Open-source information 267 + - Credits and licences 225 268 226 269 ### Link Board (`blue.linkat.board`) 227 270 ··· 231 274 232 275 ### Available Scripts 233 276 234 - - `npm run dev` - Start development server 235 - - `npm run build` - Build for production 236 - - `npm run preview` - Preview production build 237 - - `npm run check` - Type-check the project 238 - - `npm run check:watch` - Type-check in watch mode 239 - - `npm run format` - Format code with Prettier 240 - - `npm run lint` - Check code formatting 277 + - `npm run dev` – Start the development server 278 + - `npm run build` – Build for production 279 + - `npm run preview` – Preview the production build 280 + - `npm run check` – Type-check the project 281 + - `npm run check:watch` – Type-check in watch mode 282 + - `npm run format` – Format code with Prettier 283 + - `npm run lint` – Check code formatting 241 284 242 285 ### Code Quality 243 286 244 287 The project uses: 245 288 246 - - **TypeScript**: Full type safety 247 - - **Prettier**: Consistent code formatting 248 - - **svelte-check**: Svelte-specific linting 249 - - **ESLint**: (can be added if needed) 289 + - **TypeScript** – Full type safety 290 + - **Prettier** – Consistent code formatting 291 + - **svelte-check** – Svelte-specific linting 292 + - **ESLint** – (can be added if needed) 250 293 251 294 ## 📚 Reference Implementation 252 295 253 296 The `other/leaflet-main` directory contains the reference Leaflet implementation, which was used as inspiration for: 254 297 255 - - Feed generation 256 - - Publication handling 257 - - Document rendering 258 - - Bluesky integration 298 + - Feed generation 299 + - Publication handling 300 + - Document rendering 301 + - Bluesky integration 259 302 260 303 ## 🤝 Contributing 261 304 262 - Contributions are welcome! Please feel free to submit a Pull Request. 305 + Contributions are welcome! Please feel free to submit a pull request. 263 306 264 - ## 📄 License 307 + ## 📄 Licence 265 308 266 - This project is open source. See the site information section for details about the technology stack and licenses. 309 + This project is open-source. See the *Site Information* section for details about the technology stack and licences. 267 310 268 311 ## 🔗 Links 269 312 270 - - [AT Protocol Documentation](https://atproto.com/) 271 - - [SvelteKit Documentation](https://kit.svelte.dev/) 272 - - [Tailwind CSS Documentation](https://tailwindcss.com/) 273 - - [Bluesky](https://bsky.app/) 274 - - [WhiteWind](https://whtwnd.com/) 275 - - [Leaflet](https://leaflet.pub/) 313 + - [AT Protocol Documentation](https://atproto.com/) 314 + - [SvelteKit Documentation](https://kit.svelte.dev/) 315 + - [Tailwind CSS Documentation](https://tailwindcss.com/) 316 + - [Bluesky](https://bsky.app/) 317 + - [WhiteWind](https://whtwnd.com/) 318 + - [Leaflet](https://leaflet.pub/) 276 319 277 320 ## 💡 Tips 278 321 279 322 ### Finding Your DID 280 323 281 - 1. Visit your Bluesky profile 282 - 2. Click on "Settings" → "Advanced" 283 - 3. Your DID will be displayed there 284 - 4. Or visit `https://bsky.app/profile/{your-handle}` and check the page source 324 + 1. Visit your Bluesky profile 325 + 2. Click on **Settings → Advanced** 326 + 3. Your DID will be displayed there 327 + 4. Or visit `https://bsky.app/profile/{your-handle}` and check the page source 285 328 286 329 ### Cache Management 287 330 ··· 293 336 // Clear all cache 294 337 cache.clear(); 295 338 296 - // Clear specific entry 339 + // Clear a specific entry 297 340 cache.delete('profile:did:plc:...'); 298 341 ``` 299 342 ··· 305 348 306 349 ### Blog Posts Not Found 307 350 308 - 1. Check your `PUBLIC_ATPROTO_DID` is correct 309 - 2. Verify posts are not drafts (WhiteWind) or unpublished (Leaflet) 310 - 3. Check the publication configuration if using `PUBLIC_LEAFLET_BLOG_PUBLICATION` 351 + 1. Check your `PUBLIC_ATPROTO_DID` is correct 352 + 2. Verify posts are not drafts (WhiteWind) or unpublished (Leaflet) 353 + 3. Check the publication configuration if using `PUBLIC_LEAFLET_BLOG_PUBLICATION` 354 + 4. If using WhiteWind, ensure `PUBLIC_ENABLE_WHITEWIND=true` is set 355 + 5. Check the browser console for AT Protocol service errors 311 356 312 357 ### Profile Data Not Loading 313 358 314 - 1. Ensure your DID is publicly accessible 315 - 2. Check browser console for errors 316 - 3. Verify AT Protocol services are reachable 359 + 1. Ensure your DID is publicly accessible 360 + 2. Check the browser console for errors 361 + 3. Verify AT Protocol services are reachable 317 362 318 363 ### Build Errors 319 364 320 - 1. Clear `.svelte-kit` directory: `rm -rf .svelte-kit` 321 - 2. Remove node_modules: `rm -rf node_modules` 322 - 3. Reinstall dependencies: `npm install` 323 - 4. Try building again: `npm run build` 365 + 1. Clear the `.svelte-kit` directory: `rm -rf .svelte-kit` 366 + 2. Remove `node_modules`: `rm -rf node_modules` 367 + 3. Reinstall dependencies: `npm install` 368 + 4. Try building again: `npm run build` 324 369 325 - ## 🙏 Acknowledgments 370 + ## 🙏 Acknowledgements 326 371 327 - - Thanks to the AT Protocol team for creating an open protocol 328 - - Thanks to the Bluesky, WhiteWind, and Leaflet teams 329 - - Inspired by the personal web movement and IndieWeb principles 372 + - Thanks to the AT Protocol team for creating an open protocol 373 + - Thanks to the Bluesky, WhiteWind, and Leaflet teams 374 + - Inspired by the personal-web movement and IndieWeb principles 330 375 331 376 --- 332 377