This episode covers assets and static content: static assets in the static directory, image optimization and responsive images with enhanced-img, sourcing content from Markdown and MDX, plus caching and build-time optimizations. You will deliver fast content with well-managed assets.

An application isn't just about logic — it's also about assets: logos, photos, icons, and documents. How assets are managed affects load time, bandwidth costs, and user experience. Episode 9 covers three categories: static assets, optimized images, and file-based content.
SvelteKit offers two different asset paths: the static directory for files copied as-is, and module imports for files processed by Vite. Understanding this difference is the key to choosing the right path.
By the end of this episode, you can serve responsive images that are optimized automatically, load Markdown content as pages, and set up asset caching correctly.
The static folder is copied entirely into the build output and served from the domain root. It suits files that don't need processing: favicon, robots.txt, manifest, PDFs, and images that are already optimized.
static/
|-- favicon.ico
|-- robots.txt
|-- manifest.webmanifest
|-- images/
| |-- logo.png
| |-- banner.jpgFiles in static are accessed directly from the root URL: static/robots.txt becomes /robots.txt, and static/images/logo.png becomes /images/logo.png. There's no filename hashing, so make sure you use stable names.
Use static for files that rarely change and don't need processing. For images used inside components that you want optimized, import them from a module instead — Vite will handle the transformation and hashing.
The @sveltejs/enhanced-img package integrates responsive images into Vite. It produces multiple sizes and formats at build time, and provides a component to choose the srcset automatically.
import { sveltekit } from "@sveltejs/kit/vite";
import { enhancedImages } from "@sveltejs/enhanced-img";
const config = {
plugins: [enhancedImages(), sveltekit()]
};
export default config;Once the plugin is installed, import images from src/lib and Vite will generate webp and avif variants at multiple sizes. Filename hashing also gives you automatic cache invalidation when an image changes.
<script>
import { enhanced: img } from "$lib/assets/hero.png";
</script>
<img
src={img.src}
srcset={img.srcset}
sizes="(min-width: 768px) 50vw, 100vw"
alt="Hero halaman utama"
loading="lazy"
decoding="async"
/>The srcset and sizes attributes ask the browser to choose the size that best matches the viewport and screen density. Add loading="lazy" for below-the-fold images and decoding="async" so decoding doesn't block page rendering.
Editorial content — articles, documentation, changelogs — should be written as Markdown or MDX, not stored in a database. Files are easy to review, version with Git, and render as pages.
src/content/
|-- sveltekit/
| |-- pengenalan.md
| |-- routing.md
|-- vite/
| |-- dasar.mdTo turn Markdown into pages, use the mdsvex preprocessor, which converts .md files into Svelte components, or use a content library like Velite (install with npm install velite) that produces structured data and TypeScript types. The pattern: collect the file list, parse frontmatter and body, then load the content in a load function and render it with a Markdown component.
A dynamic [slug] route that is prerendered is a natural pair for static content: each Markdown file becomes a page generated at build time, fast and SEO-friendly.
Once assets are built, cache headers determine how long the browser may keep a copy. In SvelteKit, set headers inside the handle hook.
export const handle = async ({ event, resolve }) => {
const res = await resolve(event);
const url = event.url.pathname;
if (url.startsWith("/images/")) {
res.headers.set("cache-control", "public, max-age=31536000, immutable");
} else {
res.headers.set("cache-control", "no-cache");
}
return res;
};Images with hashed names that change when content changes are safe to cache long-term with immutable. HTML pages and dynamic documents are better served with no-cache so they're always revalidated.
SvelteKit minimizes duplication by reusing assets from src/lib across many pages. Markdown files processed at build time reduce runtime work. The pairing of static for rarely changing files and src/lib for processed assets strikes a balance between simplicity and performance.
Key takeaways:
static folder is copied as-is and served from the root URL, suitable for rarely changing files.src/lib so Vite processes and hashes the files.enhanced-img produces size and format variants at build time with automatic srcset.loading="lazy" and decoding="async" for below-the-fold images.cache-control headers in hooks determine cache age; hashed filenames are safe with immutable.In the next episode we move to the server side: API routes & back-end integration. You'll create endpoints with +server.js, consume and expose internal APIs, build authentication middleware for protected endpoints, and integrate databases with ORMs.