Skip to content

vp create svelte generates config where vp check reports $props as no-undef #1967

Description

@crypt0box

Describe the bug

vp create svelte can generate a project that fails vp check immediately.

The failure comes from the migrated Oxlint config preserving core no-undef for .svelte files. Valid Svelte 5 rune syntax such as $props() is reported as undefined:

eslint(no-undef): '$props' is not defined.

This appears to be a migration/config compatibility issue rather than an application code issue.

Current workaround

Manually disable no-undef for .svelte files in the generated vite.config.ts:

{
  files: ["*.svelte", "**/*.svelte"],
  rules: {
    "no-inner-declarations": "off",
    "no-self-assign": "off",
    "no-undef": "off",
  },
  jsPlugins: ["eslint-plugin-svelte"],
}

After this change, the $props() errors are no longer reported.

Proposed fix

When Vite+ migrates the ESLint config generated by sv create --add eslint into the lint block in vite.config.ts, normalize Svelte overrides so core no-undef is disabled for .svelte files.

For example, during the migrated Oxlint config sanitization step, if an override targets *.svelte / **/*.svelte, add:

rules: {
  "no-undef": "off",
}

This does not attempt to add full Svelte template linting support to Oxlint. It only prevents migrated core no-undef from flagging valid Svelte 5 rune globals such as $props() while Oxlint’s Svelte support is still partial.

One related observation: current sv create --add eslint --types ts disables no-undef globally for TypeScript projects, following typescript-eslint guidance. So another possible fix would be to preserve that top-level no-undef: "off" during migration. However, the minimal compatibility fix is to disable no-undef for migrated .svelte overrides.


This may be small enough that you might decide not to add a Vite+ migration-layer workaround and instead address it as part of broader Svelte
support in Oxlint / @oxlint/migrate. That would be understandable.

If you think this compatibility normalization belongs in Vite+, I would be happy to open a PR.

Also, thanks for building Vite+. I really like this tool.

Reproduction

https://github.com/crypt0box/vite-plus-svelte-eslint

Steps to reproduce

  1. Create a Svelte project with Vite+:
vp create svelte

Choose TypeScript and ESLint.

  1. Install dependencies if needed:
vp install
  1. Run checks:
vp check
  1. Observe that vp check fails on generated Svelte files:
error: Lint or type issues found

x eslint(no-undef): '$props' is not defined.
   ,-[src/routes/+layout.svelte:4:21]
 3 |
 4 |     let { children } = $props();
   :                        ^^^^^^
 5 | </script>
   `----

x eslint(no-undef): '$props' is not defined.
   ,-[src/lib/vitest-examples/Welcome.svelte:4:49]
 3 |
 4 |     let { host = 'SvelteKit', guest = 'Vitest' } = $props();
   :                                                    ^^^^^^
 5 | </script>
   `----

The generated vite.config.ts contains a top-level no-undef: "error" and a Svelte override that does not disable no-undef:

lint: {
  rules: {
    "no-undef": "error",
    // ...
  },
  overrides: [
    {
      files: ["*.svelte", "**/*.svelte"],
      rules: {
        "no-inner-declarations": "off",
        "no-self-assign": "off",
      },
      jsPlugins: ["eslint-plugin-svelte"],
    },
  ],
}

System Info

vp v0.2.1

Local vite-plus:
  vite-plus  v0.2.1

Tools:
  vite             v8.0.16
  rolldown         v1.1.1
  vitest           v4.1.9
  oxfmt            v0.55.0
  oxlint           v1.70.0
  oxlint-tsgolint  v0.23.0
  tsdown           v0.22.3

Environment:
  Package manager  pnpm v11.9.0
  Node.js          v24.18.0

Used Package Manager

pnpm

Validations

Metadata

Metadata

Assignees

No one assigned

    Type

    Priority

    None yet

    Effort

    None yet

    Target date

    None yet

    Start date

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions