<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: naoki haba</title>
    <description>The latest articles on DEV Community by naoki haba (@naokihaba).</description>
    <link>https://dev.to/naokihaba</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4208252%2Fb5435d63-f94c-4364-9d65-e686bf9216f7.png</url>
      <title>DEV Community: naoki haba</title>
      <link>https://dev.to/naokihaba</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/naokihaba"/>
    <language>en</language>
    <item>
      <title>Contributing to Vite+ Inside Stories — Vue Fes Japan 2026 Speaker Notes</title>
      <dc:creator>naoki haba</dc:creator>
      <pubDate>Mon, 26 Oct 2026 09:41:23 +0000</pubDate>
      <link>https://dev.to/naokihaba/contributing-to-vite-inside-stories-vue-fes-japan-2026-speaker-notes-3pm4</link>
      <guid>https://dev.to/naokihaba/contributing-to-vite-inside-stories-vue-fes-japan-2026-speaker-notes-3pm4</guid>
      <description>&lt;p&gt;This is the script of my talk "Contributing to Vite+ Inside Stories" at Vue Fes Japan 2026. I gave the talk in Japanese. This is an English translation, with links to the Issues and PRs that I talk about.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://www.docswell.com/s/naokihaba/K4N7JN-2026-10-15-132213" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbcdn.docswell.com%2Fpage%2F47QY9Q8NEP.jpg%3Fwidth%3D480" height="270" class="m-0" width="480"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://www.docswell.com/s/naokihaba/K4N7JN-2026-10-15-132213" rel="noopener noreferrer" class="c-link"&gt;
            Contributing to Vite+ Inside Stories | ドクセル
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            ドクセルはスライドやPDFをかんたんに共有できるサイトです
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fbcdn.docswell.com%2Fassets%2Fimages%2Ffavicon.ico" width="64" height="64"&gt;
          docswell.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://vuefes.jp/2026/en/speaker/naokihaba" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvuefes.jp%2F2026%2F_og%2Fd%2Fc_OgSpeaker%2Cname_Naoki%2BHaba%2CavatarUrl_~LzIwMjYvaW1hZ2VzL2F2YXRhcnMvbmFva2loYWJhLnBuZw%2CspeakerTitle_~Vml0ZSsgVGVhbSBNZW1iZXI%2Caffiliation_ANDPAD%2BInc.%2Ccolor_default%2Cp_Ii9lbi9zcGVha2VyL25hb2tpaGFiYSI%2Cs_s1cJ6uJ3xTM6gL0z.png" height="420" class="m-0" width="800"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://vuefes.jp/2026/en/speaker/naokihaba" rel="noopener noreferrer" class="c-link"&gt;
            Vue Fes Japan 2026 - Naoki Haba
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Contributing to Vite+, and the View from Becoming a Team Member
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fvuefes.jp%2F2026%2Ffavicon.ico" width="256" height="256"&gt;
          vuefes.jp
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello, everyone!&lt;br&gt;
My slides are in English, but I will speak in Japanese today, because I am still learning English.&lt;br&gt;
I hope you enjoy my talk!&lt;/p&gt;

&lt;p&gt;Today, I want to look back on the contributions that I made to Vite+.&lt;/p&gt;

&lt;p&gt;I will show the Issues and PRs that I worked on, and tell you what I was thinking at that time.&lt;/p&gt;

&lt;p&gt;This is not a difficult technical talk. It is a look back at what I did, so please relax and listen.&lt;/p&gt;

&lt;p&gt;At first, I worked on Vite+ as an individual contributor. After I joined the Core Team, my work changed. I started to investigate Issues and review PRs.&lt;/p&gt;

&lt;p&gt;Today, I will also talk about how my way of thinking about open source software (OSS) changed during that time.&lt;/p&gt;

&lt;p&gt;Let me introduce myself. My name is &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;Naoki Haba&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In my free time, I work on Vite+ every day as a Core Team member.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is Vite+?
&lt;/h2&gt;

&lt;p&gt;Before the main topic, let me introduce Vite+.&lt;/p&gt;

&lt;p&gt;Vite+ is a unified toolchain. It puts many tools for web development into one package.&lt;/p&gt;

&lt;p&gt;In daily development, you start a development server, run tests, and lint and format your code.&lt;/p&gt;

&lt;p&gt;To do this, you usually install many tools, and each tool has its own configuration and commands.&lt;/p&gt;

&lt;p&gt;Vite+ puts these tools together, so you can use all of them from one CLI, &lt;code&gt;vp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You probably know many of the tools inside it.&lt;/p&gt;

&lt;p&gt;It uses Vite for the development server and application builds, Vitest for tests, Oxlint for linting, and Oxfmt for formatting.&lt;/p&gt;

&lt;p&gt;You run them with commands such as &lt;code&gt;vp dev&lt;/code&gt;, &lt;code&gt;vp test&lt;/code&gt;, and &lt;code&gt;vp lint&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vp pack&lt;/code&gt; builds libraries, and it uses &lt;code&gt;tsdown&lt;/code&gt;. I will talk about &lt;code&gt;tsdown&lt;/code&gt; again later, in the migration part.&lt;/p&gt;

&lt;p&gt;Now, let me tell you about my first contribution.&lt;/p&gt;
&lt;h2&gt;
  
  
  My journey as a contributor
&lt;/h2&gt;
&lt;h3&gt;
  
  
  My first contribution: vp create
&lt;/h3&gt;

&lt;p&gt;The first problem that I worked on was in &lt;code&gt;vp create&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;vp create&lt;/code&gt; makes a new project from a template.&lt;/p&gt;

&lt;p&gt;When I used it, I typed the name of a template that did not exist. The command showed the pnpm 404 error as it was.&lt;/p&gt;

&lt;p&gt;With that error, it was hard to see what I did wrong.&lt;/p&gt;

&lt;p&gt;I looked on GitHub, and someone had already reported the same problem as an Issue.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/828" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Incorrect registry causing project creation to fail
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#828&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/azizbecha" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F63454940%3Fv%3D4" alt="azizbecha avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/azizbecha" rel="noopener noreferrer"&gt;azizbecha&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/828" rel="noopener noreferrer"&gt;&lt;time&gt;Mar 13, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Describe the bug&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;When I want to create a new Vite Plus using the &lt;code&gt;vp create &amp;lt;name&amp;gt;&lt;/code&gt;, the CLI fetches from &lt;code&gt;https://registry.npmjs.org/&amp;lt;name&amp;gt;&lt;/code&gt; which returns error 404.&lt;/p&gt;
&lt;p&gt;&lt;code&gt; ERR_PNPM_FETCH_404  GET https://registry.npmjs.org/create-vite-plus-app: Not Found - 404&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/user-attachments/assets/0dd5d45e-092f-4e0b-8d46-1504fb221101"&gt;&lt;img width="1468" height="916" alt="Image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F0dd5d45e-092f-4e0b-8d46-1504fb221101"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Reproduction&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;none&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Steps to reproduce&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Run &lt;code&gt;vp create &amp;lt;name&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;System Info&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;Environment:
  Version  24.14.0
  Source   lts

Tool Paths:
  node  /Users/azizbecha/.vite-plus/js_runtime/node/24.14.0/bin/node
  npm   /Users/azizbecha/.vite-plus/js_runtime/node/24.14.0/bin/npm
  npx   /Users/azizbecha/.vite-plus/js_runtime/node/24.14.0/bin/npx

vp v0.1.11

Local vite-plus:
  vite-plus  Not found

Tools:
  vite             Not found
  rolldown         Not found
  vitest           Not found
  oxfmt            Not found
  oxlint           Not found
  oxlint-tsgolint  Not found
  tsdown           Not found&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Used Package Manager&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;pnpm&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Logs&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Validations&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] Read the &lt;a href="https://github.com/voidzero-dev/vite-plus/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;Contributing Guidelines&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[x] Check that there isn't &lt;a href="https://github.com/voidzero-dev/vite-plus/issues" rel="noopener noreferrer"&gt;already an issue&lt;/a&gt; for the same bug.&lt;/li&gt;
&lt;li&gt;[x] Confirm this is a Vite+ issue and not an upstream issue (Vite, Vitest, tsdown, Rolldown, or Oxc).&lt;/li&gt;
&lt;li&gt;[x] The provided reproduction is a &lt;a href="https://stackoverflow.com/help/minimal-reproducible-example" rel="nofollow noopener noreferrer"&gt;minimal reproducible example&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/issues/828" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;So I read the code and followed the steps that it ran.&lt;/p&gt;

&lt;p&gt;I found that the command ran the package manager without first checking if the package existed on npm.&lt;/p&gt;

&lt;p&gt;Because of this, when it did not find the template, it showed the pnpm error.&lt;/p&gt;

&lt;p&gt;This is the PR that fixed it.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1055" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        fix: add troubleshooting tips for npm template not found error
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1055&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1055" rel="noopener noreferrer"&gt;&lt;time&gt;Mar 19, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Linked issue&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;resolves #828&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Description&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;The behavior when specifying an invalid template name (e.g., vite-plus-app) with the vp create command has been improved.&lt;/p&gt;
&lt;p&gt;With this update, the CLI now checks the npm registry before executing the package manager. If the template is not found (HTTP 404 error), it will display an error message and terminate the process immediately.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/pull/1055" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Before it runs the package manager, the command now asks the npm registry if the package exists.&lt;/p&gt;

&lt;p&gt;If the registry returns 404, the command shows that it did not find the template, and then it stops.&lt;/p&gt;

&lt;p&gt;The message also tells you that &lt;code&gt;vp create --list&lt;/code&gt; shows the available templates.&lt;/p&gt;

&lt;p&gt;This was my first PR to Vite+.&lt;/p&gt;

&lt;p&gt;It was a small change. But I read the real code and fixed a problem that I had when I used the tool.&lt;/p&gt;

&lt;p&gt;After that, I started to look at other Issues, a little at a time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrating Node.js version settings
&lt;/h3&gt;

&lt;p&gt;At about the same time, I wanted to use Vite+ at work.&lt;/p&gt;

&lt;p&gt;But existing projects already have a Node.js version setting and configuration for many tools.&lt;/p&gt;

&lt;p&gt;I wanted to know how to move those settings to Vite+.&lt;/p&gt;

&lt;p&gt;So I looked at &lt;code&gt;vp migrate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This command migrates an existing project to Vite+.&lt;/p&gt;

&lt;p&gt;Rewriting configuration files sounds easy. But if the migration changes the Node.js version that the project uses, that is a problem.&lt;/p&gt;

&lt;p&gt;So I had to think about two things: how to read the old settings, and how to make the project work the same way after the migration.&lt;/p&gt;

&lt;p&gt;My first task here was to migrate the Node.js version setting.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/1158" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        `vp migrate` handles migration from `.nvmrc`
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1158&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/TheAlexLichter" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F640208%3Fv%3D4" alt="TheAlexLichter avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/TheAlexLichter" rel="noopener noreferrer"&gt;TheAlexLichter&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/1158" rel="noopener noreferrer"&gt;&lt;time&gt;Mar 26, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Description&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;As a dev using Vite+, I want my old nvm files being migrated over to the Vite+ way.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Suggested solution&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Ask them if they want to migrate them over when being used.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Alternative&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Also adhere to .nvmrc (meh)&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Additional context&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Same for other node version managers!&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Validations&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] Read the &lt;a href="https://github.com/voidzero-dev/vite-plus/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;Contributing Guidelines&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[x] Confirm this request is for Vite+ itself and not for Vite, Vitest, tsdown, Rolldown, or Oxc.&lt;/li&gt;
&lt;li&gt;[x] Check that there isn't already an issue requesting the same feature.&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/issues/1158" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Two files can set the Node.js version for a project: &lt;code&gt;.nvmrc&lt;/code&gt; and &lt;code&gt;.node-version&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Vite+ uses &lt;code&gt;.node-version&lt;/code&gt;, but projects that use nvm often have a &lt;code&gt;.nvmrc&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;So I changed &lt;code&gt;vp migrate&lt;/code&gt;. When it finds &lt;code&gt;.nvmrc&lt;/code&gt;, it migrates the file to &lt;code&gt;.node-version&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1159" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat(migrate): migrate .nvmrc to .node-version during `vp migrate`
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1159&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1159" rel="noopener noreferrer"&gt;&lt;time&gt;Mar 26, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;🔗 Related Issues&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;

&lt;p&gt;Resolves: #1158&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;📚 Description&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Vite+ previously retrieved the Node.js version from .node-version, but projects using nvm typically use .nvmrc.&lt;/p&gt;
&lt;p&gt;With this change, automatic detection of .nvmrc and a migration feature to .node-version have been added as part of the vp migrate command execution process.&lt;/p&gt;
&lt;p&gt;During migration, if a v prefix is present at the beginning, it is removed, while aliases such as lts/* are carried over as is.&lt;/p&gt;
&lt;p&gt;Unit tests have confirmed that it works correctly regardless of the presence of the v prefix.&lt;/p&gt;
&lt;p&gt;On the other hand, if unsupported aliases like node or stable are included, the system is designed to display a warning and skip the migration rather than failing.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Manual Test: .nvmrc Migration&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;$ mkdir /tmp/vp-migrate-test
$ &lt;span class="pl-c1"&gt;echo&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;{ "name": "test-migrate", "version": "1.0.0" }&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt; package.json
$ &lt;span class="pl-c1"&gt;echo&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;v20.5.0&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;&amp;gt;&lt;/span&gt; .nvmrc&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;Command&lt;/h4&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;$ &lt;span class="pl-c1"&gt;cd&lt;/span&gt; /tmp/vp-migrate-test &lt;span class="pl-k"&gt;&amp;amp;&amp;amp;&lt;/span&gt; vp migrate --no-interactive&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;Output (Excerpt)&lt;/h4&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;.nvmrc detected. Auto-migrating to .node-version...
...
• Node version manager file migrated to .node-version
&lt;/code&gt;&lt;/pre&gt;
&lt;div class="markdown-heading"&gt;
&lt;h4 class="heading-element"&gt;Final State&lt;/h4&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;pre&gt;&lt;code&gt;$ cat /tmp/vp-migrate-test/.node-version
20.5.0
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;.nvmrc (v20.5.0) -&amp;gt; Deleted&lt;/li&gt;
&lt;li&gt;.node-version -&amp;gt; 20.5.0 (With the v prefix removed)&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/pull/1159" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;For example, if the file contains a version number such as &lt;code&gt;20.11.0&lt;/code&gt;, the command copies that value.&lt;/p&gt;

&lt;p&gt;If the value starts with &lt;code&gt;v&lt;/code&gt;, the command removes the &lt;code&gt;v&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Up to here, the command only cleans up the value and copies it. But &lt;code&gt;.nvmrc&lt;/code&gt; can contain values that are not version numbers.&lt;/p&gt;

&lt;p&gt;I was not sure how to handle those values.&lt;/p&gt;

&lt;p&gt;For example, &lt;code&gt;.nvmrc&lt;/code&gt; can contain &lt;code&gt;node&lt;/code&gt; instead of a version number.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;node&lt;/code&gt; means "use the latest release of Node.js".&lt;/p&gt;

&lt;p&gt;&lt;code&gt;lts/*&lt;/code&gt; means "use the latest LTS release".&lt;/p&gt;

&lt;p&gt;These two look similar, but they do not always give the same version.&lt;/p&gt;

&lt;p&gt;So, at first, when the file contained &lt;code&gt;node&lt;/code&gt;, the command showed a warning and stopped the migration.&lt;/p&gt;

&lt;p&gt;If the command changed &lt;code&gt;node&lt;/code&gt; to LTS without asking, the project could get an older Node.js version. I did not think that was correct.&lt;/p&gt;

&lt;p&gt;But when I opened the PR, a reviewer &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1159#discussion_r2998615181" rel="noopener noreferrer"&gt;suggested&lt;/a&gt; that converting it to LTS might be fine.&lt;/p&gt;

&lt;p&gt;At about that time, I had also read an announcement. From Node.js 27, every major version moves to LTS after its release.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://nodejs.org/en/blog/announcements/evolving-the-nodejs-release-schedule" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;nodejs.org&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Because of this, I changed the command to convert &lt;code&gt;node&lt;/code&gt; to &lt;code&gt;lts/*&lt;/code&gt; and continue the migration.&lt;/p&gt;

&lt;p&gt;But the new value does not mean the same thing as the old one, so the command writes a log message about the conversion.&lt;/p&gt;

&lt;p&gt;At first, I thought this task was only about copying the contents of a configuration file.&lt;/p&gt;

&lt;p&gt;But when I did it, I found cases where the command could not copy the old setting as it was.&lt;/p&gt;

&lt;p&gt;I gave priority to keeping the meaning of the old setting. The reviewer gave priority to letting the migration continue.&lt;/p&gt;

&lt;p&gt;Neither view was wrong. We had to decide which behavior was best for Vite+.&lt;/p&gt;

&lt;p&gt;Talking about the direction with other members, before and after writing code, is one thing that makes OSS contribution interesting for me.&lt;/p&gt;

&lt;p&gt;Up to here, I worked with Node.js, which I knew well. Next, I worked in a different area.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Nushell support
&lt;/h3&gt;

&lt;p&gt;That was support for Nushell.&lt;/p&gt;

&lt;p&gt;Nushell is a shell, like Bash or Zsh. You run commands in a terminal with it.&lt;/p&gt;

&lt;p&gt;Vite+ has a feature, &lt;code&gt;vp env&lt;/code&gt;, that switches the Node.js version. The Issue asked to make this feature work in Nushell.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/1144" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        nushell env wrapper
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1144&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/joknoll" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F107255664%3Fv%3D4" alt="joknoll avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/joknoll" rel="noopener noreferrer"&gt;joknoll&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/1144" rel="noopener noreferrer"&gt;&lt;time&gt;Mar 25, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Description&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;As a developer using Vite+ I want to be able to source vp into nushell so that I can still use my main shell.&lt;/p&gt;
&lt;p&gt;This includes wrapping the env use command and completions for vp.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Suggested solution&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;I've already implemented a env.nu that can be sourced in nushell like so 'source ~/.vite-plus/env.nu'&lt;/p&gt;
&lt;div class="highlight highlight-source-nushell js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;# Custom completer for the vp wrapper using fish completions&lt;/span&gt;
&lt;span class="pl-en"&gt;def&lt;/span&gt; &lt;span class="pl-en"&gt;"nu-complete vp"&lt;/span&gt; [&lt;span class="pl-v"&gt;context&lt;/span&gt;: &lt;span class="pl-en"&gt;string&lt;/span&gt;] {
    &lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;fish_comp_path&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; (&lt;span class="pl-c1"&gt;$env&lt;/span&gt;&lt;span class="pl-smi"&gt;.HOME&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;path join&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;.vite-plus/completion/vp.fish&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;)
    &lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;fish_cmd&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;$"&lt;/span&gt;source '(&lt;span class="pl-smi"&gt;$fish_comp_path&lt;/span&gt;)'; complete '--do-complete=(&lt;span class="pl-smi"&gt;$context&lt;/span&gt;)'&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
    &lt;span class="pl-en"&gt;fish&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;--&lt;/span&gt;command&lt;/span&gt; &lt;span class="pl-smi"&gt;$fish_cmd&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;from tsv&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;--&lt;/span&gt;flexible&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;--&lt;/span&gt;noheaders&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;--&lt;/span&gt;no-infer&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;rename&lt;/span&gt; &lt;span class="pl-s"&gt;value&lt;/span&gt; &lt;span class="pl-s"&gt;description&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;update&lt;/span&gt; &lt;span class="pl-s"&gt;value&lt;/span&gt; {|&lt;span class="pl-v"&gt;row&lt;/span&gt;|
        &lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;value&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; &lt;span class="pl-smi"&gt;$row.value&lt;/span&gt;
        &lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;need_quote&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;\&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;,&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;[&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;]&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;(&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;)&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt; &lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;\t&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;'&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;"&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;`&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;] &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;any&lt;/span&gt; {&lt;span class="pl-smi"&gt;$in&lt;/span&gt; &lt;span class="pl-k"&gt;in&lt;/span&gt; &lt;span class="pl-smi"&gt;$value&lt;/span&gt;}
        &lt;span class="pl-k"&gt;if&lt;/span&gt; (&lt;span class="pl-smi"&gt;$need_quote&lt;/span&gt; &lt;span class="pl-k"&gt;and&lt;/span&gt; (&lt;span class="pl-smi"&gt;$value&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;path exists&lt;/span&gt;)) {
            &lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;expanded_path&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; &lt;span class="pl-k"&gt;if&lt;/span&gt; (&lt;span class="pl-smi"&gt;$value&lt;/span&gt; &lt;span class="pl-k"&gt;starts-with&lt;/span&gt; &lt;span class="pl-s"&gt;~&lt;/span&gt;) {&lt;span class="pl-smi"&gt;$value&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;path expand&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;--&lt;/span&gt;no-symlink&lt;/span&gt;} &lt;span class="pl-k"&gt;else&lt;/span&gt; {&lt;span class="pl-smi"&gt;$value&lt;/span&gt;}
            &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;$'&lt;/span&gt;"(&lt;span class="pl-smi"&gt;$expanded_path&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;str replace&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;--&lt;/span&gt;all&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;span class="pl-cce"&gt;\"&lt;/span&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;span class="pl-cce"&gt;\\\"&lt;/span&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;)"&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;
        } &lt;span class="pl-k"&gt;else&lt;/span&gt; {&lt;span class="pl-smi"&gt;$value&lt;/span&gt;}
    }
}
&lt;span class="pl-en"&gt;export def&lt;/span&gt; &lt;span class="pl-en"&gt;--env --wrapped&lt;/span&gt; &lt;span class="pl-en"&gt;vp&lt;/span&gt; [&lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;...&lt;/span&gt;args&lt;/span&gt;: &lt;span class="pl-en"&gt;string&lt;/span&gt;@&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;nu-complete vp&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;] { &lt;span class="pl-k"&gt;match&lt;/span&gt; &lt;span class="pl-smi"&gt;$args&lt;/span&gt; {
    [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;env&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;use&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;, &lt;span class="pl-k"&gt;..&lt;/span&gt;] &lt;span class="pl-s"&gt;=&amp;gt;&lt;/span&gt; {
        &lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;out&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; (&lt;span class="pl-k"&gt;with-env&lt;/span&gt; { &lt;span class="pl-smi"&gt;VITE_PLUS_ENV_USE_EVAL_ENABLE&lt;/span&gt;&lt;span class="pl-k"&gt;:&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;1&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; } {
                &lt;span class="pl-k"&gt;^&lt;/span&gt;&lt;span class="pl-en"&gt;vp&lt;/span&gt; &lt;span class="pl-k"&gt;...&lt;/span&gt;&lt;span class="pl-smi"&gt;$args&lt;/span&gt;
            })
        &lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;out_lines&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; (&lt;span class="pl-smi"&gt;$out&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;lines&lt;/span&gt;)
        &lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;exports&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; (
            &lt;span class="pl-smi"&gt;$out_lines&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;find&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;-&lt;/span&gt;r&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;^export &lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;parse&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;-&lt;/span&gt;r&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;^export (?P&amp;lt;key&amp;gt;\w+)=["&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;]?(?P&amp;lt;value&amp;gt;[^"&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;]+)["&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;]?&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;reduce&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;-&lt;/span&gt;f&lt;/span&gt; {} {|&lt;span class="pl-v"&gt;it&lt;/span&gt;, &lt;span class="pl-v"&gt;acc&lt;/span&gt;| &lt;span class="pl-smi"&gt;$acc&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;insert&lt;/span&gt; &lt;span class="pl-smi"&gt;$it.key&lt;/span&gt; &lt;span class="pl-smi"&gt;$it.value&lt;/span&gt;}
        )
        &lt;span class="pl-k"&gt;if&lt;/span&gt; &lt;span class="pl-k"&gt;not&lt;/span&gt; (&lt;span class="pl-smi"&gt;$exports&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;is-empty&lt;/span&gt;) {
            &lt;span class="pl-k"&gt;load-env&lt;/span&gt; &lt;span class="pl-smi"&gt;$exports&lt;/span&gt;
        }
        &lt;span class="pl-k"&gt;let&lt;/span&gt; &lt;span class="pl-smi"&gt;unsets&lt;/span&gt; &lt;span class="pl-k"&gt;=&lt;/span&gt; (
            &lt;span class="pl-smi"&gt;$out_lines&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;find&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;-&lt;/span&gt;r&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;^unset &lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;parse&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;-&lt;/span&gt;r&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;^unset (?P&amp;lt;key&amp;gt;\w+)&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt; &lt;span class="pl-k"&gt;|&lt;/span&gt; &lt;span class="pl-k"&gt;get&lt;/span&gt; &lt;span class="pl-s"&gt;key&lt;/span&gt;
        )
        &lt;span class="pl-k"&gt;for&lt;/span&gt; &lt;span class="pl-smi"&gt;key&lt;/span&gt; &lt;span class="pl-k"&gt;in&lt;/span&gt; &lt;span class="pl-smi"&gt;$unsets&lt;/span&gt; { &lt;span class="pl-k"&gt;hide-env&lt;/span&gt; &lt;span class="pl-smi"&gt;$key&lt;/span&gt; }
    }
    &lt;span class="pl-en"&gt;_&lt;/span&gt; &lt;span class="pl-s"&gt;=&amp;gt;&lt;/span&gt; { &lt;span class="pl-k"&gt;^&lt;/span&gt;&lt;span class="pl-en"&gt;vp&lt;/span&gt; &lt;span class="pl-k"&gt;...&lt;/span&gt;&lt;span class="pl-smi"&gt;$args&lt;/span&gt; }
} }&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Alternative&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;No response&lt;/em&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Additional context&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;No response&lt;/em&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Validations&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] Read the &lt;a href="https://github.com/voidzero-dev/vite-plus/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;Contributing Guidelines&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[x] Confirm this request is for Vite+ itself and not for Vite, Vitest, tsdown, Rolldown, or Oxc.&lt;/li&gt;
&lt;li&gt;[x] Check that there isn't already an issue requesting the same feature.&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/issues/1144" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;This part of Vite+ uses Rust. I had never used Rust in a real product before.&lt;/p&gt;

&lt;p&gt;So I started by reading the existing code for Bash and Fish, to learn what it did.&lt;/p&gt;

&lt;p&gt;I looked up the types and syntax that I did not know, and checked step by step how to do the same thing in Nushell.&lt;/p&gt;

&lt;p&gt;But reading the Rust code was not enough. I also had to learn about the Nushell script that the code generates.&lt;/p&gt;

&lt;p&gt;For example, look at this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Does not work
source "$HOME/.vite-plus/env.nu"

# Works
source ~/.vite-plus/env.nu
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In the first example, the path that goes to &lt;code&gt;source&lt;/code&gt; starts with &lt;code&gt;$HOME&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In Bash and similar shells, you often write the home directory like this.&lt;/p&gt;

&lt;p&gt;But in Nushell, &lt;code&gt;$HOME&lt;/code&gt; inside double quotes does not expand. Also, Nushell writes environment variables as &lt;code&gt;$env.HOME&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So I thought that I only had to change that. But it still did not work.&lt;/p&gt;

&lt;p&gt;The reason is that Nushell's &lt;code&gt;source&lt;/code&gt; decides which file to load when it parses the script, before any command runs.&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://www.nushell.sh/book/how_nushell_code_gets_run.html" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;nushell.sh&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;So you cannot use a runtime environment variable in that path.&lt;/p&gt;

&lt;p&gt;I read the Nushell documentation again, and changed the path to start with a tilde, as in the second example.&lt;/p&gt;

&lt;p&gt;With a tilde, Nushell can find the home directory when it parses the script.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1312" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
          feat(env): add Nushell support via env.nu wrapper
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1312&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1312" rel="noopener noreferrer"&gt;&lt;time&gt;Apr 05, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;resolves #1144&lt;/p&gt;
&lt;p&gt;While comprehensive support for Nushell seems to be under development in #1305, that pull request has a large impact. Therefore, I have limited the scope of this change to env support to align with the existing issue.&lt;/p&gt;
&lt;div class="highlight highlight-source-nushell js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;# nushell&lt;/span&gt;

&lt;span class="pl-c"&gt;# 1. Setup&lt;/span&gt;
&lt;span class="pl-en"&gt;vp&lt;/span&gt; &lt;span class="pl-s"&gt;env&lt;/span&gt; &lt;span class="pl-s"&gt;setup&lt;/span&gt;
&lt;span class="pl-k"&gt;source&lt;/span&gt; &lt;span class="pl-s"&gt;~/.vite-plus/env.nu&lt;/span&gt;  &lt;span class="pl-c"&gt;# or restart Nushell&lt;/span&gt;

&lt;span class="pl-c"&gt;# 2. Set a specific version&lt;/span&gt;
&lt;span class="pl-en"&gt;vp&lt;/span&gt; &lt;span class="pl-s"&gt;env&lt;/span&gt; &lt;span class="pl-s"&gt;use&lt;/span&gt; &lt;span class="pl-c1"&gt;20&lt;/span&gt;
&lt;span class="pl-c"&gt;# Using Node.js v20.20.2 (resolved from 20)&lt;/span&gt;
&lt;span class="pl-c1"&gt;$env&lt;/span&gt;&lt;span class="pl-smi"&gt;.VP_NODE_VERSION&lt;/span&gt;
&lt;span class="pl-c"&gt;# 20.20.2&lt;/span&gt;

&lt;span class="pl-c"&gt;# 3. Resolve from .node-version&lt;/span&gt;
&lt;span class="pl-en"&gt;vp&lt;/span&gt; &lt;span class="pl-s"&gt;env&lt;/span&gt; &lt;span class="pl-s"&gt;use&lt;/span&gt;
&lt;span class="pl-c"&gt;# Using Node.js v22.18.0 (resolved from .node-version)&lt;/span&gt;
&lt;span class="pl-c1"&gt;$env&lt;/span&gt;&lt;span class="pl-smi"&gt;.VP_NODE_VERSION&lt;/span&gt;
&lt;span class="pl-c"&gt;# 22.18.0&lt;/span&gt;

&lt;span class="pl-c"&gt;# 4. Completion (requires Fish)&lt;/span&gt;
&lt;span class="pl-en"&gt;vp&lt;/span&gt; &lt;span class="pl-s"&gt;&amp;lt;Tab&amp;gt;&lt;/span&gt;
&lt;span class="pl-c"&gt;# add        Add packages to dependencies&lt;/span&gt;
&lt;span class="pl-c"&gt;# build      Build application&lt;/span&gt;
&lt;span class="pl-c"&gt;# cache      Manage the task cache&lt;/span&gt;
&lt;span class="pl-c"&gt;# check      Run format, lint, and type checks&lt;/span&gt;
&lt;span class="pl-c"&gt;# ... (all subcommands shown)&lt;/span&gt;

&lt;span class="pl-c"&gt;# 5. False detection regression (bash launched from Nushell)&lt;/span&gt;
&lt;span class="pl-c"&gt;# NU_VERSION is inherited by child processes, but VP_SHELL_NU is not set,&lt;/span&gt;
&lt;span class="pl-c"&gt;# so vp correctly uses POSIX eval mode inside bash.&lt;/span&gt;
&lt;span class="pl-en"&gt;bash&lt;/span&gt; &lt;span class="pl-v"&gt;&lt;span class="pl-k"&gt;-&lt;/span&gt;c&lt;/span&gt; &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;vp env use 20 &amp;amp;&amp;amp; echo $VP_NODE_VERSION&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/pull/1312" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The Rust code only makes a string. But I had to think about how Nushell reads that string.&lt;/p&gt;

&lt;p&gt;So I ran the script in Nushell to check each change.&lt;/p&gt;

&lt;p&gt;Before this, I had never written Rust code for a real product.&lt;/p&gt;

&lt;p&gt;I work as a frontend engineer, so I do not use Rust at work.&lt;/p&gt;

&lt;p&gt;I had solved some LeetCode problems in Rust, and that was all.&lt;/p&gt;

&lt;p&gt;When you study alone, you usually stay with what you already know. In OSS, you cannot do that.&lt;/p&gt;

&lt;p&gt;If you want to fix a problem, you must learn the language or the specification, even if you do not know it.&lt;/p&gt;

&lt;p&gt;In this case, I had to learn about Nushell as well as Rust.&lt;/p&gt;

&lt;p&gt;I did not understand everything at the start. I looked things up, tried them, got help in reviews, and learned a little at a time.&lt;/p&gt;

&lt;p&gt;It was good study for me, and it also helped a tool that I use. I think that is a very good deal.&lt;/p&gt;

&lt;h2&gt;
  
  
  Joining the Core Team
&lt;/h2&gt;

&lt;p&gt;I continued like this. I investigated Issues that interested me, and I opened PRs.&lt;/p&gt;

&lt;p&gt;About one month after my first PR, the Vite+ Core Team invited me to join.&lt;/p&gt;

&lt;p&gt;I was very surprised.&lt;/p&gt;

&lt;p&gt;It was my first time on the core team of an OSS project. The members were engineers that I had looked up to for a long time.&lt;/p&gt;

&lt;p&gt;I never thought that I would work on the same team as them.&lt;/p&gt;

&lt;p&gt;After I joined the team, I started to look at Issues and PRs from other people, in addition to my own PRs.&lt;/p&gt;

&lt;p&gt;For example, when someone reports an Issue, I first try to reproduce it on my machine.&lt;/p&gt;

&lt;p&gt;If I can reproduce it, I look for the cause. If the report does not have enough information, I ask the reporter.&lt;/p&gt;

&lt;p&gt;I also review more PRs from other people.&lt;/p&gt;

&lt;p&gt;But the code alone does not always tell you why a change is necessary.&lt;/p&gt;

&lt;p&gt;So I read the related Issues and past discussions. When necessary, I also read the code of projects other than Vite+.&lt;/p&gt;

&lt;p&gt;Now I will show some of the work that I did as part of this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Migrating from tsdown to Vite+
&lt;/h3&gt;

&lt;p&gt;The first one is a problem in the migration from &lt;code&gt;tsdown&lt;/code&gt; to Vite+.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;tsdown&lt;/code&gt; is a tool that builds TypeScript libraries.&lt;/p&gt;

&lt;p&gt;Vite+ could already migrate projects from &lt;code&gt;tsdown&lt;/code&gt;. But after the migration, some projects got TypeScript errors.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/1500" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        no `tsdown/client` equivalent
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1500&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/EskiMojo14" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F18308300%3Fv%3D4" alt="EskiMojo14 avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/EskiMojo14" rel="noopener noreferrer"&gt;EskiMojo14&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/1500" rel="noopener noreferrer"&gt;&lt;time&gt;Apr 29, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Describe the bug&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Similar to &lt;code&gt;vite/client&lt;/code&gt;, &lt;code&gt;tsdown&lt;/code&gt; includes a &lt;a href="https://github.com/rolldown/tsdown/blob/main/client.d.ts" rel="noopener noreferrer"&gt;&lt;code&gt;tsdown/client&lt;/code&gt;&lt;/a&gt; file to register its bundler features with Typescript.&lt;/p&gt;
&lt;p&gt;It would be useful if this was re-exported by Vite+, perhaps in &lt;code&gt;vite-plus/pack/client&lt;/code&gt; (I see that &lt;code&gt;vite/client&lt;/code&gt; is re-exported as &lt;code&gt;vite-plus/client&lt;/code&gt;).&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Reproduction&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/open-circle/schema-benchmarks/pull/124" rel="noopener noreferrer"&gt;https://github.com/open-circle/schema-benchmarks/pull/124&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Steps to reproduce&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;replace &lt;code&gt;tsdown/client&lt;/code&gt; in &lt;code&gt;schemas/tsconfig.json&lt;/code&gt; with &lt;code&gt;vite-plus/pack/client&lt;/code&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;System Info&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;admin@MacBookPro schema-benchmarks % vp env current
VITE+ - The Unified Toolchain &lt;span class="pl-k"&gt;for&lt;/span&gt; the Web

Environment:
  Version       24.15.0
  Source        .node-version
  Source Path   /Users/admin/schema-benchmarks/.node-version
  Project Root  /Users/admin/schema-benchmarks

Tool Paths:
  node  /Users/admin/.vite-plus/js_runtime/node/24.15.0/bin/node
  npm   /Users/admin/.vite-plus/js_runtime/node/24.15.0/bin/npm
  npx   /Users/admin/.vite-plus/js_runtime/node/24.15.0/bin/npx
admin@MacBookPro schema-benchmarks % vp --version
VITE+ - The Unified Toolchain &lt;span class="pl-k"&gt;for&lt;/span&gt; the Web

vp v0.1.20

Local vite-plus:
  vite-plus  v0.1.20

Tools:
  vite             v8.0.10
  rolldown         v1.0.0-rc.17
  vitest           v4.1.5
  oxfmt            v0.46.0
  oxlint           v1.61.0
  oxlint-tsgolint  v0.22.0
  tsdown           v0.21.10

Environment:
  Package manager  pnpm v10.33.2
  Node.js          v24.15.0 (.node-version)&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Used Package Manager&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;pnpm&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Logs&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Validations&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] Read the &lt;a href="https://github.com/voidzero-dev/vite-plus/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;Contributing Guidelines&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[x] Check that there isn't &lt;a href="https://github.com/voidzero-dev/vite-plus/issues" rel="noopener noreferrer"&gt;already an issue&lt;/a&gt; for the same bug.&lt;/li&gt;
&lt;li&gt;[x] Confirm this is a Vite+ issue and not an upstream issue (Vite, Vitest, tsdown, Rolldown, or Oxc).&lt;/li&gt;
&lt;li&gt;[x] The provided reproduction is a &lt;a href="https://stackoverflow.com/help/minimal-reproducible-example" rel="nofollow noopener noreferrer"&gt;minimal reproducible example&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/issues/1500" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I investigated and found that references to the &lt;code&gt;tsdown/client&lt;/code&gt; type definitions stayed in the project after the migration.&lt;/p&gt;

&lt;p&gt;So I added a matching export, &lt;code&gt;vite-plus/pack/client&lt;/code&gt;, to Vite+, and made &lt;code&gt;vp migrate&lt;/code&gt; rewrite the references.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1501" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        fix: add vite-plus/pack/client export as tsdown/client equivalent
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1501&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1501" rel="noopener noreferrer"&gt;&lt;time&gt;Apr 29, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;resolves #1500&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/pull/1501" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;But import statements were not the only place with these references. They were also in type declarations, in &lt;code&gt;tsconfig.json&lt;/code&gt;, and in other places.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/1502" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        migrate: rewrite `tsdown/client` and `vite/client` in TS imports and tsconfig.json `types` array
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1502&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/1502" rel="noopener noreferrer"&gt;&lt;time&gt;Apr 30, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Description&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;When running &lt;code&gt;vp migrate&lt;/code&gt;, &lt;code&gt;tsdown&lt;/code&gt; is removed as a dependency and replaced with &lt;code&gt;vite-plus&lt;/code&gt; equivalents.
However, two patterns are currently left unrewritten, causing broken imports and TypeScript errors after migration.&lt;/p&gt;
&lt;p&gt;relates: &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1501" rel="noopener noreferrer"&gt;https://github.com/voidzero-dev/vite-plus/pull/1501&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Cases to handle&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1. &lt;code&gt;import "tsdown/client"&lt;/code&gt; in &lt;code&gt;.ts&lt;/code&gt; files&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-ts js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;// before&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s"&gt;"tsdown/client"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-c"&gt;// after&lt;/span&gt;
&lt;span class="pl-k"&gt;import&lt;/span&gt; &lt;span class="pl-s"&gt;"vite-plus/pack/client"&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Real-world example: &lt;a href="https://github.com/Tarrowren/css-class-intellisense/c91dd77dc1fb5acf/lezer/less/test/test-less.ts#L1" rel="noopener noreferrer"&gt;https://github.com/Tarrowren/css-class-intellisense/c91dd77dc1fb5acf/lezer/less/test/test-less.ts#L1&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2. &lt;code&gt;types&lt;/code&gt; array in &lt;code&gt;tsconfig.json&lt;/code&gt;
&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-json js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ii"&gt;// before&lt;/span&gt;
{ &lt;span class="pl-ent"&gt;"compilerOptions"&lt;/span&gt;: { &lt;span class="pl-ent"&gt;"types"&lt;/span&gt;: [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;tsdown/client&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;] } }
{ &lt;span class="pl-ent"&gt;"compilerOptions"&lt;/span&gt;: { &lt;span class="pl-ent"&gt;"types"&lt;/span&gt;: [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;vite/client&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;] } }

&lt;span class="pl-ii"&gt;// after&lt;/span&gt;
{ &lt;span class="pl-ent"&gt;"compilerOptions"&lt;/span&gt;: { &lt;span class="pl-ent"&gt;"types"&lt;/span&gt;: [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;vite-plus/pack/client&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;] } }
{ &lt;span class="pl-ent"&gt;"compilerOptions"&lt;/span&gt;: { &lt;span class="pl-ent"&gt;"types"&lt;/span&gt;: [&lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;vite-plus/client&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;] } }&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Real-world example: &lt;a href="https://github.com/ascorbic/cirrus/blob/98aec98dc56de58f8d6010565cef6cfc5c62311e/packages/pds/tsconfig.json#L5" rel="noopener noreferrer"&gt;https://github.com/ascorbic/cirrus/blob/98aec98dc56de58f8d6010565cef6cfc5c62311e/packages/pds/tsconfig.json#L5&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Suggested solution&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Case 1 — import in .ts files&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Add a new ast-grep rule to &lt;code&gt;REWRITE_TSDOWN_RULES&lt;/code&gt; (&lt;code&gt;import_rewriter.rs&lt;/code&gt;)
to match &lt;code&gt;import "tsdown/client"&lt;/code&gt; and rewrite it to &lt;code&gt;import "vite-plus/pack/client"&lt;/code&gt;,
alongside the existing &lt;code&gt;tsdown&lt;/code&gt; rule.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Case 2 — tsconfig.json types array&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Add a new function to &lt;code&gt;packages/cli/src/utils/tsconfig.ts&lt;/code&gt; using the existing
&lt;code&gt;jsonc-parser&lt;/code&gt; dependency to rewrite entries in &lt;code&gt;compilerOptions.types&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;"tsdown/client"&lt;/code&gt; → &lt;code&gt;"vite-plus/pack/client"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;"vite/client"&lt;/code&gt; → &lt;code&gt;"vite-plus/client"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Call this function from &lt;code&gt;migrator.ts&lt;/code&gt; alongside &lt;code&gt;cleanupDeprecatedTsconfigOptions()&lt;/code&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Alternative&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Document as manual steps instead of automating. (Even though I don't want to)&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Additional context&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;No response&lt;/em&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Validations&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] Read the &lt;a href="https://github.com/voidzero-dev/vite-plus/blob/main/CONTRIBUTING.md" rel="noopener noreferrer"&gt;Contributing Guidelines&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[x] Confirm this request is for Vite+ itself and not for Vite, Vitest, tsdown, Rolldown, or Oxc.&lt;/li&gt;
&lt;li&gt;[x] Check that there isn't already an issue requesting the same feature.&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/issues/1502" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;So I had to add a migration step for each of these formats.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1541" rel="noopener noreferrer"&gt;#1541&lt;/a&gt; rewrites import and declare module statements.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1541" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat(migration): rewrite tsdown/client import and declare module statements
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1541&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1541" rel="noopener noreferrer"&gt;&lt;time&gt;May 09, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;resolves #1502&lt;/p&gt;
&lt;p&gt;This PR depends on #1501. When you're ready, please make sure #1501, #1541, and #1542 are all merged together.&lt;/p&gt;
&lt;p&gt;I originally thought about including this in #1501, but I decided to pull it into a separate PR so the scope wouldn't get too wide. I figured it would be easier to review if we kept the Rust and TypeScript changes apart rather than mixing them into one.&lt;/p&gt;
&lt;p&gt;Let me know if you’d prefer a different merge strategy and I can easily adjust things.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/pull/1541" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1542" rel="noopener noreferrer"&gt;#1542&lt;/a&gt; rewrites &lt;code&gt;compilerOptions.types&lt;/code&gt; in &lt;code&gt;tsconfig.json&lt;/code&gt;.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1542" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        feat(migration): rewrite tsdown/client and vite/client in tsconfig compilerOptions.types
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#1542&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/pull/1542" rel="noopener noreferrer"&gt;&lt;time&gt;May 09, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;resolves #1502&lt;/p&gt;
&lt;p&gt;This PR depends on #1501. When you're ready to merge, please make sure #1501, #1541, and #1542 are all merged at the same time.&lt;/p&gt;
&lt;p&gt;I thought about putting this together with #1501, but I decided to keep it separate so the scope didn't get too messy. I wanted to keep the Rust and TypeScript parts in different PRs to make the review a bit easier for everyone.&lt;/p&gt;
&lt;p&gt;If you’d prefer to have these combined for the merge, just let me know and I can adjust it.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/pull/1542" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Replacing a dependency sounds easy. But I had to make sure that TypeScript still worked after the migration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Supporting GitLab CI with setup-vp
&lt;/h3&gt;

&lt;p&gt;Next, let me talk about CI.&lt;/p&gt;

&lt;p&gt;If you use Vite+ at work, you want to use it in CI too, and not only on your machine.&lt;/p&gt;

&lt;p&gt;For this, I worked on &lt;code&gt;setup-vp&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;setup-vp&lt;/code&gt; installs Vite+ in a CI environment, and sets up dependencies and caches.&lt;/p&gt;

&lt;p&gt;At that time, it supported GitHub Actions, but not GitLab CI.&lt;/p&gt;

&lt;p&gt;So, to use Vite+ on GitLab, you had to write the install steps yourself.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/setup-vp/issues/88" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Add GitLab CI/CD template support
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#88&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/setup-vp/issues/88" rel="noopener noreferrer"&gt;&lt;time&gt;Jun 25, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;We've received several requests for a GitLab CI/CD version of our existing Vite+ GitHub Action. Currently, we only provide &lt;code&gt;voidzero-dev/setup-vp&lt;/code&gt; for GitHub, leaving GitLab users without an official, reusable setup method. You can find more details in this issue: &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/1920" rel="noopener noreferrer"&gt;https://github.com/voidzero-dev/vite-plus/issues/1920&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Objective&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Our goal is to add official GitLab CI/CD support, enabling users to easily integrate a Vite+ setup template directly into their &lt;code&gt;.gitlab-ci.yml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;For example, users should be able to use the following:&lt;/p&gt;
&lt;div class="highlight highlight-source-yaml js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-ent"&gt;include&lt;/span&gt;:
  - &lt;span class="pl-ent"&gt;remote&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;https://raw.githubusercontent.com/voidzero-dev/setup-vp/v1/gitlab/setup-vp.yml&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The template should replicate the functionality of the GitHub Action, including Node.js and package manager setup, Vite+ installation, and dependency caching.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Proposed Changes&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;I propose adding a dedicated folder for the GitLab CI template:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;gitlab/
└── setup-vp.yml&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Since GitLab supports remote YAML includes, hosting the template in this repository will work seamlessly as long as it remains public.&lt;/p&gt;
&lt;p&gt;For more information on how this works, please refer to the GitLab documentation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.gitlab.com/ci/yaml/#includeremote" rel="nofollow noopener noreferrer"&gt;https://docs.gitlab.com/ci/yaml/#includeremote&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.gitlab.com/ci/migration/github_actions/" rel="nofollow noopener noreferrer"&gt;https://docs.gitlab.com/ci/migration/github_actions/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I will take care of this implementation.&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/setup-vp/issues/88" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;I added a template, so that you do not have to write those steps yourself on GitLab CI.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/setup-vp/pull/97" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
          feat: add GitLab CI/CD integration for setup-vp
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#97&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/setup-vp/pull/97" rel="noopener noreferrer"&gt;&lt;time&gt;Jun 28, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;resolves #88&lt;/p&gt;
&lt;p&gt;I thought it would be best to document the GitLab integration features as an RFC, so I’ve put everything together along with a diagram of the overall flow.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;rfcs/assets/gitlab-runtime-flow.svg&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/user-attachments/assets/860e9587-a0d8-46eb-a733-ae5a0d0d0d20"&gt;&lt;img width="1120" height="780" alt="gitlab-runtime-flow" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fuser-attachments%2Fassets%2F860e9587-a0d8-46eb-a733-ae5a0d0d0d20"&gt;&lt;/a&gt;&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/setup-vp/pull/97" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Now I am a collaborator on &lt;code&gt;setup-vp&lt;/code&gt;, and I help to maintain it.&lt;/p&gt;

&lt;p&gt;For this work, I did not start by writing code. First, I wrote the design in an &lt;a href="https://github.com/voidzero-dev/setup-vp/blob/main/rfcs/gitlab-integration.md" rel="noopener noreferrer"&gt;RFC&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;An RFC is a document that proposes a feature or a design, so that the team can discuss it.&lt;/p&gt;

&lt;p&gt;In the RFC, I used a diagram and text to show how to use &lt;code&gt;setup-vp&lt;/code&gt; in GitLab CI and the order of the steps.&lt;/p&gt;

&lt;p&gt;The GitHub Actions code already existed, so at first it looked like we could reuse it.&lt;/p&gt;

&lt;p&gt;But GitLab CI reads inputs and sets PATH in a different way, so that code does not work there.&lt;/p&gt;

&lt;p&gt;So I kept the usage as similar as possible, and wrote steps only for GitLab.&lt;/p&gt;

&lt;p&gt;Development continued after that. Now several CI services share the same install and authentication steps.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;setup-vp&lt;/code&gt; also supports caching, and it uses the cache feature of both GitHub Actions and GitLab.&lt;/p&gt;

&lt;p&gt;I did not build all of this myself.&lt;/p&gt;

&lt;p&gt;After I added GitLab support, other members added more features.&lt;/p&gt;

&lt;p&gt;A feature can grow from one PR as other people add to it. I think that is one of the interesting things about OSS.&lt;/p&gt;

&lt;p&gt;Up to here, I showed things that I built. After I joined the team, I also started to investigate the causes of Issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Investigating a SolidStart preview failure
&lt;/h3&gt;

&lt;p&gt;One example is an Issue where &lt;code&gt;vp preview&lt;/code&gt; failed on SolidStart v2.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/2416" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        [Bug]: vp preview fails on SolidStart v2 — looks for dist/server but build is in .output/server
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#2416&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/Nicktriez" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F39567847%3Fv%3D4" alt="Nicktriez avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/Nicktriez" rel="noopener noreferrer"&gt;Nicktriez&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/voidzero-dev/vite-plus/issues/2416" rel="noopener noreferrer"&gt;&lt;time&gt;Aug 11, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Describe the bug&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;vp preview&lt;/code&gt; fails on a SolidStart v2 project. &lt;code&gt;vp build&lt;/code&gt; succeeds, but &lt;code&gt;vp preview&lt;/code&gt; throws:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;error when starting preview server:
Error: Could not find the SolidStart server entry in &amp;lt;project&amp;gt;/dist/server
    at resolvePreviewServerEntry (file:///.../@solidjs/start/dist/config/dev-server.js:108:15)
    at configurePreviewServer (.../dev-server.js:20:54)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The build output lands in &lt;code&gt;.output/server&lt;/code&gt; (Nitro's standard layout — the build log shows &lt;code&gt;nitro ... preset: node-server&lt;/code&gt; writing &lt;code&gt;.output/server/index.mjs&lt;/code&gt;), but SolidStart 2's &lt;code&gt;configurePreviewServer&lt;/code&gt; hook hardcodes &lt;code&gt;dist/server&lt;/code&gt; as the server-entry location. So preview looks in the wrong directory.&lt;/p&gt;
&lt;p&gt;This is distinct from #1291 (SolidStart v1 / Vinxi dev-server support, closed). SolidStart v2 uses native Vite (no Vinxi), so the preview hook resolution is the remaining mismatch.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Steps to reproduce&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;Scaffold a SolidStart v2 project with the Tailwind template:
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;pnpm create solid@latest
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; select: SolidStart, TypeScript, with-tailwindcss&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Add the Vite+ toolchain:
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;vp migrate&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Build:
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;vp build
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; succeeds — output written to .output/server and .output/public&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;Preview:
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;vp preview
&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; fails: "Could not find the SolidStart server entry in .../dist/server"&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Expected behavior&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;vp preview&lt;/code&gt; should serve the production build — either by finding the server entry at &lt;code&gt;.output/server&lt;/code&gt; (where Vite+/Nitro actually wrote it), or by delegating preview to Nitro's server for frameworks that use Nitro.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Actual behavior&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;vp preview&lt;/code&gt; errors out looking for &lt;code&gt;dist/server&lt;/code&gt;, which never exists in a Vite+/Nitro build.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Environment&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Vite+ / &lt;code&gt;vp&lt;/code&gt; via &lt;code&gt;vp migrate&lt;/code&gt; (vite-plus core 0.2.8)&lt;/li&gt;
&lt;li&gt;SolidStart 2 (&lt;code&gt;@solidjs/start@^2.0.0&lt;/code&gt;, &lt;code&gt;vite@^8&lt;/code&gt;, &lt;code&gt;nitro@^3&lt;/code&gt; beta)&lt;/li&gt;
&lt;li&gt;OS: Ubuntu 24.04 / Pop!_OS&lt;/li&gt;
&lt;li&gt;Node 24&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Workaround&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;&lt;code&gt;node .output/server/index.mjs&lt;/code&gt; (the &lt;code&gt;start&lt;/code&gt; script) runs the production server correctly. The only broken piece is &lt;code&gt;vp preview&lt;/code&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Related&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;#1291 (closed) — SolidStart v1 / Vinxi &lt;code&gt;vp dev&lt;/code&gt; support. Different: this is SolidStart v2 + &lt;code&gt;vp preview&lt;/code&gt;, where the failure is the preview server-entry path mismatch.&lt;/li&gt;
&lt;/ul&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/voidzero-dev/vite-plus/issues/2416" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;The error occurred when the user used Vite+, so at first it looked like a Vite+ problem.&lt;/p&gt;

&lt;p&gt;But that was not enough to find the cause.&lt;/p&gt;

&lt;p&gt;So I made two projects to test: one with Vite+, and one with Vite only.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/naokihaba/repro-vite-plus-2416" rel="noopener noreferrer"&gt;Reproduction with Vite+&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/naokihaba/repro-vite-plus-2416-plain-vite" rel="noopener noreferrer"&gt;Reproduction with Vite only&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The same error occurred with Vite only.&lt;/p&gt;

&lt;p&gt;So I knew that the problem occurred without Vite+.&lt;/p&gt;

&lt;p&gt;Then, was it a Vite problem? I still did not know.&lt;/p&gt;

&lt;p&gt;The cause could be in SolidStart, so I read the stack trace to find where it failed.&lt;/p&gt;

&lt;p&gt;I investigated more, and found that the cause was in the connection between SolidStart and Nitro.&lt;/p&gt;

&lt;p&gt;Nitro is a tool that builds server applications.&lt;/p&gt;

&lt;p&gt;Nitro writes the built server files to &lt;code&gt;.output/server&lt;/code&gt;, but SolidStart looked for them in a different directory.&lt;/p&gt;

&lt;p&gt;Because of this, SolidStart failed before Nitro's preview step started.&lt;/p&gt;

&lt;p&gt;So I opened an Issue in the SolidStart repository, and shared the reproduction repositories and what I found.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/solidjs/solid-start/issues/2291" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        [Bug?]: Vite preview fails with Nitro v3 because SolidStart looks for dist/server
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#2291&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F59875779%3Fv%3D4" alt="naokihaba avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/naokihaba" rel="noopener noreferrer"&gt;naokihaba&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/solidjs/solid-start/issues/2291" rel="noopener noreferrer"&gt;&lt;time&gt;Aug 14, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Duplicates&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] I have searched the existing issues&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Latest version&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;[x] I have tested the latest version&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Current behavior 😯&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;I’d appreciate the maintainers’ guidance on the preferred approach here. If the analysis and proposed direction below look correct,
I’d be happy to contribute a fix.&lt;/p&gt;
&lt;p&gt;I am a member of the Vite+ team. I found this issue while investigating a bug reported here:
&lt;a href="https://github.com/voidzero-dev/vite-plus/issues/2416" rel="noopener noreferrer"&gt;https://github.com/voidzero-dev/vite-plus/issues/2416&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The same behavior is reproducible with both Vite+ and official Vite:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vite+ reproduction: &lt;a href="https://github.com/naokihaba/repro-vite-plus-2416" rel="noopener noreferrer"&gt;https://github.com/naokihaba/repro-vite-plus-2416&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Official Vite reproduction: &lt;a href="https://github.com/naokihaba/repro-vite-plus-2416-plain-vite" rel="noopener noreferrer"&gt;https://github.com/naokihaba/repro-vite-plus-2416-plain-vite&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The official Vite reproduction uses &lt;code&gt;vite@8.2.0&lt;/code&gt; and does not have either &lt;code&gt;vite-plus&lt;/code&gt; or &lt;code&gt;@voidzero-dev/vite-plus-core&lt;/code&gt; installed.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;vite build&lt;/code&gt; succeeds and generates the Nitro server entry at:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.output/server/index.mjs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nitro records this entry in &lt;code&gt;.output/nitro.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-json js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"serverEntry"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;server/index.mjs&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
  &lt;span class="pl-ent"&gt;"commands"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"preview"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;node ./server/index.mjs&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;
  }
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;However, &lt;code&gt;vite preview&lt;/code&gt; fails with the following error:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;error when starting preview server:
Error: Could not find the SolidStart server entry in &amp;lt;project&amp;gt;/dist/server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The stack trace points to SolidStart's &lt;code&gt;resolvePreviewServerEntry&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;at resolvePreviewServerEntry (.../@solidjs/start/dist/config/dev-server.js:108:15)
at configurePreviewServer (.../@solidjs/start/dist/config/dev-server.js:20:54)
at preview (.../vite/dist/node/chunks/node.js:...)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SolidStart's &lt;code&gt;resolvePreviewServerEntry&lt;/code&gt; only searches for:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;dist/server/entry-server.js
dist/server/entry-server.mjs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Relevant implementation:
&lt;a href="https://github.com/solidjs/solid-start/blob/main/packages/start/src/config/dev-server.ts" rel="noopener noreferrer"&gt;https://github.com/solidjs/solid-start/blob/main/packages/start/src/config/dev-server.ts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Both SolidStart and Nitro register a &lt;code&gt;configurePreviewServer&lt;/code&gt; hook. The resolved hook order is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;solid-start-dev-server
nitro:preview
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SolidStart's hook runs first and throws an error because &lt;code&gt;dist/server/entry-server.*&lt;/code&gt; does not exist. This stops Vite's hook loop before reaching Nitro's preview hook.&lt;/p&gt;
&lt;p&gt;I have shared the detailed investigation here:
&lt;a href="https://github.com/voidzero-dev/vite-plus/issues/2416#issuecomment-5296733248" rel="noopener noreferrer"&gt;https://github.com/voidzero-dev/vite-plus/issues/2416#issuecomment-5296733248&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Expected behavior 🤔&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;When Nitro's Vite plugin controls the production server, SolidStart's preview hook should not require its standalone &lt;code&gt;dist/server/entry-server.*&lt;/code&gt; output.&lt;/p&gt;
&lt;p&gt;Instead, &lt;code&gt;vite preview&lt;/code&gt; should delegate preview handling to Nitro and serve the generated &lt;code&gt;.output/server/index.mjs&lt;/code&gt; build.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Steps to reproduce 🕹&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Reproduction using official Vite:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/naokihaba/repro-vite-plus-2416-plain-vite" rel="noopener noreferrer"&gt;https://github.com/naokihaba/repro-vite-plus-2416-plain-vite&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Clone the reproduction:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;git clone https://github.com/naokihaba/repro-vite-plus-2416-plain-vite.git
&lt;span class="pl-c1"&gt;cd&lt;/span&gt; repro-vite-plus-2416-plain-vite&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Install dependencies:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;pnpm install&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Build the application:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;pnpm build&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;The build succeeds and generates &lt;code&gt;.output/server/index.mjs&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Start the preview server:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;pnpm preview&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;Preview fails while looking for &lt;code&gt;dist/server/entry-server.*&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The generated Nitro server works when started directly:&lt;/p&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;pnpm start&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Context 🔦&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;This was initially reported as a Vite+ bug. I investigated it as a member of the Vite+ team and created a control reproduction using official &lt;code&gt;vite@8.2.0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Because the same failure occurs without Vite+, this appears to be an integration issue between SolidStart's preview hook and Nitro's preview handling.&lt;/p&gt;
&lt;p&gt;SolidStart's &lt;code&gt;configureServer&lt;/code&gt; hook already avoids taking control when another plugin manages the development server:&lt;/p&gt;
&lt;div class="highlight highlight-source-ts js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-k"&gt;if&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s"&gt;"dispatchFetch"&lt;/span&gt; &lt;span class="pl-k"&gt;in&lt;/span&gt; &lt;span class="pl-s1"&gt;serverEnv&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-k"&gt;return&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;

&lt;span class="pl-c"&gt;// another plugin is controlling the dev server&lt;/span&gt;
&lt;span class="pl-k"&gt;if&lt;/span&gt; &lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-c1"&gt;!&lt;/span&gt;&lt;span class="pl-en"&gt;isRunnableDevEnvironment&lt;/span&gt;&lt;span class="pl-kos"&gt;(&lt;/span&gt;&lt;span class="pl-s1"&gt;serverEnv&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt;&lt;span class="pl-kos"&gt;)&lt;/span&gt; &lt;span class="pl-kos"&gt;{&lt;/span&gt;
  &lt;span class="pl-k"&gt;return&lt;/span&gt;&lt;span class="pl-kos"&gt;;&lt;/span&gt;
&lt;span class="pl-kos"&gt;}&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;I think &lt;code&gt;configurePreviewServer&lt;/code&gt; needs equivalent delegation or skip behavior when Nitro controls preview.&lt;/p&gt;
&lt;p&gt;The exact &lt;code&gt;configureServer&lt;/code&gt; condition may not be directly reusable because the preview hook does not necessarily expose the same runtime environment. The important behavior is that SolidStart should avoid resolving &lt;code&gt;dist/server/entry-server.*&lt;/code&gt; when another plugin, such as Nitro, owns the preview server.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Your environment 🌎&lt;/h3&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;div class="highlight highlight-source-shell js-code-highlight"&gt;
&lt;pre&gt;System:
  OS: macOS 26.5.2
  CPU: arm64

Binaries:
  Node: 24.19.0
  pnpm: 11.21.0

npmPackages:
  @solidjs/start: 2.0.0
  nitro: 3.0.260610-beta
  solid-js: 1.9.14
  vite: 8.2.0&lt;/pre&gt;

&lt;/div&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/solidjs/solid-start/issues/2291" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;After that, the SolidStart team fixed the problem in PR &lt;a href="https://github.com/solidjs/solid-start/pull/2294" rel="noopener noreferrer"&gt;#2294&lt;/a&gt;, and released the fix in version 2.0.1.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/solidjs/solid-start/pull/2294" rel="noopener noreferrer"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        fix(dev-server): delegate preview to Nitro when building with Nitro v3
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#2294&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/waterWang" rel="noopener noreferrer"&gt;
        &lt;img class="github-liquid-tag-img" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Favatars.githubusercontent.com%2Fu%2F6082925%3Fv%3D4" alt="waterWang avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/waterWang" rel="noopener noreferrer"&gt;waterWang&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/solidjs/solid-start/pull/2294" rel="noopener noreferrer"&gt;&lt;time&gt;Aug 16, 2026&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Problem&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;When using the official Nitro v3 Vite plugin with &lt;code&gt;preset: "node-server"&lt;/code&gt;, &lt;code&gt;vite preview&lt;/code&gt; fails with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Error: Could not find the SolidStart server entry in &amp;lt;project&amp;gt;/dist/server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SolidStart's &lt;code&gt;configurePreviewServer&lt;/code&gt; hook runs before the &lt;code&gt;nitro:preview&lt;/code&gt; hook. Since Nitro stores the server entry at &lt;code&gt;.output/server/index.mjs&lt;/code&gt; instead of &lt;code&gt;dist/server/entry-server.*&lt;/code&gt;, &lt;code&gt;resolvePreviewServerEntry&lt;/code&gt; throws, stopping Vite's hook loop before Nitro's hook can handle the request.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Fix&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;p&gt;Check for the Nitro build output marker (&lt;code&gt;.output/nitro.json&lt;/code&gt;). If present and the file declares a &lt;code&gt;serverEntry&lt;/code&gt;, SolidStart skips its own preview middleware and lets the &lt;code&gt;nitro:preview&lt;/code&gt; hook handle requests.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Verification&lt;/h2&gt;
&lt;span class="octicon octicon-link"&gt;&lt;/span&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;vite build&lt;/code&gt; + &lt;code&gt;vite preview&lt;/code&gt; with Nitro v3 → succeeds (preview delegated to Nitro)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;vite build&lt;/code&gt; + &lt;code&gt;vite preview&lt;/code&gt; without Nitro → unchanged behavior (SolidStart middleware still used)&lt;/li&gt;
&lt;li&gt;No Nitro build → &lt;code&gt;dist/server/entry-server.*&lt;/code&gt; checked as before&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fixes #2291&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/solidjs/solid-start/pull/2294" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;a href="https://github.com/solidjs/solid-start/releases/tag/%40solidjs%2Fstart%402.0.1" rel="noopener noreferrer"&gt;&lt;code&gt;@solidjs/start&lt;/code&gt; 2.0.1 release&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I updated my projects and confirmed that the problem was gone.&lt;/p&gt;

&lt;p&gt;In this case, I did not change any code.&lt;/p&gt;

&lt;p&gt;But when someone reports a problem in Vite+, the correct fix is not always in Vite+.&lt;/p&gt;

&lt;p&gt;I think finding the cause and taking it to the correct project is also a contribution to OSS.&lt;/p&gt;

&lt;p&gt;As I showed, after I joined the team, I started to work on the project in many ways, and writing code was only one of them.&lt;/p&gt;

&lt;p&gt;At first, I mostly fixed problems that I had myself.&lt;/p&gt;

&lt;p&gt;For example, I thought that my first PR for &lt;code&gt;vp create&lt;/code&gt; was done when the command showed that it did not find the template.&lt;/p&gt;

&lt;p&gt;But after I joined the team and started to look at other people's Issues and PRs, I thought more before writing code.&lt;/p&gt;

&lt;p&gt;In the SolidStart case, if I had changed Vite+ immediately, I could have changed code that was not the cause.&lt;/p&gt;

&lt;p&gt;So now I investigate the problem first, and think about where the fix should go.&lt;/p&gt;

&lt;p&gt;Before, other people reviewed my PRs. Now, I also think about other people's proposals together with them. That is the biggest change from my early days.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI and OSS contributions
&lt;/h2&gt;

&lt;p&gt;Up to here, I talked about investigating Issues and reviewing PRs.&lt;/p&gt;

&lt;p&gt;I also use AI when I read code or implement changes.&lt;/p&gt;

&lt;p&gt;It helped me most when I read code in a language that I did not know well.&lt;/p&gt;

&lt;p&gt;But using AI for my own PRs is different from receiving PRs from other people as a team member.&lt;/p&gt;

&lt;p&gt;Let me tell you what I learned from both sides.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using AI to understand code
&lt;/h3&gt;

&lt;p&gt;First, back to the Nushell work.&lt;/p&gt;

&lt;p&gt;For Nushell, I used AI to read the Rust code.&lt;/p&gt;

&lt;p&gt;When I saw a type or syntax that I did not know, I asked the AI what it meant.&lt;/p&gt;

&lt;p&gt;I also asked it to make an HTML animation of the steps that the code runs.&lt;/p&gt;

&lt;p&gt;In a language that you do not know, the syntax alone can stop you.&lt;/p&gt;

&lt;p&gt;So getting an explanation at that moment helped me a lot.&lt;/p&gt;

&lt;p&gt;But when you read an AI's explanation, you can feel that you understand when you do not.&lt;/p&gt;

&lt;p&gt;In the Nushell example, even if I understood the Rust code, I still did not know if the generated &lt;code&gt;source&lt;/code&gt; command worked.&lt;/p&gt;

&lt;p&gt;So I ran it in Nushell, and checked the original code and the specification.&lt;/p&gt;

&lt;p&gt;When you open a PR, a reviewer may ask why you wrote the code that way.&lt;/p&gt;

&lt;p&gt;"Because the AI said so" is not an explanation.&lt;/p&gt;

&lt;p&gt;So I check what the AI tells me, and I make sure that I can explain it in my own words.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reviewing contributions made with AI
&lt;/h3&gt;

&lt;p&gt;As a reviewer, I see a different side.&lt;/p&gt;

&lt;p&gt;Now, implementation PRs sometimes arrive less than five minutes after someone opens an Issue.&lt;/p&gt;

&lt;p&gt;A fast fix is good.&lt;/p&gt;

&lt;p&gt;But for some Issues, the team has not yet decided whether to make the change.&lt;/p&gt;

&lt;p&gt;When a PR arrives at that stage, the maintainers must check the code, and also decide whether the change is necessary at all.&lt;/p&gt;

&lt;p&gt;Sometimes I ask a question in the review, and the author does not reply.&lt;/p&gt;

&lt;p&gt;Then nobody can confirm the intent of the change, and the PR stops.&lt;/p&gt;

&lt;p&gt;AI can make writing code faster.&lt;/p&gt;

&lt;p&gt;But you still need time to understand that code and check that it works.&lt;/p&gt;

&lt;p&gt;If you leave that work to the maintainers, you only move the work to them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding the problem before writing code
&lt;/h3&gt;

&lt;p&gt;So I think you can also use AI for research and understanding before you write code.&lt;/p&gt;

&lt;p&gt;For example, you find an open Issue on GitHub.&lt;/p&gt;

&lt;p&gt;But an open Issue is not always waiting for an implementation.&lt;/p&gt;

&lt;p&gt;The team may still be discussing the direction, or may not have decided whether to fix it at all.&lt;/p&gt;

&lt;p&gt;So first, ask an AI to summarize the discussion in the Issue.&lt;/p&gt;

&lt;p&gt;Then read the original comments too, and find out what the team has decided and what it has not.&lt;/p&gt;

&lt;p&gt;If it is still not clear, tell the maintainers what you found, and ask them.&lt;/p&gt;

&lt;p&gt;In the SolidStart Issue, I also shared the conditions that reproduce the problem and what I found, and asked about the direction of the fix.&lt;/p&gt;

&lt;p&gt;With AI, writing code is much easier than before.&lt;/p&gt;

&lt;p&gt;But opening a PR is not the goal. You must understand the problem, test the change yourself, and take responsibility for it.&lt;/p&gt;

&lt;p&gt;So, before you ask AI to write code, use it to help you understand the problem.&lt;/p&gt;

&lt;p&gt;I think this way of using AI is important for OSS contributions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Today, I showed some of the Issues and PRs that I worked on.&lt;/p&gt;

&lt;p&gt;At first, I only fixed a problem that I had with &lt;code&gt;vp create&lt;/code&gt;. As I continued, I worked on migration, shells, CI, and more.&lt;/p&gt;

&lt;p&gt;I did not know these areas well at the start.&lt;/p&gt;

&lt;p&gt;I looked up what I did not know, tried it, opened a PR, and learned from the review. I did this again and again.&lt;/p&gt;

&lt;p&gt;Over time, I learned the Vite+ code. I also learned what the project discusses and which direction it takes.&lt;/p&gt;

&lt;p&gt;Now, what I learned then helps me when I look at other people's Issues and PRs.&lt;/p&gt;

&lt;p&gt;Today I talked mostly about code. But you can contribute to OSS without writing code.&lt;/p&gt;

&lt;p&gt;The SolidStart case is an example.&lt;/p&gt;

&lt;p&gt;I reproduced the problem, found the cause, and shared it in an Issue. That was all.&lt;/p&gt;

&lt;p&gt;Another person changed the code.&lt;/p&gt;

&lt;p&gt;Also, if you try to reproduce a reported Issue on your machine, that helps.&lt;/p&gt;

&lt;p&gt;If your comment includes your versions and the steps to reproduce the problem, it is easier to find the cause.&lt;/p&gt;

&lt;p&gt;After a fix, a comment such as "I updated and it works now" also helps.&lt;/p&gt;

&lt;p&gt;Fixing documentation, or telling the team what you think after you use a tool, is also a real contribution.&lt;/p&gt;

&lt;p&gt;After I started to investigate Issues and review PRs myself, I saw how much these reports help.&lt;/p&gt;

&lt;p&gt;Maybe you are interested in OSS, but you are not sure that you can help.&lt;/p&gt;

&lt;p&gt;If so, start with one thing that you noticed in a tool that you use every day.&lt;/p&gt;

&lt;p&gt;For example, when you have a problem, look on GitHub for the same Issue.&lt;/p&gt;

&lt;p&gt;If you find it, try to reproduce it on your machine. If you find the conditions that cause it, write them in a comment.&lt;/p&gt;

&lt;p&gt;That alone can help the maintainers who investigate the problem.&lt;/p&gt;

&lt;p&gt;If you want to implement something, first read the Issue discussion and the contribution guide.&lt;/p&gt;

&lt;p&gt;If the team has not decided the direction yet, tell them what you found and ask them.&lt;/p&gt;

&lt;p&gt;Now AI can help you, so it is easier than before to read and understand code that you do not know.&lt;/p&gt;

&lt;p&gt;I did not plan to join the Core Team.&lt;/p&gt;

&lt;p&gt;I looked into a problem that I had when I used the tool, and I sent a fix. Because of that, I still work on Vite+ today.&lt;/p&gt;

&lt;p&gt;Finally, let me tell you why I continue to contribute to OSS.&lt;/p&gt;

&lt;p&gt;I look into a problem, change the code, and that makes a tool that I use better.&lt;/p&gt;

&lt;p&gt;That is interesting.&lt;/p&gt;

&lt;p&gt;But there is more. I can discuss the same project and review code with engineers that I would not meet at work.&lt;/p&gt;

&lt;p&gt;These connections with people are a big reason why I continue with OSS.&lt;/p&gt;

&lt;p&gt;It started when I fixed a problem that I had with a tool.&lt;/p&gt;

&lt;p&gt;Now, I build Vite+ together with the people that I met there.&lt;/p&gt;

&lt;p&gt;Behind the code of OSS, there are people who think and build together.&lt;/p&gt;

&lt;p&gt;I want to continue to build OSS together with these people.&lt;/p&gt;

&lt;p&gt;Thank you for listening.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>opensource</category>
      <category>softwaredevelopment</category>
      <category>vue</category>
    </item>
  </channel>
</rss>
