SSR safety
Every rune state class in @cstar.help/svelte checks typeof window === 'undefined' before wiring real-time subscriptions. SSR renders a
loading state; the browser takes over on hydration. No export const ssr = false needed.
Why it matters
Real-time state classes used to crash during SSR because they tried to open SSE connections in
Node. Setting ssr = false on every chat-bearing route was a footgun — broke Lighthouse,
broke OG previews, and forced full client renders for surfaces that didn't need them. The state classes
now defer subscribe-wiring until they detect a browser.
The pattern
<script>
import { ArticlesState } from '@cstar.help/svelte';
// Construction is safe on the server — fields are empty until hydration.
// First arg is the client (undefined = read from CStarLibraryProvider);
// second arg is the list params.
const articles = new ArticlesState(undefined, { categorySlug: 'billing' });
</script>
<!-- Renders a static loading state on the server, real data after hydration -->
{#if articles.isLoading}
<p>Loading…</p>
{:else}
{#each articles.articles as a (a.id)}
<a href="/help/{a.slug}">{a.title}</a>
{/each}
{/if}Prerendering with real data
If you want the help center to render with content during SSR (for SEO), fetch in a +page.server.js with the JS client and pass it through props. The state class on the
client picks up where the server left off.
import { LibraryClient } from '@cstar.help/js/library';
export const prerender = true;
export async function load() {
const library = new LibraryClient({ teamSlug: 'acme' });
const articles = await library.articles({ limit: 20 });
return { articles };
}