Server-Side Rendering (SSR)
Coralite is built from the ground up as a Server-Side Rendering (SSR) first framework. Unlike traditional Single Page Applications (SPAs) that rely on heavy client-side JavaScript to render the initial UI, Coralite generates your HTML on the server during the build process.
Why Coralite chose SSR #
By prioritizing the server, Coralite provides a superior experience for both developers and users:
- Security: Access databases, use private API keys, or perform sensitive calculations without exposing secrets to the client.
- Performance: Offload heavy data processing to the server. The client only receives the final, processed state and pre-rendered HTML, leading to near-instant "First Meaningful Paint".
- SEO: Content fetched on the server is present in the initial HTML, making it easily indexable by search engines and social media crawlers.
Architecture: The Life of a Page #
Understanding how Coralite processes your code is key to building performant websites. The lifecycle follows three distinct phases:
- Build Phase (SSR): Coralite's compiler parses your components. It executes all
serverblocks, resolves attributes, and generates a static HTML file. Any data returned from theserverblock is serialized into a JSON state object and embedded in the page. - Paint Phase: The browser receives the pre-rendered HTML and instantly displays it to the user. At this point, the page is visible but not yet interactive.
- Hydration Phase: The Coralite runtime loads in the browser. It reads the serialized state, finds the dynamic components in the DOM, and "boots" them by running their
clientblocks. The component becomes interactive.
The Server Block #
The server block is the heart of Coralite's SSR capabilities. It is an async function that runs strictly on the server during the build phase.
Top-level imports in your component's script block are treated as server-side only unless they are specifically accessed by the client block. This allows you to import heavy server-side libraries (like database drivers) without them ever reaching the browser.
The following example shows the full loop: fetching data on the server, passing it to the state, and rendering it in the template.
<template id="user-profile">
<div class="user-card">
<h2>{{ user.name }}</h2>
<p>Rank: {{ user.rank }}</p>
</div>
</template>
<script type="module">
import { defineComponent } from 'coralite'
// Safely stays on the server
import { db } from '#lib/database'
export default defineComponent({
// The server block executes during the build phase
async server () {
// 1. Fetch data securely
const userData = await db.query('SELECT name, rank FROM users LIMIT 1')
// 2. Return data to automatically populate the state and template
return { user: userData }
}
})
</script>
AST Splicing & no-hydration #
By default, Coralite preserves component host tags (e.g., <my-component>) so it can find and hydrate them later. However, for static layout components, this wrapper tag is unnecessary and adds DOM bloat.
Adding the no-hydration attribute tells Coralite to perform AST Splicing: the host tag is completely removed from the final HTML, leaving only the inner HTML. This component will never hydrate on the client.
Before & After Splicing #
<!-- Source Code -->
<my-static-header no-hydration="">
<h1>Welcome</h1>
</my-static-header>
<!-- Final Rendered HTML -->
<header class="header-styles">
<h1>Welcome</h1>
</header>
Patterns & Anti-Patterns #
Recommended Patterns #
- Prerender Everything: If data doesn't change based on the user's session, fetch it in the
serverblock. - Strategic Splicing: Use
no-hydrationfor 90% of your site (headers, footers, static content) to keep the client-side JS bundle tiny. - Lean State: Only return data from the
serverblock that is actually needed by the template orclientblock.
Anti-Patterns #
- Browser APIs on Server: Do not use
window,document, orlocalStorageinside theserverblock. It will cause the build to fail. - Large State for Static Content: If you fetch a massive array of 1,000 items in a
no-hydrationcomponent, but only display the first 5, do not return the full array from theserverblock. Only return the exact data needed by the template to avoid serializing unneeded data into the HTML payload. - Heavy Hydration: Avoid putting complex logic in the
clientblock that runs on every page load if it could have been solved with CSS or static HTML.
Next: Learn more about Components and how they integrate with SSR.