17.2 Environment Setup
There are two main ways to set up a Svelte development environment: using SvelteKit (the full-stack framework) or a plain Svelte + Vite combination. For most real-world projects, SvelteKit is recommended.
Prerequisites
# Check Node.js version (18+ required)
node --version # v18.x.x or higher
# Check npm version
npm --version # 8+ recommended
# Install VS Code extension
# "Svelte for VS Code" (svelte.svelte-vscode)
Option 1: Create a Project with SvelteKit (Recommended)
SvelteKit is the official application framework for Svelte. It supports routing, SSR, SSG, API endpoints, and more.
# Create a SvelteKit project
npm create svelte@latest my-svelte-app
# Interactive prompts
# ┌ Welcome to SvelteKit!
# │
# ◆ Which Svelte app template?
# │ ○ SvelteKit demo app
# │ ● Skeleton project ← recommended
# │ ○ Library project
# │
# ◆ Add type checking with TypeScript?
# │ ○ Yes, using TypeScript syntax
# │ ● Yes, using JavaScript with JSDoc comments
# │ ○ No
# │
# ◆ Select additional options
# │ ☑ Add ESLint for code linting
# │ ☑ Add Prettier for code formatting
# │ ☑ Add Playwright for browser testing
# │ ☑ Add Vitest for unit testing
cd my-svelte-app
npm install
npm run dev
Starting the Development Server
npm run dev # Dev server (localhost:5173)
npm run dev -- --open # Auto-open browser
npm run build # Production build
npm run preview # Preview the build
Option 2: Plain Svelte + Vite
Use this when you only need a simple SPA (Single Page Application) without SvelteKit.
# Create a Svelte project with Vite template
npm create vite@latest my-svelte-app -- --template svelte
# TypeScript version
npm create vite@latest my-svelte-app -- --template svelte-ts
cd my-svelte-app
npm install
npm run dev
Project Directory Structure (SvelteKit)
my-svelte-app/
├── src/
│ ├── app.html # HTML entry point (base HTML shell)
│ ├── app.css # Global CSS
│ ├── lib/ # Reusable code ($lib alias)
│ │ ├── components/ # Shared components
│ │ ├── stores/ # Svelte stores
│ │ └── utils/ # Utility functions
│ └── routes/ # File-based routing
│ ├── +layout.svelte # Root layout
│ ├── +page.svelte # / route
│ └── about/
│ └── +page.svelte # /about route
├── static/ # Static files (images, fonts, etc.)
├── tests/ # Test files
├── svelte.config.js # Svelte/SvelteKit config
├── vite.config.js # Vite config
└── package.json
src/app.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
%sveltekit.head%: Content injected by SvelteKit (title, meta, link tags)%sveltekit.body%: The actual page content%sveltekit.assets%: Path to static assets
Key svelte.config.js Settings
// svelte.config.js
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Preprocessor settings (TypeScript, SCSS, etc.)
preprocess: vitePreprocess(),
kit: {
// Adapter (change based on deployment target)
adapter: adapter(),
// Path aliases
alias: {
$lib: 'src/lib',
$components: 'src/lib/components',
$stores: 'src/lib/stores',
},
// CSRF protection
csrf: {
checkOrigin: true,
},
// Environment variable prefix
env: {
publicPrefix: 'PUBLIC_',
},
},
// Svelte compiler options
compilerOptions: {
// Enable Runes mode globally (Svelte 5)
// runes: true, // Uncomment to apply Runes to all files
},
};
export default config;
TypeScript Setup
When using TypeScript, tsconfig.json is automatically generated:
// tsconfig.json
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true
}
}
TypeScript Svelte Component
<!-- Counter.svelte -->
<script lang="ts">
interface Props {
initialCount?: number;
label?: string;
}
let { initialCount = 0, label = 'Counter' }: Props = $props();
let count = $state(initialCount);
function increment(): void {
count++;
}
function reset(): void {
count = initialCount;
}
</script>
<div>
<h2>{label}: {count}</h2>
<button onclick={increment}>+1</button>
<button onclick={reset}>Reset</button>
</div>
Vite Configuration
// vite.config.js
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()],
// Dev server settings
server: {
port: 5173,
open: true,
},
// Build optimization
build: {
target: 'es2020',
sourcemap: true,
},
// Test settings (Vitest)
test: {
include: ['src/**/*.{test,spec}.{js,ts}'],
environment: 'jsdom',
globals: true,
setupFiles: ['./src/setupTests.ts'],
},
});
VS Code Extensions and Settings
Essential Extensions
- Svelte for VS Code (
svelte.svelte-vscode): Syntax highlighting, autocomplete, type checking - ESLint (
dbaeumer.vscode-eslint): Code quality - Prettier (
esbenp.prettier-vscode): Code formatting
.vscode/settings.json
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"[svelte]": {
"editor.defaultFormatter": "svelte.svelte-vscode"
},
"svelte.enable-ts-plugin": true,
"typescript.preferences.importModuleSpecifier": "shortest"
}
.prettierrc
{
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"plugins": ["prettier-plugin-svelte"],
"overrides": [
{
"files": "*.svelte",
"options": {
"parser": "svelte"
}
}
]
}
Adapters Overview
SvelteKit uses Adapters to deploy to different platforms. An adapter converts the build output to fit a specific deployment environment.
| Adapter | Package | Use Case |
|---|---|---|
adapter-auto | @sveltejs/adapter-auto | Auto-detect platform (default) |
adapter-node | @sveltejs/adapter-node | Node.js server |
adapter-static | @sveltejs/adapter-static | Static site (SSG) |
adapter-cloudflare | @sveltejs/adapter-cloudflare | Cloudflare Pages |
adapter-vercel | @sveltejs/adapter-vercel | Vercel |
adapter-netlify | @sveltejs/adapter-netlify | Netlify |
// svelte.config.js - static adapter example
import adapter from '@sveltejs/adapter-static';
export default {
kit: {
adapter: adapter({
pages: 'build',
assets: 'build',
fallback: '404.html',
precompress: false,
strict: true,
}),
prerender: {
handleHttpError: 'warn',
},
},
};
Building Your First Component
After creating the project, let's update the first page:
<!-- src/routes/+page.svelte -->
<script>
import Counter from '$lib/Counter.svelte';
</script>
<main>
<h1>My First Svelte App</h1>
<Counter initialCount={5} label="Visit Count" />
</main>
<style>
main {
max-width: 800px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
</style>
<!-- src/lib/Counter.svelte -->
<script>
let { initialCount = 0, label = 'Counter' } = $props();
let count = $state(initialCount);
</script>
<div class="counter">
<p>{label}: <strong>{count}</strong></p>
<button onclick={() => count--}>-</button>
<button onclick={() => count++}>+</button>
</div>
<style>
.counter {
display: inline-flex;
align-items: center;
gap: 1rem;
padding: 1rem 2rem;
border: 2px solid #ff3e00;
border-radius: 8px;
}
button {
width: 36px;
height: 36px;
background: #ff3e00;
color: white;
border: none;
border-radius: 50%;
font-size: 1.2rem;
cursor: pointer;
}
</style>
Development Commands Reference
npm run dev # Start dev server
npm run build # Production build
npm run preview # Preview the build
npm run check # TypeScript + Svelte type check
npm run lint # Run ESLint
npm run format # Run Prettier
npm run test # Run Vitest unit tests
npm run test:e2e # Run Playwright E2E tests
Pro Tips
Tip 1: Environment Variable Management
# .env file
DATABASE_URL=postgresql://... # Server-only (never exposed)
PUBLIC_API_URL=https://api.example.com # Safe for client
<script>
import { PUBLIC_API_URL } from '$env/static/public';
import { DATABASE_URL } from '$env/static/private'; // Server components only
</script>
Tip 2: Use Path Aliases
<!-- Use aliases instead of relative paths -->
<script>
// Not recommended
import Button from '../../../lib/components/Button.svelte';
// Recommended
import Button from '$lib/components/Button.svelte';
</script>
Tip 3: SvelteKit Inspector
Click a component in dev mode to jump directly to its source file:
# Set environment variable
SVELTE_INSPECTOR=true npm run dev
Or configure in svelte.config.js:
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
export default {
preprocess: vitePreprocess(),
vitePlugin: {
inspector: {
holdMode: true, // Only activate when holding a key
},
},
};
Summary
| Tool | Role |
|---|---|
| SvelteKit | Routing, SSR, API, full-stack support |
| Vite | Bundler, dev server, HMR |
svelte.config.js | Svelte compiler and SvelteKit settings |
vite.config.js | Vite build settings |
| Adapter | Deployment platform targeting |
$lib alias | Shorthand for src/lib path |
The next chapter dives into Svelte 5's reactivity system and the Runes API.