TypeScript Fundamentals
Core types & syntax
- Primitive types: string, number, boolean, null, undefined
- Arrays: string[] and Array<number> syntax
- const vs let — never use var again
- Arrow functions with return type annotations
- Template literals and string interpolation
- Type inference — when TS figures it out automatically
Interfaces & type aliases
- interface — define object shapes (User, Product, etc.)
- type alias — unions, primitives, complex combos
- Optional fields with ?
- readonly fields — immutability
- Extending interfaces: interface Admin extends User
- Union types: type Status = 'active' | 'inactive' | 'pending'
Generics & utility types
- Generic functions: function getFirst<T>(arr: T[]): T
- Generic interfaces: ApiResponse<T>
- Partial<T> — all fields optional
- Readonly<T> — no mutation
- Pick<T, keys> — subset of fields
- Omit<T, keys> — exclude fields
Async TypeScript — fetch & error handling
- Promise<T> return type annotation
- async/await with typed responses
- unknown vs any — always use unknown, never any
- try/catch with err instanceof Error pattern
- Optional chaining: user?.name
- Nullish coalescing: user?.name ?? 'Anonymous'
Tooling — tsconfig & project setup
- Scaffold plain TS project: npm create vite@latest -- --template vanilla-ts
- tsconfig.json key options: strict, target, module
- Enable strict: true — always
- Run tsc --noEmit to type-check without building
🛠 Mini Project 1 — Typed API Client
- Pick any free public API (JSONPlaceholder, OpenMeteo, etc.)
- Model the response shape as TypeScript interfaces
- Write a generic fetchData<T>(url: string): Promise<T> function
- Call it with your interface as the type argument
- Handle errors with try/catch and typed error messages
- Log results to console — no UI needed yet
Week 2 — Svelte Core
Setup & component structure
- Scaffold Svelte project: npm create svelte@latest
- Choose skeleton project + TypeScript + ESLint
- Understand the .svelte file: script, template, style sections
- Scoped CSS — styles only affect the current component
- lang='ts' on script tag — always use this
Reactivity — the core of Svelte
- let variables are reactive — Svelte watches them automatically
- $: reactive declarations — auto-recalculate on dependency change
- $: statements — run side effects reactively
- Reactivity with arrays/objects — must reassign, not mutate
🛠 Mini Project 2 — Live Calculator
- Single .svelte component — no routing yet
- Two number inputs bound with bind:value
- Four operations using $: reactive declarations
- Result updates live without any button click
- Handle division by zero gracefully
Props & component communication
- export let propName — declare incoming props
- Default prop values: export let count: number = 0
- createEventDispatcher — emit custom events to parent
- on:eventName in parent to listen to child events
- event.detail — accessing payload from dispatched event
Control flow — if, each, await blocks
- {#if condition}...{:else if}...{:else}...{/if}
- {#each items as item (item.id)} — always use a key
- {#await promise}{:then data}{:catch err}{/await}
- class:active={condition} — conditional CSS classes
Stores — global state management
- writable() — mutable global state
- derived() — computed state from other stores
- readable() — read-only state (timers, sensors)
- $ prefix in template — auto-subscribe and unsubscribe
- stores.ts pattern — keep stores in a separate file
🛠 Mini Project 3 — Shopping Cart
- ProductCard component — accepts product prop, emits addToCart
- cartStore using writable — holds array of cart items
- derived store for cartTotal — sum of all item prices
- CartSidebar component — reads from store, shows items + total
- Remove item from cart functionality
- Empty cart state with {#if} block
Fetching data & lifecycle
- onMount — runs after component mounts in DOM
- onDestroy — cleanup timers, subscriptions
- fetch inside onMount — load data from your API
- loading / error / data state pattern
- bind:this — reference a DOM element directly
🛠 Mini Project 4 — API Data Table
- Connect to your own backend API (or JSONPlaceholder)
- TypeScript interfaces matching the API response shape
- onMount + fetch with loading spinner and error message
- Render results in a simple HTML table
- Search/filter input — filter rows reactively with $:
Week 3 — SvelteKit Routing & Data Loading
SvelteKit project structure & file conventions
- npm create svelte@latest — choose SvelteKit + TypeScript
- src/routes/ — every folder is a URL segment
- +page.svelte — the page component for a route
- +layout.svelte — wraps all child routes (nav, footer)
- [param] folders — dynamic route segments
- $lib alias — import from src/lib without relative paths
Universal load functions (+page.ts)
- export const load: PageLoad — typed load function signature
- Return data from load — available as data prop in page
- PageData type — auto-generated, use it in +page.svelte
- Use Kit's fetch — not the global one, handles cookies
- params — access dynamic route segments in load
Server-only load functions (+page.server.ts)
- Difference: +page.ts runs everywhere, +page.server.ts server only
- Access cookies in server load
- Access environment variables (private) in server load
- throw error(404, 'Not found') — typed HTTP errors
- redirect(303, '/login') — redirect from load
🛠 Mini Project 5 — Multi-page Blog Viewer
- / — home page listing all posts (fetched in load)
- /posts — all posts with title and summary
- /posts/[id] — single post detail page
- Shared +layout.svelte with nav links
- Custom +error.svelte for 404 and other errors
- Use JSONPlaceholder /posts API or your own backend
Navigation & URL utilities
- goto('/path') — programmatic navigation
- invalidate(url) — re-run specific load functions
- invalidateAll() — re-run all load functions on current page
- $page store — access params, url, data, status
- preloadData — hover-prefetch for instant navigation feel
API routes (+server.ts)
- export const GET: RequestHandler — handle GET requests
- export const POST: RequestHandler — handle POST
- json() helper — return JSON responses
- request.json() — parse incoming JSON body
- When to use Kit API routes vs calling external backend directly
🛠 Mini Project 6 — GitHub Profile Viewer
- / — search page with a username input
- /users/[username] — profile page loaded via +page.ts load
- /users/[username]/repos — list repos, separate route
- Use GitHub public API — no auth needed
- TypeScript interfaces for GithubUser and GithubRepo
- 404 error if username not found — throw error(404)
- +layout.svelte with back navigation
Week 4 — Forms, Actions & Auth
Form actions — SvelteKit's way to handle mutations
- export const actions: Actions in +page.server.ts
- request.formData() — read submitted form fields
- fail(status, data) — return validation errors back to page
- redirect(303, '/path') after successful action
- ActionData type — type the form return value
Progressive enhancement with use:enhance
- import { enhance } from '$app/forms'
- use:enhance on form tag — no full page reload
- Show pending state during submission
- Custom enhance callback — control success/failure behavior
Multiple named actions
- Named actions object: { create: async () => {}, delete: async () => {} }
- action='?/create' attribute on form element
- Hidden inputs to pass IDs: <input type='hidden' name='id' value={id} />
🛠 Mini Project 7 — Full CRUD Notes App
- / — list all notes loaded via +page.server.ts
- Create note — form action ?/create, title + body fields
- /notes/[id]/edit — edit form pre-filled with existing data
- Update note — form action ?/update
- Delete note — ?/delete action with hidden id field
- Zod validation on create and update actions
- Show field errors inline using form?.errors
- use:enhance on all forms — no full reload
Authentication pattern — JWT via cookie
- Login form action — POST credentials to backend, get token
- cookies.set() — store JWT as httpOnly cookie
- Logout action — cookies.delete()
- Cookie options: httpOnly, sameSite, maxAge, path
Hooks & middleware (hooks.server.ts)
- export const handle: Handle — runs on every request
- Read session cookie in handle hook
- Verify token with backend, attach user to event.locals
- app.d.ts — declare App.Locals interface with user type
Protecting routes
- Check locals.user in +page.server.ts load
- redirect(303, '/login') if not authenticated
- +layout.server.ts — protect an entire route group at once
Schema validation with Zod
- npm install zod
- z.object() — define schema matching your form fields
- schema.safeParse() — validate without throwing
- error.flatten().fieldErrors — structured per-field errors
- Return errors to page with fail() and display inline
🛠 Mini Project 8 — Auth-Protected Dashboard
- /login — login form with email + password, form action
- POST credentials to your backend, store token as httpOnly cookie
- hooks.server.ts — verify token, attach user to locals on every request
- /dashboard — protected route, redirects to /login if no session
- Show logged-in user name from locals.user on dashboard
- /logout — action that clears cookie and redirects
- Zod validation on the login form with inline errors
Week 5 — Portfolio Project & Deploy
Project planning & scaffold
- Pick your project — admin panel, dashboard, or CRUD app for your backend
- Draw routes on paper first — map URLs before touching code
- Define TypeScript interfaces for all API response shapes
- npm create svelte@latest — fresh project with TS
- npx svelte-add@latest tailwindcss — add Tailwind
- src/lib/api.ts — centralized typed API client for all fetch calls
Core feature implementation
- List view — table or card grid with load function
- Detail view — dynamic route with +page.ts load
- Create form — form action + Zod validation
- Edit form — pre-filled with existing data from load
- Delete — named action with hidden id, redirect after
- Auth — login/logout + protected routes (if your API needs it)
UX polish
- Loading skeletons or spinners on data fetch
- Empty state messages — 'No items yet, create one'
- Toast or banner notifications for create/update/delete success
- Confirm before delete — simple window.confirm or modal
- Custom +error.svelte — friendly error page
- Responsive layout with Tailwind — usable on mobile
Code quality check
- npx tsc --noEmit — fix all TypeScript errors
- npm run lint — fix all ESLint warnings
- No any types — replace all with proper types
- Environment variables in .env.local — no hardcoded URLs
- .env.local in .gitignore — never commit secrets
Deploy
- Vercel — easiest: npx vercel, zero config for SvelteKit
- Cloudflare Pages — free, fast: npm install @sveltejs/adapter-cloudflare
- Node.js server — npm install @sveltejs/adapter-node, npm run build
- Set VITE_API_URL environment variable in deploy platform
- Configure CORS on your backend to allow the deployed frontend origin
- Test deployed app end-to-end — happy path, error path, empty state
README & wrap-up
- README.md — what the project does, tech stack, setup steps
- Link to live deploy and backend repo
- Screenshot or demo GIF in README
- Push to GitHub — make it public for portfolio