Svelte July 2026 — SvelteKit Config, Env Vars, {const ...}
Technical Deep-Dive · July 6, 2026

Svelte July 2026 Update:
SvelteKit Config, Env Vars, {const ...}

The July 2026 Svelte update brings a real shift in how SvelteKit projects are configured. SvelteKit config moves to vite.config.js — previewing how Kit 3 will work, explicit environment variables, full toolchain support for {const ...} declarations, and improvements to remote functions, prerendering, and the sv CLI.

Oleg Maximov July 6, 2026 12 min read

Introduction

July 2026 is a milestone month for the Svelte ecosystem. The SvelteKit team shipped nine feature releases (2.62.0 through 2.68.0) in a single month, while the Svelte CLI and language tools caught up with Svelte 5's latest syntax. The result is a significantly improved developer experience for anyone building with SvelteKit.

This article covers everything that landed this month: the SvelteKit config consolidation that previews Kit 3, the experimental explicit environment variable system, full toolchain support for {const ...} declaration tags, direct file uploads through remote functions, prerendered Markdown precompression, and the improved sv CLI.

Whether you're evaluating SvelteKit for your next project or already building with it, these changes matter — particularly the config and environment variable improvements, which signal the direction of SvelteKit 3.

SvelteKit Config in vite.config.js — Preview of Kit 3

The biggest structural change this month: you can now define your SvelteKit configuration directly inside vite.config.js, removing the need for a separate svelte.config.js file (SvelteKit 2.62.0).

This is a preview of how SvelteKit 3 will require config to live in vite.config.js. Instead of maintaining two config files, everything goes into your Vite config:

// svelte.config.js — no longer required (but still supported)
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';

export default {
  preprocess: vitePreprocess()
};
// vite.config.js — now the single source of truth
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';

export default defineConfig({
  plugins: [
    sveltekit({
      // SvelteKit config goes here
      preprocess: vitePreprocess(),
      kit: {
        outDir: '.svelte-kit',
        adapter: adapter()
      }
    })
  ]
});

The sv create scaffolding now generates projects with this setup by default ([email protected]), so new projects start with a single config file. The language tools ([email protected] / [email protected]) can also read Svelte config straight from vite.config.js/ts, so your editor integrations continue working without svelte.config.js.

What this means for your projects

Existing projects: svelte.config.js continues to work in SvelteKit 2.x. There's no immediate migration required. New projects: sv create generates a single vite.config.js by default. SvelteKit 3: the separate config file will be fully replaced. If you start adopting the new pattern now, migration will be seamless.

Explicit Environment Variables — Replacing $env/* in Kit 3

SvelteKit 2.63.0 introduces experimental explicit environment variables. Instead of relying on the $env/* virtual modules, you now declare and type your environment variables in one place.

This is a significant architectural change. The $env/* modules have been SvelteKit's environment variable interface since the beginning, but they have limitations: no type safety (you get strings by default), no autocompletion in editors, and the module system can be confusing for new developers.

The new approach uses a defineEnv helper that declares your env vars with their types:

// src/lib/env.js
import { defineEnv } from '@sveltejs/kit/env';

export const env = defineEnv({
  // Public env vars (exposed to the client)
  public: {
    VITE_API_URL: { type: 'string', default: 'https://api.example.com' },
    VITE_APP_NAME: { type: 'string' }
  },
  // Private env vars (server-only)
  private: {
    DATABASE_URL: { type: 'string' },
    STRIPE_SECRET_KEY: { type: 'string' },
    MAX_UPLOAD_SIZE: { type: 'number', default: 5242880 }
  }
});

Once declared, you import from your env.js file instead of using $env/static/public or $env/dynamic/private. TypeScript autocompletion and type checking work natively — your editor knows the shape of every env var, including defaults.

// Instead of: import { PUBLIC_API_URL } from '$env/static/public';
import { env } from '$lib/env';

// Full type-safety — autocompletion works
const apiUrl = env.VITE_API_URL;
const dbUrl = env.DATABASE_URL;

The drizzle and better-auth CLI add-ons already support the new explicit env var system, generating the correct declarations automatically ([email protected]). This is designed to eventually replace $env/* entirely in SvelteKit 3.

Remote Functions: Direct File Upload and Query Refreshing

Direct File Upload Without FormData

SvelteKit 2.64.0 adds native File object support to remote function commands. Previously, uploading a file through a remote function required manually wrapping it in FormData. Now you can pass File objects directly:

// Before — manual FormData wrapping
import { uploadAvatar } from './api';

const formData = new FormData();
formData.append('avatar', fileInput.files[0]);
await uploadAvatar({ data: formData });
// After — direct File object
import { uploadAvatar } from './api';

await uploadAvatar({ file: fileInput.files[0] });

SvelteKit handles serialization automatically, making the code cleaner and removing a common source of bugs. The server-side command receives the File object natively.

Refreshing Other Queries After Mutations

SvelteKit 2.65.0 lets remote queries refresh other queries. This solves a common pain point: after mutating data (e.g., adding a comment), you want to refresh related queries (e.g., the comment list) without manual invalidation logic.

// query.js
export const getPosts = remote.query(async () => {
  return db.select().from(posts);
});

export const getComments = remote.query(async (postId) => {
  return db.select().from(comments).where(eq(comments.postId, postId));
});
// command.js — addComment refreshes both queries automatically
export const addComment = remote.command(async ({ postId, text }) => {
  await db.insert(comments).values({ postId, text });
  // This triggers a refresh of both queries on the client
  return { refreshes: [getPosts, getComments(postId)] };
});

The refreshes property on the return value tells the client which queries to re-fetch after the mutation succeeds. This eliminates the need for manual cache invalidation or event-based refresh coordination.

Also in remote functions this month

SvelteKit 2.66.0 adds warnings when boolean fields in remote form schemas are not marked optional — a common cause of silent submit failures. Version 2.68.0 exports RemoteFormEnhanceInstance and RemoteFormEnhanceCallback types for typed custom enhance callbacks, and submitted submit fields now keep their value in the form action payload, making multi-button forms easier to handle on the server.

Prerendered Markdown Precompression

SvelteKit 2.66.0 extends precompression to prerendered .md and .mdx files. Previously, only HTML, JavaScript, and CSS assets were precompressed (gzip, brotli) during the build. Now Markdown content also gets precompressed, meaning faster delivery of documentation sites, blogs, and any site that prerenders Markdown content.

Combined with adapter-static's precompress option, your Markdown-based content now serves as efficiently as HTML. This is particularly valuable for documentation sites generated from .md/.mdx files using SvelteKit's content rendering pipeline.

Boolean Form Field Warnings and Prerender URL Handling

Boolean Field Warnings

SvelteKit 2.66.0 introduces a warning when boolean fields in remote form schemas are not marked optional. This is a subtle but important quality-of-life improvement:

// Without marking optional — now warns
const schema = {
  agreeToTerms: 'boolean'
};
// When the checkbox is unchecked, no value is submitted,
// and the schema validation fails silently.
// Correct — mark as optional
const schema = {
  agreeToTerms: { type: 'boolean', optional: true }
};

Unchecked checkboxes don't submit a value, which causes unexpected schema failures. The new warning catches this during development instead of leaving you to debug a mystery submit failure in production.

Custom Prerender URL Handling

SvelteKit 2.67.0 adds prerender.handleInvalidUrl, giving you control over how invalid URLs found during crawling are reported. You can now configure the behaviour instead of accepting the default fail-fast approach:

// svelte.config.js (or vite.config.js plugin options)
export default {
  kit: {
    prerender: {
      handleInvalidUrl: 'warn'  // or 'ignore', or a custom function
    }
  }
};

This is useful for sites that link to external resources or have known URL patterns that the prerenderer can't resolve. Instead of the build failing, you can choose to warn or ignore specific patterns while still catching genuine broken links.

{const ...} Declaration Tags — Full Toolchain Support

Svelte 5 introduced {const ...} declarations, which let you destructure and transform data inline inside blocks like {#each}. Until this month, editor tooling didn't fully support them — the language server, svelte-check, and svelte2tsx either ignored or incorrectly handled the syntax.

The July update brings full toolchain support across the board:

Here's what the syntax looks like in practice:

{#each products as product}
  {const {id, name, price, image} = product}
  {const discounted = price * 0.9}
  
{name}

{name}

${price} ${discounted.toFixed(2)}

{/each}

Before this update, you'd either destructure in a <script> block or use reactive $: statements. The {const ...} approach keeps the template self-contained and makes the data flow explicit at the point of use.

sv CLI Improvements

The sv CLI received several meaningful upgrades in version 0.16.0:

Default Vite Plugin Configuration

sv create now scaffolds projects against @sveltejs/kit@^2.62.0 and moves the Svelte config into the Vite plugin by default. New projects start with a single vite.config.js — no svelte.config.js needed.

Experimental Add-On System

A new experimental add-on lets you toggle experimental flags and opt into @next versions directly from the CLI. Instead of manually editing config files to try preview features, you can enable them interactively:

sv add experimental --flag explicit-env-vars
sv add experimental --next

Drizzle and better-auth Support

The drizzle and better-auth add-ons now support SvelteKit's new explicit environment variables. When you add these integrations, the CLI generates the correct defineEnv declarations automatically — no manual wiring required.

sv-utils Helpers

New defineEnv and svelteConfig helpers in @sveltejs/[email protected] make it easier for add-on authors to read and edit a project's Svelte config programmatically. This lowers the barrier for building custom add-ons.

Language Tools Updates

The Svelte language server and related tools had their own improvements beyond {const ...} support:

CSS Completions in Nested Style Tags

CSS completions now work inside nested <style> tags ([email protected]). If your Svelte component contains multiple style blocks (e.g., a component-level style block and a scoped one), the editor now provides correct CSS completions in both.

Config Reading from vite.config.js/ts

The language tools can now read Svelte config straight from vite.config.js/ts ([email protected] / [email protected]). This is the companion change to the config consolidation — editor integrations work whether your config is in svelte.config.js or inside the Vite plugin options.

tsgo Experimental Support

An experimental tsgo option is available for faster type checking. This is early-stage and not yet enabled by default, but it signals the Svelte team's interest in reducing type checking overhead for large projects.

Summary of Version Changes

SvelteKit versions shipped this month

2.62.0 — SvelteKit config in vite.config.js (Kit 3 preview)
2.63.0 — Explicit environment variables (experimental)
2.64.0 — Direct File upload in remote functions
2.65.0 — Query refreshing in remote functions
2.66.0 — .md/.mdx precompression + boolean field warnings
2.67.0prerender.handleInvalidUrl option
2.68.0 — Exported types + submit field payload

sv CLI: 0.16.0
Language server: 0.18.1 / 0.18.2
svelte-check: 4.5.0 / 4.6.0

FAQ

What changed with SvelteKit configuration in July 2026?
Starting from SvelteKit 2.62.0, you can now pass your SvelteKit config directly to the Vite plugin, eliminating the need for a separate svelte.config.js file. This is a preview of how Kit 3 will work — all configuration will live in vite.config.js. The sv CLI now scaffolds new projects with this setup by default. Existing projects can migrate gradually — svelte.config.js still works in SvelteKit 2.x.
How do explicit environment variables work in SvelteKit?
SvelteKit 2.63.0 introduces experimental explicit environment variables using a defineEnv helper. You declare and type your env vars — both public (client-exposed) and private (server-only) — in one place. This replaces the $env/* module imports with a single typed import. TypeScript autocompletion, type checking, and defaults all work natively. The drizzle and better-auth add-ons already support this system.
What are {const ...} declaration tags in Svelte?
{const ...} is Svelte 5's declaration syntax for inline data transformation inside blocks like {#each}. It lets you destructure or compute values without jumping into a script tag. The July update brings full toolchain support: the sv CLI demo template includes them, the language server provides completions and diagnostics, svelte-check validates types, and svelte2tsx correctly converts them. For a comparison of Svelte with other reactive UI frameworks, see my Gea compiler-first framework deep-dive which covers Svelte vs other compile-time approaches. For a broader look at the framework landscape, read my React vs Vue.js vs Angular comparison guide.
Can I upload files without FormData in SvelteKit remote functions?
Yes. SvelteKit 2.64.0 adds direct File object support to remote function commands. You can pass File objects directly to your remote function calls — SvelteKit handles the serialization automatically, eliminating the need to manually wrap them in FormData. This makes file upload code significantly cleaner.
What is the new prerender.handleInvalidUrl option?
Added in SvelteKit 2.67.0, this option lets you customize how invalid URLs found during prerendering crawling are reported. You can configure it to 'warn', 'ignore', 'fail' (the default), or pass a custom function for fine-grained control. It's useful for sites that link to external resources or have URL patterns the prerenderer can't resolve.
Do I need to migrate my existing svelte.config.js to vite.config.js?
Not yet. The vite.config.js approach is a preview — svelte.config.js still works in SvelteKit 2.x. The migration to vite.config.js will become mandatory with SvelteKit 3. For now, you can adopt it optionally. New projects scaffolded with sv create already use the new configuration by default. If you're starting a new project, it's worth adopting the new pattern early for a smoother Kit 3 transition.
Should my next project use SvelteKit?
SvelteKit is an excellent choice for content-driven sites (blogs, documentation, marketing pages), real-time dashboards, and full-stack web applications where developer experience and bundle size matter. Its compile-time approach produces smaller bundles than React or Vue. If you're evaluating frameworks for a new project and want to understand how SvelteKit compares, contact me for a free consultation — I'll recommend the best stack for your specific requirements.

Ready to Build with SvelteKit?

The July 2026 update makes SvelteKit more configurable, more type-safe, and better tooled than ever. Whether you're migrating from another framework or starting fresh, these improvements lower the barriers to building fast, maintainable web applications.

I work with SvelteKit alongside React, Vue.js, and Angular — choosing the right tool for each project. If you're planning a web application and want an experienced perspective, reach out to me. I provide free initial consultations to help you make the right technology choices.

I'm a full-stack developer with 20+ years of experience building web applications. Based in Minsk and working worldwide, let's discuss your project.

Contact

Let's discuss your project

Tell me about your project — I'll recommend the best framework and provide a preliminary estimate. Free of charge.