02 - Project Setup & Structure

Creating a Project

npx sv create my-app
cd my-app
npm install
npm run dev

npm run dev starts a local server at http://localhost:5173. Changes auto-reload.

Project Structure

After creating a project, you'll see:

my-app/
├── src/
│   ├── routes/              ← Your pages live here
│   │   ├── +page.svelte     ← Home page (/)
│   │   └── +layout.svelte   ← Root layout (wraps all pages)
│   ├── lib/                 ← Your reusable code
│   │   ├── components/      ← Shared components
│   │   └── server/          ← Server-only code (DB, secrets) — PROTECTED
│   ├── app.html             ← HTML shell (you rarely edit this)
│   ├── hooks.server.ts      ← Server hooks (auth, logging)
│   └── hooks.client.ts      ← Client hooks (optional — only for global error handling)
├── static/                  ← Static files (favicon, images)
├── svelte.config.js         ← SvelteKit config
├── vite.config.ts           ← Vite bundler config
├── tsconfig.json            ← TypeScript config
└── package.json

The Two Most Important Folders

src/routes/ — Your Pages

This is where you spend most of your time. Each folder = a URL:

src/routes/
├── +page.svelte              → /           (home page)
├── +layout.svelte            → wraps all pages (nav, footer)
├── +layout.server.ts         → loads data for the layout (server-only, e.g. auth user)
├── about/
│   └── +page.svelte          → /about
├── blog/
│   └── +page.svelte          → /blog
└── contact/
    └── +page.svelte          → /contact

src/lib/ — Your Reusable Code

Components, utilities, types, stores — anything shared across pages. Import using the $lib alias:

<!-- Instead of: import Card from '../../../lib/components/Card.svelte' -->
<script>
import Card from '$lib/components/Card.svelte';
</script>

$lib always points to src/lib/ no matter where you import from.

src/lib/server/ — Protected Server Code

src/lib/server/ is a special folder — SvelteKit prevents it from being imported in client-side code. If you try, the build fails. This is where you put database connections, API keys, and any code that must never reach the browser.

Only server-only files can import from it:

  • +page.server.ts, +layout.server.ts, +server.ts, hooks.server.ts
  • +page.svelte, +page.ts ❌ (build error)

The rule: if it has server in the name, it stays on the server.

Special Files in a Route

Each route folder can have these files (all optional except +page.svelte):

File What it does Runs on
+page.svelte The page UI Browser
+page.ts Loads data for the page Server + Browser
+page.server.ts Loads data (server only) + form actions Server only
+layout.svelte Wraps child pages with shared UI Browser
+layout.ts Loads data for the layout Server + Browser
+layout.server.ts Loads data for layout (server only) Server only
+error.svelte Error page Browser
+server.ts API endpoint (no UI) Server only

Don't memorize this — you'll learn each one in upcoming lessons. For now, just know:

  • .svelte files = UI (what the user sees)
  • .ts files = logic (data loading, form handling, API endpoints)
  • server in the name = runs only on the server (safe for secrets/DB)

Your First Page

Create src/routes/+page.svelte:

<!-- src/routes/+page.svelte -->
<h1>Hello SvelteKit!</h1>
<p>This is the home page.</p>

That's it. Visit http://localhost:5173 and you'll see it. No imports, no configuration.

Adding a Second Page

Create src/routes/about/+page.svelte:

<!-- src/routes/about/+page.svelte -->
<h1>About</h1>
<p>This is the about page.</p>
<a href="/">← Back home</a>

Visit http://localhost:5173/about. Navigation between pages is instant — SvelteKit handles it client-side.

The app.html Shell

src/app.html is the HTML template that wraps everything:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    %sveltekit.head%
  </head>
  <body>
    %sveltekit.body%
  </body>
</html>
  • %sveltekit.head% — SvelteKit injects CSS, meta tags, etc.
  • %sveltekit.body% — SvelteKit injects your rendered page

You rarely need to edit this file.

Key Takeaways

  • src/routes/ = pages. Folder structure = URL structure
  • src/lib/ = shared code. Import with $lib/
  • +page.svelte = what the user sees
  • +page.server.ts = server logic (data, forms)
  • npm run dev = start developing

Next Lesson

Now that you have a project, let's learn how routing works in detail — dynamic routes, parameters, and navigation.