# svelte-standard-site Examples This file contains comprehensive examples of using svelte-standard-site in various scenarios. ## Table of Contents - [Basic Setup](#basic-setup) - [Simple Blog](#simple-blog) - [Using Utility Components](#using-utility-components) - [Building Custom Cards](#building-custom-cards) - [Multi-Publication Site](#multi-publication-site) - [Custom Styling](#custom-styling) - [Custom Layout](#custom-layout) - [Programmatic Theme Control](#programmatic-theme-control) - [Internationalization](#internationalization) - [Server-Side Rendering](#server-side-rendering) ## Basic Setup ### 1. Install and Configure ```bash pnpm add svelte-standard-site ``` Create `.env`: ```env PUBLIC_ATPROTO_DID=did:plc:your-did-here ``` ### 2. Root Layout ```svelte {@render children()} ``` ### 3. Home Page ```svelte

Welcome!

{#each data.publications as publication} {/each}
``` ## Simple Blog ### Load Function ```typescript // src/routes/blog/+page.server.ts import { createClient } from 'svelte-standard-site'; import { getConfigFromEnv } from 'svelte-standard-site/config/env'; import type { PageServerLoad } from './$types'; export const load: PageServerLoad = async ({ fetch }) => { const config = getConfigFromEnv(); if (!config) { throw new Error('Missing AT Proto configuration'); } const client = createClient(config); const documents = await client.fetchAllDocuments(fetch); return { posts: documents }; }; ``` ### Blog Index Page ```svelte

Blog Posts

Thoughts, tutorials, and updates

{#each data.posts as post} {/each}
``` ### Individual Post Page ```typescript // src/routes/blog/[pub_rkey]/[doc_rkey]/+page.server.ts import { createClient } from 'svelte-standard-site'; import { getConfigFromEnv } from 'svelte-standard-site/config/env'; import { error } from '@sveltejs/kit'; import type { PageServerLoad } from './$types'; export const load: PageServerLoad = async ({ params, fetch }) => { const config = getConfigFromEnv(); if (!config) { throw new Error('Missing configuration'); } const client = createClient(config); const document = await client.fetchDocument(params.doc_rkey, fetch); if (!document) { throw error(404, 'Post not found'); } return { post: document }; }; ``` ```svelte {post.title} - My Blog {#if post.description} {/if}
{#if post.coverImage} {post.title} {/if}

{post.title}

{#if post.updatedAt} Updated: {formatDate(post.updatedAt)} {/if}
{#if post.tags && post.tags.length > 0}
{#each post.tags as tag} {tag} {/each}
{/if}
{@html post.content || post.textContent || ''}
``` ## Using Utility Components The modular utility components make it easy to build consistent, theme-aware UIs. ### Using DateDisplay ```svelte

{data.post.value.title}

``` ### Using TagList ```svelte ``` ### Using ThemedText ```svelte {data.post.value.title} {data.post.value.description} Read more → ``` ### Combining Utility Components ```svelte {data.post.value.title} {data.post.value.description}
{#if data.post.value.updatedAt} {/if}
{@html data.post.value.content}
``` ## Building Custom Cards Use ThemedCard and utility components to build custom card layouts. ### Blog Post Card ```svelte
{#if value.coverImage} {value.title} {/if}
{value.title} {#if value.description} {value.description} {/if}
{#if value.tags?.length} {/if}
``` ### Author Card ```svelte
{#if avatar} {name} {/if}
{name} {bio}
``` ### Feature Card with Icon ```svelte
{@render icon()}
{title} {description}
``` ## Internationalization ### Automatic Locale Detection The DateDisplay component automatically detects the user's browser locale. ```svelte ``` ### Explicit Locale Override ```svelte ``` ### Multi-Language Blog ```svelte {data.post.value.title}
{@html data.post.value.content}
``` ## Multi-Publication Site ```typescript // src/routes/+page.server.ts import { createClient } from 'svelte-standard-site'; import { getConfigFromEnv } from 'svelte-standard-site/config/env'; import type { PageServerLoad } from './$types'; export const load: PageServerLoad = async ({ fetch }) => { const config = getConfigFromEnv(); if (!config) { return { error: 'Configuration missing', publications: [], documents: [] }; } const client = createClient(config); const [publications, documents] = await Promise.all([ client.fetchAllPublications(fetch), client.fetchAllDocuments(fetch) ]); // Group documents by publication const documentsByPub = new Map(); for (const doc of documents) { const pubUri = doc.value.site; if (!documentsByPub.has(pubUri)) { documentsByPub.set(pubUri, []); } documentsByPub.get(pubUri).push(doc); } return { publications, documents, documentsByPub: Object.fromEntries(documentsByPub) }; }; ``` ```svelte {#each data.publications as publication}

Recent from {publication.value.name}

{#if data.documentsByPub[publication.uri]}
{#each data.documentsByPub[publication.uri].slice(0, 5) as document} {/each}
{:else}

No documents yet

{/if}
{/each}
``` ## Custom Styling ### Override Theme Colors ```css /* src/app.css or src/lib/styles/custom.css */ @import 'svelte-standard-site/styles/base.css'; /* Override primary color */ :root { --color-primary-50: oklch(18.2% 0.018 280); --color-primary-100: oklch(26.5% 0.03 280); --color-primary-200: oklch(40.5% 0.048 280); --color-primary-300: oklch(54% 0.065 280); --color-primary-400: oklch(66.5% 0.08 280); --color-primary-500: oklch(78.5% 0.095 280); --color-primary-600: oklch(82.2% 0.078 280); --color-primary-700: oklch(86.5% 0.062 280); --color-primary-800: oklch(91% 0.042 280); --color-primary-900: oklch(95.8% 0.022 280); --color-primary-950: oklch(98% 0.012 280); } ``` ### Custom Component Styles ```svelte ``` ## Custom Layout ### Full Custom Layout with Theme Support ```svelte
{@render children()}
``` ## Programmatic Theme Control ### Theme Toggle Button ```svelte ``` ### System Preference Detection ```svelte
``` ## Server-Side Rendering ### Pre-render Static Pages ```typescript // svelte.config.js import adapter from '@sveltejs/adapter-static'; export default { kit: { adapter: adapter({ pages: 'build', assets: 'build', fallback: null, precompress: false }), prerender: { entries: ['*'] } } }; ``` ### Generate Dynamic Routes ```typescript // src/routes/blog/[pub_rkey]/[doc_rkey]/+page.server.ts import { createClient } from 'svelte-standard-site'; import { getConfigFromEnv } from 'svelte-standard-site/config/env'; import { error } from '@sveltejs/kit'; import type { PageServerLoad, EntryGenerator } from './$types'; export const load: PageServerLoad = async ({ params, fetch }) => { const config = getConfigFromEnv(); if (!config) throw error(500, 'Configuration missing'); const client = createClient(config); const document = await client.fetchDocument(params.doc_rkey, fetch); if (!document) throw error(404, 'Post not found'); return { post: document }; }; export const entries: EntryGenerator = async () => { const config = getConfigFromEnv(); if (!config) return []; const client = createClient(config); const documents = await client.fetchAllDocuments(); return documents.map((doc) => { const pubRkey = doc.value.site.split('/').pop() || ''; const docRkey = doc.uri.split('/').pop() || ''; return { pub_rkey: pubRkey, doc_rkey: docRkey }; }); }; ``` ## Tips and Best Practices 1. **Always import base.css** in your root layout for consistent styling 2. **Use the ThemeToggle component** or manage theme with themeStore 3. **Leverage utility components** - Use DateDisplay, TagList, ThemedText, etc. for consistency 4. **Follow DRY principles** - Don't manually format dates or apply theme colors repeatedly 5. **Leverage the design tokens** (ink, canvas, primary, etc.) for consistency 6. **Pass custom classes** to components for one-off customizations 7. **Use server-side rendering** for better SEO and performance 8. **Cache aggressively** - the library has built-in caching 9. **Handle errors gracefully** - always check for null/undefined data 10. **Test dark mode** - all components support it out of the box 11. **Embrace locale-aware dates** - DateDisplay automatically formats for user's locale For more examples and detailed documentation, visit the [GitHub repository](https://github.com/ewanc26/svelte-standard-site).