DEV Community

Frank
Frank

Posted on

How to Move SvelteKit Config Into vite.config.js (July 2026)

I saw the July 2026 Svelte blog post announcing that SvelteKit’s configuration can now live directly inside vite.config.js. As someone who maintains several SvelteKit apps, this caught my eye because it promises a single source of truth for build tooling, reduces boilerplate, and aligns SvelteKit more tightly with the Vite ecosystem we already use daily.

Why this change matters right now

Since the first stable release of SvelteKit, the framework has relied on a separate svelte.config.js file for things like adapters, prerendering options, and preprocessors. While that separation made sense when SvelteKit was still figuring out its relationship with Vite, it also introduced a small friction point:

  • Two config files to keep in sync – you often end up opening both svelte.config.js and vite.config.js when tweaking SSR, environment variables, or custom Vite plugins.
  • Tooling confusion – IDE extensions sometimes treat the two files as unrelated, causing false warnings about unknown properties.
  • Bootstrapping overhead – new contributors have to learn which settings belong where, which adds cognitive load during onboarding.

By allowing the SvelteKit config to be embedded under a sveltekit key in vite.config.js, the Svelte team has effectively merged the two configuration surfaces. This is especially handy for monorepos or when you already have a complex Vite setup (e.g., multiple entry points, custom aliasing, or shared plugins). Now you can see the whole picture in one place, and the Vite dev server will automatically pick up any SvelteKit‑specific tweaks without an extra config file.

What the new API looks like

The blog post shows a minimal example that replaces a typical svelte.config.js with a single vite.config.js. Here’s how I migrated a fresh SvelteKit project:

// vite.config.js
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
import { visualizer } from 'rollup-plugin-visualizer';

// Old separate svelte.config.js (for reference)
// export default {
//   kit: {
//     adapter: adapterNode(),
//     prerender: { default: true }
//   }
// };

export default defineConfig({
  plugins: [
    sveltekit({
      // All SvelteKit options go here
      kit: {
        // The adapter you were using before
        adapter: require('@sveltejs/adapter-node')(),
        // Keep your prerender defaults
        prerender: { default: true },
        // You can still add vite-specific overrides inside
        // the same object if you need them
        vite: {
          // Example: custom environment variable handling
          define: {
            __APP_VERSION__: JSON.stringify('1.0.0')
          }
        }
      }
    }),
    // Any other Vite plugins stay where they belong
    visualizer({ filename: './stats.html' })
  ],
  // General Vite config stays at the top level
  resolve: {
    alias: {
      $components: '/src/lib/components',
      $utils: '/src/lib/utils'
    }
  },
  server: {
    port: 5173,
    strictPort: true
  }
});
Enter fullscreen mode Exit fullscreen mode

A few things to note:

  1. Import the sveltekit plugin from @sveltejs/kit/vite – this is the same plugin that Vite automatically adds when you run npm init svelte@next, but now you call it explicitly.
  2. Wrap all SvelteKit‑specific keys inside the kit object – this mirrors the shape of the old svelte.config.js.
  3. You can still expose Vite‑only settings (like resolve.alias or server.port) at the top level of the config, keeping everything in one file.

If you already have a vite.config.js with custom plugins, you simply add the sveltekit call to the plugins array and move the kit block into its options. No more “duplicate adapter definitions” or “missing prerender flag” errors.

How this affects common workflows

1. Adding a new adapter

Previously you’d edit svelte.config.js:

// svelte.config.js
import adapterStatic from '@sveltejs/adapter-static';
export default {
  kit: {
    adapter: adapterStatic(),
    // …
  }
};
Enter fullscreen mode Exit fullscreen mode

Now you do it inside vite.config.js:

// vite.config.js (excerpt)
sveltekit({
  kit: {
    adapter: require('@sveltejs/adapter-static')(),
    // …
  }
})
Enter fullscreen mode Exit fullscreen mode

The change is syntactic, but it eliminates the need to keep two files in sync when you switch adapters for staging vs. production.

2. Using environment variables in adapters

Because the adapter configuration lives inside the Vite plugin call, you can reference Vite’s process.env (or the newer import.meta.env) directly:

kit: {
  adapter: require('@sveltejs/adapter-node')({
    env: {
      // Pass a runtime variable to the adapter
      NODE_ENV: process.env.NODE_ENV
    }
  })
}
Enter fullscreen mode Exit fullscreen mode

This feels more natural than pulling dotenv into a separate svelte.config.js.

3. Custom preprocessors

If you need a preprocessor like svelte-preprocess, you still import it and pass it to the sveltekit plugin:

import preprocess from 'svelte-preprocess';

sveltekit({
  kit: {
    // …
  },
  preprocess
})
Enter fullscreen mode Exit fullscreen mode

The API remains identical; the only difference is the file location.

Potential downsides

No change is without trade‑offs. Here are the practical concerns I ran into during migration:

  • Learning curve for newcomers – developers who have only read older tutorials may be confused when they can’t find a svelte.config.js. The docs now need to be explicit about the new location.
  • Tooling gaps – some community plugins (e.g., ESLint configs that look for svelte.config.js) still assume the old file exists. In my monorepo I had to add a small shim file that re‑exports the config just to keep those tools happy.
  • Version lock – the new feature is tied to SvelteKit 1.28+ (the version shipped with the July 2026 release). Projects pinned to earlier releases will need to upgrade anyway, which may involve other breaking changes.

Overall, the drawbacks are mostly about updating documentation and a few edge‑case tool integrations, not about runtime behavior.

My personal take

I decided to upgrade my production SvelteKit apps to the July 2026 release after a quick test branch. The migration took less than 15 minutes per repo, and the resulting vite.config.js felt cleaner: everything from adapters to custom Vite plugins lives under one roof. In environments where we already maintain a shared Vite config (e.g., a design‑system library that ships both React and Svelte components), this consolidation reduces the mental overhead for new hires.

If you’re on a brand‑new SvelteKit project, I’d start there—skip the svelte.config.js entirely and keep your config in vite.config.js. For existing projects, weigh the benefit of a single config file against the effort of updating any tooling that expects svelte.config.js. In most cases, the upgrade is worth it, especially because it aligns SvelteKit with the broader Vite ecosystem and paves the

Top comments (0)