Virtual Modules
Reference for $models, $schema, $validation, $db, $auth and other omni-svelte path aliases.
Virtual Modules
omni-svelte injects a set of virtual modules and path aliases so you can import framework features without hardcoding file paths. All of them are resolved by the Vite plugin — nothing extra to configure.
Overview
Importing a server-only alias from a universal context (
+page.ts,+layout.ts) triggers a Vite build warning. Use+page.server.ts/+layout.server.tsinstead.
$models — typed model classes
// +page.server.ts
import { Posts } from '$models'; // barrel — all models
import { Posts } from '$models/posts.model'; // single model (IDE-friendly)
export const load = async () => {
const posts = await Posts.query()
.where('published', true)
.orderBy('created_at', 'desc')
.limit(10)
.get();
return { posts };
};Generated from your .schema.ts files. The barrel re-exports every *.model.ts file in schema.output.model.path.
$schema — Drizzle table definitions
// src/lib/db/server/+server.ts
import { db } from '$db';
import { posts, users } from '$schema';
import { eq } from 'drizzle-orm';
const publishedPosts = await db.select().from(posts).where(eq(posts.published, true));$schema exports everything from your generated Drizzle schema file (schema.output.drizzle.path).
$db — raw database connection
import { db } from '$db';
import type { PostgresJsDatabase } from 'drizzle-orm/postgres-js';The db export is a fully typed PostgresJsDatabase instance. Use it when you need raw Drizzle queries beyond what the model API provides.
$validation — Zod schemas
// Universal — safe for both server and client
import { postsCreateSchema, postsUpdateSchema } from '$validation';
import { postsCreateSchema } from '$validation/posts.validation'; // single file
// Validate form data
const result = postsCreateSchema.safeParse(Object.fromEntries(formData));
if (!result.success) {
return fail(400, { errors: result.error.flatten() });
}Validation schemas are the only virtual module safe to use in client-side code and universal SvelteKit routes.
$auth/server and $auth/client
// Server (hooks.server.ts, +page.server.ts, API routes)
import { auth } from '$auth/server';
const session = await auth.api.getSession({ headers: request.headers });
// Client (+page.svelte, stores)
import { authClient } from '$auth/client';
await authClient.signIn.email({ email, password });Powered by Better-Auth. The server instance is auto-generated from your omni.auth config in svelte.config.js.
TypeScript IDE support
Auto-generated: src/omni-env.d.ts
omni-svelte writes this file automatically on dev-server start. It declares the barrel aliases so TypeScript always knows their shape:
// src/omni-env.d.ts ← do not edit manually
declare module '$models' {
export * from '$lib/db/models/index';
}
declare module '$schema' {
export * from '$lib/db/server/schema';
}
declare module '$validation' {
export * from '$lib/db/validation/index';
}
declare module '$db' {
export const db: PostgresJsDatabase;
}Manual: sub-path shims
For per-file sub-path imports the IDE can't auto-resolve, add a test-env.d.ts in your project root (already included in the playground):
// test-env.d.ts
declare module '$models/posts.model' {
export * from '$lib/db/models/posts.model'; // ← must be $lib/..., not ./
}Make sure this file is included in your tsconfig.json:
{
"extends": "./.svelte-kit/tsconfig.json",
"include": ["test-env.d.ts", "src/**/*.ts", "src/**/*.svelte"]
}Customising output paths
All virtual module resolution follows the schema.output config you set in svelte.config.js. Changing a path there re-generates src/omni-env.d.ts automatically:
// svelte.config.js
omni: {
schema: {
output: {
model: { path: 'src/lib/db/models', format: 'per-schema' },
drizzle: { path: 'src/lib/db/server/schema.ts', format: 'single-file' },
zod: { path: 'src/lib/db/validation', format: 'per-schema' },
}
}
}