Svelte
Server-render Svelte components with full type safety and automatic hydration.
Build Configuration
Add Svelte to your build by specifying the directory containing your Svelte components:
TS
1// Configure Svelte in your build
2const manifest = await build({
3 svelteDirectory: 'src/svelte/pages',
4 // Svelte components are compiled during build
5});Page Handler
Use handleSveltePageRequest with asset() to get the compiled paths for both the page and index files:
TS
1// backend/server.ts
2import { handleSveltePageRequest, asset } from '@absolutejs/absolute';
3
4new Elysia()
5 .get('/dashboard', async ({ cookie }) => {
6 const user = await getUser(cookie);
7 const stats = await getStats(user.id);
8
9 // Both the page and index use asset() to get the compiled paths
10 return handleSveltePageRequest(
11 asset(manifest, 'Dashboard'), // Compiled page for SSR
12 asset(manifest, 'DashboardIndex'), // Compiled index for hydration
13 { user, stats }
14 );
15 })Components
Svelte components receive typed props via exports. Use svelte:head for meta tags:
SVELTE
1<!-- src/svelte/pages/Dashboard.svelte -->
2<script lang="ts">
3 type DashboardProps = {
4 user: User;
5 stats: Stats;
6 };
7
8 export let user: DashboardProps['user'];
9 export let stats: DashboardProps['stats'];
10</script>
11
12<svelte:head>
13 <title>Dashboard | {user.name}</title>
14</svelte:head>
15
16<main>
17 <h1>Welcome back, {user.name}</h1>
18
19 <div class="stats-grid">
20 <div class="stat">
21 <span class="label">Total Views</span>
22 <span class="value">{stats.views}</span>
23 </div>
24 <div class="stat">
25 <span class="label">Revenue</span>
26 <span class="value">${stats.revenue}</span>
27 </div>
28 </div>
29</main>
30
31<style>
32 .stats-grid {
33 display: grid;
34 grid-template-columns: repeat(2, 1fr);
35 gap: 1rem;
36 }
37</style>Compilation
During the build process, each raw .svelte file is compiled into two separate JavaScript files:
TS
// Your raw Svelte file:
src/svelte/pages/Dashboard.svelte
// Gets compiled into two files:
build/DashboardPage.js // Compiled page component for SSR
build/DashboardIndex.js // Compiled index file for client hydration- Page file: The compiled component used for server-side rendering
- Index file: The compiled hydration script that makes the page interactive on the client
Type Safety
Svelte components enjoy the same end-to-end type safety as React. Define your database schema and infer types directly from your table definitions using Drizzle:
TS
1// db/schema.ts
2import { pgTable, text, integer } from 'drizzle-orm/pg-core';
3
4export const users = pgTable('users', {
5 id: text('id').primaryKey(),
6 name: text('name').notNull(),
7 avatar: text('avatar')
8});
9
10export const stats = pgTable('stats', {
11 id: text('id').primaryKey(),
12 userId: text('user_id').notNull().references(() => users.id),
13 views: integer('views').notNull().default(0),
14 revenue: integer('revenue').notNull().default(0)
15});
16
17// types/databaseTypes.ts
18export type User = typeof users.$inferSelect;
19export type Stats = typeof stats.$inferSelect;Use those types in your server handlers to ensure props match your components:
TS
1// backend/server.ts
2import { User, Stats } from '../types/databaseTypes';
3
4type DashboardProps = {
5 user: User;
6 stats: Stats;
7};
8
9new Elysia()
10 .get('/dashboard', async ({ cookie }) => {
11 const user = await getUser(cookie);
12 const stats = await getStats(user.id);
13
14 // TypeScript error if props don't match DashboardProps!
15 return handleSveltePageRequest(
16 asset(manifest, 'DashboardPage'),
17 asset(manifest, 'DashboardIndex'),
18 { user, stats }
19 );
20 })- Schema → Types: Drizzle infers types directly from your table definitions
- Types → Server: Your inferred types flow into route handlers and props
- Props → Component: Svelte receives correctly typed props on both server and client