AbsoluteJS
AbsoluteJS

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