SvelteKit with DaisyUI provides a compiler-based framework for building blazing-fast web applications with minimal bundle sizes.
Overview
SvelteKit compiles your code to highly optimized vanilla JavaScript, resulting in smaller bundles and better runtime performance.
Pre-installed Packages
SvelteKit : Full-stack framework with file-based routing
Svelte : Compiler-based UI framework
DaisyUI : Tailwind CSS component library
Tailwind CSS : Utility-first CSS framework
TypeScript : Full type safety
Vite : Fast development server and build tool
Key Features
Compile-time framework (no virtual DOM)
Reactive declarations with $:
Built-in state management
File-based routing
Server-side rendering
Zero-config setup
Smallest bundle sizes
Use Cases
SvelteKit is best suited for:
Performance-Critical Apps Applications requiring minimal bundle size and maximum performance
Fast Websites Sites that prioritize loading speed and runtime performance
Simple Syntax Projects Projects that benefit from Svelte’s straightforward syntax
Full-Stack Apps Applications using SvelteKit’s server-side capabilities
DaisyUI Components
DaisyUI is a plugin for Tailwind CSS that provides semantic component classes without JavaScript dependencies.
Available Components
Actions : Button, Dropdown, Modal, Swap
Data Display : Accordion, Avatar, Badge, Card, Carousel, Chat Bubble, Collapse, Countdown, Kbd, Stat, Table, Timeline
Navigation : Breadcrumbs, Bottom Navigation, Link, Menu, Navbar, Pagination, Steps, Tabs
Feedback : Alert, Loading, Progress, Radial Progress, Skeleton, Toast, Tooltip
Data Input : Checkbox, File Input, Radio, Range, Rating, Select, Text Input, Textarea, Toggle
Layout : Artboard, Divider, Drawer, Footer, Hero, Indicator, Join, Mask, Stack
Mockup : Browser, Code, Phone, Window
Component Usage
Critical Rules
Main File : The main page is src/routes/+page.svelte. Layout is in src/routes/+layout.svelte.
Pre-installed : DaisyUI and Tailwind CSS are already installed. Do not run installation commands for these packages.
File Conventions
Page files : +page.svelte (in routes/)
Layout files : +layout.svelte (in routes/)
Component files : ComponentName.svelte (PascalCase)
Components directory : src/lib/components/
Utilities directory : src/lib/utils/
Types directory : src/lib/types/
Stores directory : src/lib/stores/
Component Structure
< script lang = "ts" >
import { onMount } from 'svelte' ;
// Props
export let title : string ;
export let count = 0 ;
// Reactive declarations
$ : doubled = count * 2 ;
$ : isEven = count % 2 === 0 ;
// Functions
function increment () {
count ++ ;
}
// Lifecycle
onMount (() => {
console . log ( 'Component mounted' );
});
</ script >
< div >
< h1 > { title } </ h1 >
< p > Count: { count } </ p >
< p > Doubled: { doubled } </ p >
< p > Is even: { isEven } </ p >
< button class = "btn" on : click = { increment } > Increment </ button >
</ div >
< style >
/* Component-scoped styles or use Tailwind classes */
</ style >
Project Structure
src/
├── routes/
│ ├── +page.svelte # Main page
│ └── +layout.svelte # Root layout
├── lib/
│ ├── components/ # Reusable components
│ ├── stores/ # Svelte stores
│ ├── utils/ # Utility functions
│ └── types/ # TypeScript types
└── app.html # HTML template
Reactive Declarations
Svelte’s reactive declarations automatically update when dependencies change:
Basic Reactivity
Reactive Statements
Array Reactivity
< script lang = "ts" >
let count = 0 ;
// Automatically recalculates when count changes
$ : doubled = count * 2 ;
$ : tripled = count * 3 ;
$ : message = count > 10 ? 'High' : 'Low' ;
</ script >
< div >
< p > Count: { count } </ p >
< p > Doubled: { doubled } </ p >
< p > Tripled: { tripled } </ p >
< p > Status: { message } </ p >
< button class = "btn" on : click = { () => count ++ } > Increment </ button >
</ div >
< script lang = "ts" >
let count = 0 ;
// Runs whenever count changes
$ : if ( count > 5 ) {
console . log ( 'Count is greater than 5' );
}
// Multiple statements
$ : {
console . log ( 'Count changed:' , count );
document . title = `Count: ${ count } ` ;
}
</ script >
< script lang = "ts" >
let items = [ 1 , 2 , 3 ];
// Reactive length
$ : itemCount = items . length ;
$ : total = items . reduce (( sum , item ) => sum + item , 0 );
function addItem () {
// Trigger reactivity with assignment
items = [ ... items , items . length + 1 ];
}
function removeItem () {
items = items . slice ( 0 , - 1 );
}
</ script >
< div >
< p > Items: { itemCount } </ p >
< p > Total: { total } </ p >
< button class = "btn" on : click = { addItem } > Add </ button >
< button class = "btn" on : click = { removeItem } > Remove </ button >
</ div >
Svelte Stores
For global state management:
// src/lib/stores/counter.ts
import { writable , derived , readable } from 'svelte/store' ;
// Writable store
export const count = writable ( 0 );
export function increment () {
count . update ( n => n + 1 );
}
export function decrement () {
count . update ( n => n - 1 );
}
export function reset () {
count . set ( 0 );
}
// Derived store
export const doubled = derived ( count , $count => $count * 2 );
// Readable store
export const time = readable ( new Date (), function start ( set ) {
const interval = setInterval (() => {
set ( new Date ());
}, 1000 );
return function stop () {
clearInterval ( interval );
};
});
<!-- Usage in component -->
< script lang = "ts" >
import { count , doubled , increment , decrement , reset } from '$lib/stores/counter' ;
</ script >
< div >
< p > Count: { $ count } </ p >
< p > Doubled: { $ doubled } </ p >
< button class = "btn" on : click = { increment } > + </ button >
< button class = "btn" on : click = { decrement } > - </ button >
< button class = "btn" on : click = { reset } > Reset </ button >
</ div >
DaisyUI Theming
DaisyUI includes multiple built-in themes:
<!-- src/app.html -->
< html data-theme = "light" >
<!-- Available themes:
light, dark, cupcake, bumblebee, emerald, corporate, synthwave,
retro, cyberpunk, valentine, halloween, garden, forest, aqua,
lofi, pastel, fantasy, wireframe, black, luxury, dracula
-->
</ html >
Conditional Rendering & Loops
< script lang = "ts" >
let loggedIn = false ;
</ script >
{# if loggedIn }
< p > Welcome back! </ p >
{: else }
< button class = "btn" > Login </ button >
{/ if }
< script lang = "ts" >
let items = [
{ id: 1 , name: 'Apple' },
{ id: 2 , name: 'Banana' },
{ id: 3 , name: 'Cherry' }
];
</ script >
< ul >
{# each items as item ( item . id )}
< li > { item . name } </ li >
{: else }
< li > No items </ li >
{/ each }
</ ul >
< script lang = "ts" >
async function fetchData () {
const res = await fetch ( 'https://api.example.com/data' );
return res . json ();
}
let promise = fetchData ();
</ script >
{# await promise }
< div class = "loading loading-spinner" ></ div >
{: then data }
< div > { JSON . stringify ( data ) } </ div >
{: catch error }
< div class = "alert alert-error" > { error . message } </ div >
{/ await }
Best Practices
Use reactive declarations for computed values
< script >
let firstName = 'John' ;
let lastName = 'Doe' ;
// Automatically updates when firstName or lastName change
$ : fullName = ` ${ firstName } ${ lastName } ` ;
</ script >
Use stores for global state
// lib/stores/user.ts
import { writable } from 'svelte/store' ;
export const user = writable ( null );
Use bind: for two-way binding
< input class = "input" bind : value = { name } />
<!-- Instead of value={name} on:input={...} -->
Use transitions and animations
< script >
import { fade , slide } from 'svelte/transition' ;
</ script >
{# if visible }
< div transition : fade > Fades in and out </ div >
< div transition : slide > Slides in and out </ div >
{/ if }
Use component slots for composition
<!-- Card.svelte -->
< div class = "card" >
< slot name = "header" />
< slot />
< slot name = "footer" />
</ div >
<!-- Usage -->
< Card >
< h2 slot = "header" > Title </ h2 >
< p > Content </ p >
< button slot = "footer" class = "btn" > Action </ button >
</ Card >