<?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: yao tang</title>
    <description>The latest articles on DEV Community by yao tang (@diana_tang).</description>
    <link>https://dev.to/diana_tang</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1537420%2F10fe593b-4f62-40c9-8e7f-8cfe762dd6d6.png</url>
      <title>DEV Community: yao tang</title>
      <link>https://dev.to/diana_tang</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/diana_tang"/>
    <language>en</language>
    <item>
      <title>Complete Guide: Publishing VS Code Extensions to Both Marketplaces</title>
      <dc:creator>yao tang</dc:creator>
      <pubDate>Mon, 13 Oct 2025 08:04:50 +0000</pubDate>
      <link>https://dev.to/diana_tang/complete-guide-publishing-vs-code-extensions-to-both-marketplaces-4d58</link>
      <guid>https://dev.to/diana_tang/complete-guide-publishing-vs-code-extensions-to-both-marketplaces-4d58</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2s0kfngl9j1l529eej3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2s0kfngl9j1l529eej3w.png" alt=" " width="760" height="199"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;Publishing a VS Code extension involves more than just writing code. This guide covers the complete process of publishing to both the official Visual Studio Marketplace and the open-source Open VSX Registry.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prerequisites&lt;/li&gt;
&lt;li&gt;Preparing Your Extension&lt;/li&gt;
&lt;li&gt;Publishing to Visual Studio Marketplace&lt;/li&gt;
&lt;li&gt;Publishing to Open VSX Registry&lt;/li&gt;
&lt;li&gt;Automating with CI/CD&lt;/li&gt;
&lt;li&gt;Best Practices&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Required Tools
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install vsce (Visual Studio Code Extensions CLI)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @vscode/vsce

&lt;span class="c"&gt;# Install ovsx (Open VSX CLI)&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; ovsx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Required Accounts
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Microsoft Account&lt;/strong&gt; - for VS Code Marketplace&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure DevOps Account&lt;/strong&gt; - for Personal Access Token&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eclipse Foundation Account&lt;/strong&gt; - for Open VSX&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Account&lt;/strong&gt; - linked to Eclipse Foundation&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Preparing Your Extension
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Project Structure
&lt;/h3&gt;

&lt;p&gt;Ensure your extension has the proper structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;my-extension/
├── src/
│   └── extension.ts
├── package.json
├── README.md
├── CHANGELOG.md
├── LICENSE
├── .vscodeignore
└── icon.png (128x128 recommended)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Essential package.json Fields
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-extension"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"displayName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My Awesome Extension"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A brief description of what your extension does"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"publisher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-publisher-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Your Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"icon"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"icon.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"repository"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/username/repo"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"engines"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"vscode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^1.80.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"categories"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Other"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"keyword1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"keyword2"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Create a .vscodeignore File
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.vscode/**
.git/**
.gitignore
node_modules/**
src/**
.eslintrc.json
tsconfig.json
**/*.map
**/*.ts
!dist/**
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Write Quality Documentation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;README.md&lt;/strong&gt; should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What the extension does&lt;/li&gt;
&lt;li&gt;Features with screenshots/GIFs&lt;/li&gt;
&lt;li&gt;Installation instructions&lt;/li&gt;
&lt;li&gt;Usage examples&lt;/li&gt;
&lt;li&gt;Configuration options&lt;/li&gt;
&lt;li&gt;Known issues&lt;/li&gt;
&lt;li&gt;Contribution guidelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;CHANGELOG.md&lt;/strong&gt; format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Change Log&lt;/span&gt;

&lt;span class="gu"&gt;## [0.0.1] - 2025-01-15&lt;/span&gt;
&lt;span class="gu"&gt;### Added&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; Initial release
&lt;span class="p"&gt;-&lt;/span&gt; Feature X
&lt;span class="p"&gt;-&lt;/span&gt; Feature Y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Publishing to Visual Studio Marketplace
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create Azure DevOps Organization
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://dev.azure.com/" rel="noopener noreferrer"&gt;https://dev.azure.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sign in with your Microsoft account&lt;/li&gt;
&lt;li&gt;Create a new organization (if you don't have one)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Generate Personal Access Token (PAT)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Click on your profile icon → &lt;strong&gt;User settings&lt;/strong&gt; → &lt;strong&gt;Personal access tokens&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;New Token&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configure:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name&lt;/strong&gt;: VS Code Extension Publishing&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Organization&lt;/strong&gt;: Select your organization&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expiration&lt;/strong&gt;: Custom (set to 1 year or more)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scopes&lt;/strong&gt;: Custom defined → Check &lt;strong&gt;Marketplace&lt;/strong&gt; → &lt;strong&gt;Manage&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create&lt;/strong&gt; and &lt;strong&gt;copy the token immediately&lt;/strong&gt; (you won't see it again!)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Create Publisher
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Create publisher (first time only)&lt;/span&gt;
vsce create-publisher your-publisher-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or create manually at: &lt;a href="https://marketplace.visualstudio.com/manage" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/manage&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Login with vsce
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vsce login your-publisher-name
&lt;span class="c"&gt;# Enter your Personal Access Token when prompted&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Package and Publish
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Test packaging first&lt;/span&gt;
vsce package

&lt;span class="c"&gt;# This creates a .vsix file you can test locally&lt;/span&gt;
&lt;span class="c"&gt;# Install it in VS Code: Extensions → ... → Install from VSIX&lt;/span&gt;

&lt;span class="c"&gt;# Publish to marketplace&lt;/span&gt;
vsce publish

&lt;span class="c"&gt;# Or publish with version bump&lt;/span&gt;
vsce publish patch  &lt;span class="c"&gt;# 0.0.1 → 0.0.2&lt;/span&gt;
vsce publish minor  &lt;span class="c"&gt;# 0.0.1 → 0.1.0&lt;/span&gt;
vsce publish major  &lt;span class="c"&gt;# 0.0.1 → 1.0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Verify Publication
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://marketplace.visualstudio.com/" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Search for your extension&lt;/li&gt;
&lt;li&gt;Check that all information displays correctly&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Publishing to Open VSX Registry
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Setup Eclipse Foundation Account
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create account at &lt;a href="https://accounts.eclipse.org/" rel="noopener noreferrer"&gt;https://accounts.eclipse.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Sign the Eclipse Contributor Agreement (ECA):

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://accounts.eclipse.org/user/eca" rel="noopener noreferrer"&gt;https://accounts.eclipse.org/user/eca&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Read and sign the agreement&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Link GitHub Account
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://accounts.eclipse.org/user/edit" rel="noopener noreferrer"&gt;https://accounts.eclipse.org/user/edit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Find "Social Accounts" section&lt;/li&gt;
&lt;li&gt;Connect your GitHub account&lt;/li&gt;
&lt;li&gt;Verify the connection is successful&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Create Namespace on Open VSX
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Log in to &lt;a href="https://open-vsx.org/" rel="noopener noreferrer"&gt;https://open-vsx.org/&lt;/a&gt; with GitHub&lt;/li&gt;
&lt;li&gt;Go to &lt;a href="https://open-vsx.org/user-settings/namespaces" rel="noopener noreferrer"&gt;https://open-vsx.org/user-settings/namespaces&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create a namespace (should match your publisher name)&lt;/li&gt;
&lt;li&gt;Wait for approval (usually instant if ECA is signed)&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 4: Generate Access Token
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://open-vsx.org/user-settings/tokens" rel="noopener noreferrer"&gt;https://open-vsx.org/user-settings/tokens&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Generate New Token&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Give it a description (e.g., "CLI Publishing")&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Copy the token immediately&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 5: Publish with ovsx
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Login (first time only)&lt;/span&gt;
ovsx create-namespace your-namespace
&lt;span class="c"&gt;# Enter your access token when prompted&lt;/span&gt;

&lt;span class="c"&gt;# Package the extension (if not already packaged)&lt;/span&gt;
vsce package

&lt;span class="c"&gt;# Publish to Open VSX&lt;/span&gt;
ovsx publish &lt;span class="nt"&gt;-p&lt;/span&gt; YOUR_ACCESS_TOKEN

&lt;span class="c"&gt;# Or publish specific file&lt;/span&gt;
ovsx publish your-extension-0.0.1.vsix &lt;span class="nt"&gt;-p&lt;/span&gt; YOUR_ACCESS_TOKEN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Verify on Open VSX
&lt;/h3&gt;

&lt;p&gt;Visit &lt;a href="https://open-vsx.org/" rel="noopener noreferrer"&gt;https://open-vsx.org/&lt;/a&gt; and search for your extension.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating with CI/CD
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GitHub Actions Example
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;.github/workflows/publish.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish Extension&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;created&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;publish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node.js&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;18'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build extension&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run compile&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Package extension&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx vsce package&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish to VS Marketplace&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx vsce publish -p ${{ secrets.VSCE_TOKEN }}&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish to Open VSX&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npx ovsx publish -p ${{ secrets.OVSX_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setup GitHub Secrets
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to your repository → &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Secrets and variables&lt;/strong&gt; → &lt;strong&gt;Actions&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Add secrets:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;VSCE_TOKEN&lt;/code&gt;: Your Azure DevOps PAT&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;OVSX_TOKEN&lt;/code&gt;: Your Open VSX access token&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Version Management
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Use&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;semantic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;versioning&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MAJOR.MINOR.PATCH"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Example:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Initial&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;stable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;release&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;New&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;features,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;backward&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;compatible&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Bug&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;fixes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Breaking&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;changes&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pre-publish Checklist
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Test extension thoroughly in VS Code&lt;/li&gt;
&lt;li&gt;[ ] Update CHANGELOG.md&lt;/li&gt;
&lt;li&gt;[ ] Update version in package.json&lt;/li&gt;
&lt;li&gt;[ ] Update README.md if features changed&lt;/li&gt;
&lt;li&gt;[ ] Check all links work&lt;/li&gt;
&lt;li&gt;[ ] Verify icon displays correctly (128x128 PNG)&lt;/li&gt;
&lt;li&gt;[ ] Run &lt;code&gt;vsce package&lt;/code&gt; and test the .vsix locally&lt;/li&gt;
&lt;li&gt;[ ] Commit and push all changes&lt;/li&gt;
&lt;li&gt;[ ] Create Git tag for version&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Security Best Practices
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Never commit tokens to Git&lt;/span&gt;
&lt;span class="c"&gt;# Add to .gitignore:&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"*.vsix"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;".env"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; .gitignore

&lt;span class="c"&gt;# Store tokens in environment variables&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VSCE_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-token"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OVSX_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your-token"&lt;/span&gt;

&lt;span class="c"&gt;# Or use a .env file (don't commit!)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Extension Quality Guidelines
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimize activation time&lt;/li&gt;
&lt;li&gt;Use activation events efficiently&lt;/li&gt;
&lt;li&gt;Lazy load heavy dependencies&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;User Experience&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Provide clear error messages&lt;/li&gt;
&lt;li&gt;Add configuration options&lt;/li&gt;
&lt;li&gt;Include helpful documentation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Compatibility&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Test on multiple VS Code versions&lt;/li&gt;
&lt;li&gt;Support both Windows and Unix line endings&lt;/li&gt;
&lt;li&gt;Consider different VS Code themes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Common Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Issue: "Publisher not found"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Create publisher first with &lt;code&gt;vsce create-publisher&lt;/code&gt; or via web interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue: "Missing repository field"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Add repository to package.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"repository"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/username/repo"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Issue: "Icon not found"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure icon.png exists in root directory&lt;/li&gt;
&lt;li&gt;Use 128x128 PNG format&lt;/li&gt;
&lt;li&gt;Reference it in package.json: &lt;code&gt;"icon": "icon.png"&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Issue: Open VSX "Must sign Publisher Agreement"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: See my other article on solving this specific issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Issue: "Invalid version"
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Use semantic versioning format (X.Y.Z) in package.json.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating Your Extension
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 1. Make your changes&lt;/span&gt;
&lt;span class="c"&gt;# 2. Update CHANGELOG.md&lt;/span&gt;
&lt;span class="c"&gt;# 3. Test thoroughly&lt;/span&gt;

&lt;span class="c"&gt;# 4. Bump version and publish&lt;/span&gt;
vsce publish patch  &lt;span class="c"&gt;# or minor, or major&lt;/span&gt;

&lt;span class="c"&gt;# 5. Publish to Open VSX&lt;/span&gt;
ovsx publish &lt;span class="nt"&gt;-p&lt;/span&gt; YOUR_TOKEN

&lt;span class="c"&gt;# 6. Create Git tag&lt;/span&gt;
git tag v0.0.2
git push &lt;span class="nt"&gt;--tags&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Useful Commands Reference
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Package without publishing&lt;/span&gt;
vsce package

&lt;span class="c"&gt;# Publish with specific version&lt;/span&gt;
vsce publish 1.0.0

&lt;span class="c"&gt;# Unpublish (use carefully!)&lt;/span&gt;
vsce unpublish publisher.extension-name

&lt;span class="c"&gt;# List all versions&lt;/span&gt;
vsce show publisher.extension-name

&lt;span class="c"&gt;# Open VSX commands&lt;/span&gt;
ovsx get extension-name
ovsx publish package.vsix &lt;span class="nt"&gt;-p&lt;/span&gt; TOKEN
ovsx version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/api" rel="noopener noreferrer"&gt;VS Code Extension API&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/api/working-with-extensions/publishing-extension" rel="noopener noreferrer"&gt;Publishing Extensions Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/manage" rel="noopener noreferrer"&gt;VS Marketplace Management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/eclipse/openvsx/wiki" rel="noopener noreferrer"&gt;Open VSX Wiki&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/vscode-vsce" rel="noopener noreferrer"&gt;vsce Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/eclipse/openvsx/wiki/Publishing-Extensions" rel="noopener noreferrer"&gt;ovsx Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Publishing VS Code extensions requires setup, but once configured, the process is straightforward. Key points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set up accounts and tokens for both marketplaces&lt;/li&gt;
&lt;li&gt;Prepare quality documentation&lt;/li&gt;
&lt;li&gt;Test thoroughly before publishing&lt;/li&gt;
&lt;li&gt;Automate with CI/CD for efficiency&lt;/li&gt;
&lt;li&gt;Keep both marketplaces in sync&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Remember: Open VSX is important for VS Code forks like VSCodium, Gitpod, and others that don't use the Microsoft Marketplace.&lt;/p&gt;

&lt;p&gt;Happy publishing! 🚀&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>extensions</category>
      <category>development</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Solving Open VSX "Must log in with Eclipse Foundation account" Error</title>
      <dc:creator>yao tang</dc:creator>
      <pubDate>Mon, 13 Oct 2025 07:25:50 +0000</pubDate>
      <link>https://dev.to/diana_tang/solving-open-vsx-must-log-in-with-eclipse-foundation-account-error-hp5</link>
      <guid>https://dev.to/diana_tang/solving-open-vsx-must-log-in-with-eclipse-foundation-account-error-hp5</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1muf49m29p6a0rz5l7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1muf49m29p6a0rz5l7r.png" alt=" " width="606" height="252"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;When trying to create a namespace on &lt;a href="https://open-vsx.org/" rel="noopener noreferrer"&gt;Open VSX&lt;/a&gt; to publish VS Code extensions, I encountered this error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Error&lt;/strong&gt;: You must log in with an Eclipse Foundation account and sign a Publisher Agreement before publishing any extension.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The confusing part? I had already logged into my Eclipse Foundation account at &lt;a href="https://accounts.eclipse.org/" rel="noopener noreferrer"&gt;https://accounts.eclipse.org/&lt;/a&gt;, but Open VSX kept redirecting me to GitHub login, and the error persisted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the Issue
&lt;/h2&gt;

&lt;p&gt;Here's what I learned:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open VSX only supports GitHub OAuth login&lt;/strong&gt; - there's no direct Eclipse Foundation login option on the Open VSX website&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eclipse Foundation account is still required&lt;/strong&gt; - but it works behind the scenes through account linking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Publisher Agreement (ECA) must be signed&lt;/strong&gt; - this is separate from just having an account&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Solution
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Sign the Eclipse Contributor Agreement (ECA)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to your Eclipse Foundation account: &lt;a href="https://accounts.eclipse.org/" rel="noopener noreferrer"&gt;https://accounts.eclipse.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Navigate to the ECA page: &lt;a href="https://accounts.eclipse.org/user/eca" rel="noopener noreferrer"&gt;https://accounts.eclipse.org/user/eca&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Read and sign the Eclipse Contributor Agreement&lt;/li&gt;
&lt;li&gt;Alternatively, you can sign it directly at: &lt;a href="https://www.eclipse.org/legal/ECA.php" rel="noopener noreferrer"&gt;https://www.eclipse.org/legal/ECA.php&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 2: Link Your GitHub Account
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to your Eclipse Foundation account settings: &lt;a href="https://accounts.eclipse.org/user/edit" rel="noopener noreferrer"&gt;https://accounts.eclipse.org/user/edit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Find the "Social Accounts" or "External Accounts" section&lt;/li&gt;
&lt;li&gt;Connect your GitHub account that you use to log into Open VSX&lt;/li&gt;
&lt;li&gt;Make sure the connection is successful&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 3: Wait for Synchronization
&lt;/h3&gt;

&lt;p&gt;After signing the ECA and linking accounts, wait a few minutes (sometimes up to an hour) for the systems to synchronize.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Create Your Namespace
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Clear your browser cache and cookies for open-vsx.org&lt;/li&gt;
&lt;li&gt;Log in to Open VSX with your GitHub account: &lt;a href="https://open-vsx.org/" rel="noopener noreferrer"&gt;https://open-vsx.org/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go to namespace settings: &lt;a href="https://open-vsx.org/user-settings/namespaces" rel="noopener noreferrer"&gt;https://open-vsx.org/user-settings/namespaces&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create your namespace - the error should be gone!&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why This Happens
&lt;/h2&gt;

&lt;p&gt;Open VSX uses GitHub for authentication (OAuth), but requires Eclipse Foundation's legal framework for publishing. The connection between these two systems requires:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An Eclipse Foundation account&lt;/li&gt;
&lt;li&gt;A signed Eclipse Contributor Agreement (ECA)&lt;/li&gt;
&lt;li&gt;Your GitHub account linked to your Eclipse Foundation account&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Troubleshooting Tips
&lt;/h2&gt;

&lt;p&gt;If you still see the error after following these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clear browser data&lt;/strong&gt;: Remove all cookies and cache for open-vsx.org&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Try incognito mode&lt;/strong&gt;: This ensures no old session data interferes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Wait longer&lt;/strong&gt;: Sometimes synchronization takes time&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Verify the link&lt;/strong&gt;: Check your Eclipse Foundation account to confirm GitHub is properly linked&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Re-sign if needed&lt;/strong&gt;: If you signed the ECA a long time ago, try signing again&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://open-vsx.org/" rel="noopener noreferrer"&gt;Open VSX Registry&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://accounts.eclipse.org/" rel="noopener noreferrer"&gt;Eclipse Foundation Account&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.eclipse.org/legal/ECA.php" rel="noopener noreferrer"&gt;Eclipse Contributor Agreement&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/eclipse/openvsx/wiki/Publishing-Extensions" rel="noopener noreferrer"&gt;Open VSX Publishing Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The key insight is that Open VSX uses GitHub for login but Eclipse Foundation for legal compliance. Once you understand this relationship and properly link your accounts with a signed ECA, publishing extensions becomes straightforward.&lt;/p&gt;

&lt;p&gt;Hope this helps others who encounter the same issue! 🚀&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you encountered similar issues with Open VSX or VS Code extension publishing? Share your experience in the comments!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>extensions</category>
      <category>opensource</category>
      <category>troubleshooting</category>
    </item>
    <item>
      <title>How to Publish Your First NPM Package: A Complete Guide</title>
      <dc:creator>yao tang</dc:creator>
      <pubDate>Wed, 11 Jun 2025 16:54:34 +0000</pubDate>
      <link>https://dev.to/diana_tang/how-to-publish-your-first-npm-package-a-complete-guide-4h0l</link>
      <guid>https://dev.to/diana_tang/how-to-publish-your-first-npm-package-a-complete-guide-4h0l</guid>
      <description>&lt;p&gt;Publishing your first NPM package can seem daunting, but it's actually straightforward once you know the steps. In this guide, I'll walk you through the entire process, including how to solve common issues like registry configuration problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node.js and npm installed&lt;/li&gt;
&lt;li&gt;A project ready to publish&lt;/li&gt;
&lt;li&gt;An NPM account (create one at &lt;a href="https://npmjs.com" rel="noopener noreferrer"&gt;npmjs.com&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Check Package Name Availability
&lt;/h2&gt;

&lt;p&gt;Before you start, make sure your desired package name isn't already taken:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm search your-package-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the name is taken, you have several options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use a scoped package: &lt;code&gt;@yourusername/package-name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Choose a different name&lt;/li&gt;
&lt;li&gt;Add descriptive prefixes/suffixes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, if "testpilot" is taken, you could use "ai-testpilot" or "@yourusername/testpilot".&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Configure Your package.json
&lt;/h2&gt;

&lt;p&gt;Make sure your &lt;code&gt;package.json&lt;/code&gt; has all the required fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"your-package-name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"What your package does"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"repository"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git+https://github.com/yourusername/your-repo.git"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"keyword1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"keyword2"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"author"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Your Name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"license"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"MIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bugs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/yourusername/your-repo/issues"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"homepage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/yourusername/your-repo#readme"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For CLI tools, add a &lt;code&gt;bin&lt;/code&gt; field:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"your-command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./bin/cli.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Fix Registry Configuration (Important!)
&lt;/h2&gt;

&lt;p&gt;This is where many people get stuck. If you're using a mirror like Taobao or npmmirror, you need to switch back to the official NPM registry for publishing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check your current registry:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm config get registry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If it shows anything other than &lt;code&gt;https://registry.npmjs.org/&lt;/code&gt;, fix it:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm config &lt;span class="nb"&gt;set &lt;/span&gt;registry https://registry.npmjs.org/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Common problematic registries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;https://registry.npmmirror.com/&lt;/code&gt; (Alibaba mirror)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;https://registry.npm.taobao.org/&lt;/code&gt; (Taobao mirror)&lt;/li&gt;
&lt;li&gt;Company internal registries&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 4: Login to NPM
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll be prompted for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username&lt;/li&gt;
&lt;li&gt;Password&lt;/li&gt;
&lt;li&gt;Email address&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Verify you're logged in:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;whoami&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5: Prepare for Publishing
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Create .npmignore (optional):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;node_modules/
.git/
.DS_Store
*.log
test/
.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If you're using TypeScript, build first:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test your package locally:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm pack
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; your-package-name-1.0.0.tgz
&lt;span class="c"&gt;# Test your package&lt;/span&gt;
npm uninstall &lt;span class="nt"&gt;-g&lt;/span&gt; your-package-name
&lt;span class="nb"&gt;rm &lt;/span&gt;your-package-name-1.0.0.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6: Publish!
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;For scoped packages, make them public:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm publish &lt;span class="nt"&gt;--access&lt;/span&gt; public
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7: Verify Publication
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Check on NPM website:&lt;/strong&gt;&lt;br&gt;
Visit &lt;code&gt;https://npmjs.com/package/your-package-name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Search for your package:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm search your-package-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test installation:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;your-package-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Issues and Solutions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  "Package name already exists"
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Use a scoped package: &lt;code&gt;@yourusername/package-name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Choose a different name&lt;/li&gt;
&lt;li&gt;Check if the existing package is abandoned (contact NPM support)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  "Public registration is not allowed"
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You're trying to publish to a private registry (like CNPM)&lt;/li&gt;
&lt;li&gt;Fix your registry configuration (Step 3)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  "You do not have permission to publish"
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Make sure you're logged in: &lt;code&gt;npm whoami&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Check if you're trying to publish to the correct registry&lt;/li&gt;
&lt;li&gt;For scoped packages, use &lt;code&gt;--access public&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  "Avatar not updating"
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;NPM uses Gravatar for avatars&lt;/li&gt;
&lt;li&gt;Link your NPM email to a Gravatar account&lt;/li&gt;
&lt;li&gt;Clear browser cache and wait for synchronization&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pro Tips
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Version Management:&lt;/strong&gt; Use semantic versioning (major.minor.patch)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a README:&lt;/strong&gt; Include installation and usage instructions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keywords:&lt;/strong&gt; Add relevant keywords for better discoverability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;License:&lt;/strong&gt; Always specify a license (MIT is popular)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated Publishing:&lt;/strong&gt; Consider using GitHub Actions for CI/CD&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Updating Your Package
&lt;/h2&gt;

&lt;p&gt;When you need to update:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Make your changes&lt;/li&gt;
&lt;li&gt;Update the version in &lt;code&gt;package.json&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npm publish&lt;/code&gt; again
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Quick version bump&lt;/span&gt;
npm version patch  &lt;span class="c"&gt;# 1.0.0 -&amp;gt; 1.0.1&lt;/span&gt;
npm version minor  &lt;span class="c"&gt;# 1.0.0 -&amp;gt; 1.1.0&lt;/span&gt;
npm version major  &lt;span class="c"&gt;# 1.0.0 -&amp;gt; 2.0.0&lt;/span&gt;
npm publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Publishing to NPM is straightforward once you understand the process. The most common stumbling block is registry configuration - always make sure you're pointing to the official NPM registry when publishing.&lt;/p&gt;

&lt;p&gt;Your package is now available for the entire Node.js community to use. Congratulations on your first NPM publication! 🎉&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have you published your first NPM package? Share your experience in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>node</category>
      <category>npm</category>
      <category>ai</category>
    </item>
    <item>
      <title>🐳 NestJS + Docker + PostgreSQL Debugging: Why Is It Trying to Connect as `callustang`?</title>
      <dc:creator>yao tang</dc:creator>
      <pubDate>Wed, 28 May 2025 11:04:28 +0000</pubDate>
      <link>https://dev.to/diana_tang/nestjs-docker-postgresql-debugging-why-is-it-trying-to-connect-as-callustang-1g5m</link>
      <guid>https://dev.to/diana_tang/nestjs-docker-postgresql-debugging-why-is-it-trying-to-connect-as-callustang-1g5m</guid>
      <description>&lt;h2&gt;
  
  
  🧩 Background
&lt;/h2&gt;

&lt;p&gt;While developing a backend project with &lt;strong&gt;NestJS + TypeORM + PostgreSQL&lt;/strong&gt;, I used &lt;code&gt;docker-compose&lt;/code&gt; to spin up both the backend service and the database. Although I had successfully created tables and inserted data into the database, the NestJS app kept failing to connect—mysteriously attempting to authenticate as my Mac user, &lt;code&gt;callustang&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here’s the error log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;Nest] 75975  - ERROR &lt;span class="o"&gt;[&lt;/span&gt;TypeOrmModule] Unable to connect to the database. Retrying...
Error: password authentication failed &lt;span class="k"&gt;for &lt;/span&gt;user &lt;span class="s2"&gt;"callustang"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But my &lt;code&gt;.env&lt;/code&gt; configuration clearly specified:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_USER=root
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And even in &lt;code&gt;app.module.ts&lt;/code&gt;, I logged the DB config:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DB Config:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DB_HOST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DB_USER&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything looked correct, yet the connection kept failing. 🤯&lt;/p&gt;




&lt;h2&gt;
  
  
  🕵️ Investigation Path
&lt;/h2&gt;

&lt;p&gt;The core question was: &lt;strong&gt;Where is the app actually running, and what database is it trying to connect to?&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ I checked:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.env&lt;/code&gt; had &lt;code&gt;DB_HOST=pgsqldb&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker-compose.yml&lt;/code&gt; defined a &lt;code&gt;pgsqldb&lt;/code&gt; service correctly&lt;/li&gt;
&lt;li&gt;NestJS printed out &lt;code&gt;DB_HOST: 'pgsqldb'&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;But the logs showed: &lt;code&gt;getaddrinfo ENOTFOUND pgsqldb&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❗ The real issue:
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;The NestJS app was &lt;strong&gt;running locally on my Mac&lt;/strong&gt;, not inside a Docker container.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your local machine &lt;strong&gt;cannot resolve &lt;code&gt;pgsqldb&lt;/code&gt;&lt;/strong&gt;, which is a hostname only available inside Docker’s internal network. Hence, the DB connection failed.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Solution 1: Run the NestJS App &lt;strong&gt;Inside Docker&lt;/strong&gt; ✅
&lt;/h2&gt;

&lt;p&gt;I created a proper development Dockerfile and ensured the container had essential tools like &lt;code&gt;ps&lt;/code&gt; (used by SWC for hot reload).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:20.14.0-bookworm-slim&lt;/span&gt;

&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;  vim curl wget git procps &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get clean &lt;span class="se"&gt;\
&lt;/span&gt;  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /var/lib/apt/lists/&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /usr/src/app&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; package.json package-lock.json ./&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 3000&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "run", "start:dev"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In &lt;code&gt;docker-compose.yml&lt;/code&gt;, I updated the &lt;code&gt;app&lt;/code&gt; service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4000:4000"&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.:/usr/src/app&lt;/span&gt;
    &lt;span class="na"&gt;env_file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;.env&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;pgsqldb&lt;/span&gt;
    &lt;span class="na"&gt;networks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;app-network&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I rebuilt and started everything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker compose down &lt;span class="nt"&gt;-v&lt;/span&gt;
docker compose build &lt;span class="nt"&gt;--no-cache&lt;/span&gt;
docker compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Boom! NestJS successfully connected to PostgreSQL inside the container.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Solution 2: Still want to run NestJS &lt;strong&gt;locally&lt;/strong&gt;?
&lt;/h2&gt;

&lt;p&gt;Then you must change &lt;code&gt;.env&lt;/code&gt; to use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DB_HOST=localhost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That way, your Mac connects to the containerized PostgreSQL via port mapping.&lt;/p&gt;

&lt;p&gt;Ensure your &lt;code&gt;pgsqldb&lt;/code&gt; service has:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;5432:5432&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works but is &lt;strong&gt;not recommended&lt;/strong&gt; for long-term use, especially in team projects or CI/CD pipelines.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❓ What about &lt;code&gt;/bin/sh: ps: not found&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;When running &lt;code&gt;npm run start:dev&lt;/code&gt;, I saw this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Error: Command failed: ps &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; pid,ppid
/bin/sh: 1: ps: not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Turns out the Docker image I used (&lt;code&gt;node:bookworm-slim&lt;/code&gt;) doesn't include the &lt;code&gt;ps&lt;/code&gt; utility. The solution is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; procps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;SWC, Nest CLI, and some TypeScript checkers rely on &lt;code&gt;ps&lt;/code&gt; to inspect running processes. It’s not critical, but removing the error makes development smoother.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔒 Should I install &lt;code&gt;procps&lt;/code&gt; in &lt;strong&gt;production&lt;/strong&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;No.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In production, your command is simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"start:prod"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node dist/src/main"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This does not need &lt;code&gt;ps&lt;/code&gt;, &lt;code&gt;SWC&lt;/code&gt;, or any hot-reloading tools. Keep your prod images &lt;strong&gt;lean and secure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I used a multi-stage Docker build:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Stage 1: Build&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;node:20.14.0-bookworm-slim&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;as&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;builder&lt;/span&gt;
...
&lt;span class="k"&gt;RUN &lt;/span&gt;npm run build &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm prune &lt;span class="nt"&gt;--production&lt;/span&gt;

&lt;span class="c"&gt;# Stage 2: Runtime&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; node:20.14.0-bookworm-slim&lt;/span&gt;
...
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="s"&gt; node&lt;/span&gt;
&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["npm", "run", "start:prod"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🚫 No &lt;code&gt;ps&lt;/code&gt; needed. No bloat.&lt;/p&gt;




&lt;h2&gt;
  
  
  📌 Summary &amp;amp; Lessons Learned
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Cause&lt;/th&gt;
&lt;th&gt;Solution&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DB connection fails as &lt;code&gt;callustang&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;App is running on the host and defaulting to Mac user&lt;/td&gt;
&lt;td&gt;Run the app inside Docker&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ENOTFOUND pgsqldb&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Local machine can't resolve Docker hostname&lt;/td&gt;
&lt;td&gt;Either switch to Docker or use &lt;code&gt;localhost&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;/bin/sh: ps: not found&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Slim image lacks &lt;code&gt;procps&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Add &lt;code&gt;apt-get install procps&lt;/code&gt; in Dockerfile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Should prod image include &lt;code&gt;ps&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Keep it minimal and secure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  💬 Have You Run Into This?
&lt;/h2&gt;

&lt;p&gt;Let me know in the comments if you’ve hit similar container vs. host confusion with NestJS, or if you’ve debugged weird Docker DNS issues. If this helped, give it a ❤️, bookmark it, or share it with someone struggling with dev containers!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Complete Git Authentication Troubleshooting Guide</title>
      <dc:creator>yao tang</dc:creator>
      <pubDate>Fri, 23 May 2025 06:51:07 +0000</pubDate>
      <link>https://dev.to/diana_tang/complete-git-authentication-troubleshooting-guide-487m</link>
      <guid>https://dev.to/diana_tang/complete-git-authentication-troubleshooting-guide-487m</guid>
      <description>&lt;h2&gt;
  
  
  Problem Description
&lt;/h2&gt;

&lt;p&gt;While working with Git for code management, I encountered a classic authentication failure issue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git pull &lt;span class="nt"&gt;--tags&lt;/span&gt; origin main
ERROR: Repository not found.
fatal: Could not &lt;span class="nb"&gt;read &lt;/span&gt;from remote repository.

Please make sure you have the correct access rights and the repository exists.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This problem typically occurs in the following scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switched to a different GitHub account&lt;/li&gt;
&lt;li&gt;Previously used email is no longer accessible&lt;/li&gt;
&lt;li&gt;Local Git configuration doesn't match the current available account&lt;/li&gt;
&lt;li&gt;SSH key configuration issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Environment Information
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Operating System&lt;/strong&gt;: macOS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Git Version&lt;/strong&gt;: Standard version&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Problem Scenario&lt;/strong&gt;: Can download GitHub repository content but unable to execute git pull operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Historical Context&lt;/strong&gt;: Previously used a different account for commits, that email is no longer available&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Complete Solution Workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Problem Diagnosis
&lt;/h3&gt;

&lt;h4&gt;
  
  
  1.1 Check Current Git Configuration
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email
git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  1.2 Check Repository Status
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Issues Identified&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local repository remote URL points to incorrect user repository&lt;/li&gt;
&lt;li&gt;Authentication credentials don't match current available account&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step 2: Attempting SSH Authentication Fix
&lt;/h3&gt;

&lt;h4&gt;
  
  
  2.1 Test SSH Connection
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: SSH connection was successful, showing correct username authentication.&lt;/p&gt;

&lt;h4&gt;
  
  
  2.2 Update Remote Repository URL
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote set-url origin git@github.com:YourUsername/repository-name.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2.3 Test Pull Operation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull &lt;span class="nt"&gt;--tags&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Result&lt;/strong&gt;: Still encountering "Connection closed by 140.82.112.4 port 22" error.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Switch to HTTPS Authentication (Key Solution)
&lt;/h3&gt;

&lt;h4&gt;
  
  
  3.1 Change Remote Repository URL to HTTPS
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote set-url origin https://github.com/YourUsername/repository-name.git
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3.2 Verify URL Update
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Should display:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;origin  https://github.com/YourUsername/repository-name.git (fetch)
origin  https://github.com/YourUsername/repository-name.git (push)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3.3 Configure Pull Strategy
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git config pull.rebase &lt;span class="nb"&gt;false&lt;/span&gt;  &lt;span class="c"&gt;# Use merge strategy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3.4 Execute Pull Operation
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull &lt;span class="nt"&gt;--tags&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Resolve History Conflicts
&lt;/h3&gt;

&lt;p&gt;After executing the pull, you may encounter "refusing to merge unrelated histories" error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;fatal: refusing to merge unrelated histories
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4.1 Force Merge Unrelated Histories
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git pull &lt;span class="nt"&gt;--tags&lt;/span&gt; origin main &lt;span class="nt"&gt;--allow-unrelated-histories&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4.2 Resolve Potential Conflicts
&lt;/h4&gt;

&lt;p&gt;If conflicts occur, follow these steps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check conflict status&lt;/span&gt;
git status

&lt;span class="c"&gt;# Manually edit conflict files, then after resolving conflicts&lt;/span&gt;
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Merge remote and local histories"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Core Solution Points
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. SSH vs HTTPS Selection
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSH Advantages&lt;/strong&gt;: One-time setup, long-term use, no repeated password entry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTPS Advantages&lt;/strong&gt;: Better network compatibility, more stable in firewall environments&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recommendation&lt;/strong&gt;: If SSH connections are unstable, switch to HTTPS decisively&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Authentication Credential Management
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When using HTTPS, you need GitHub Personal Access Token, not account password&lt;/li&gt;
&lt;li&gt;Token acquisition path: GitHub Settings → Developer settings → Personal access tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Repository History Merging
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When local and remote repository histories are unrelated, use &lt;code&gt;--allow-unrelated-histories&lt;/code&gt; parameter&lt;/li&gt;
&lt;li&gt;This situation is common when merging independently created local and remote repositories&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prevention Measures
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Regularly Update Git Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Ensure using current available email and username&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.name &lt;span class="s2"&gt;"CurrentUsername"&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; user.email &lt;span class="s2"&gt;"current-available-email@example.com"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Choose Appropriate Authentication Method
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Stable network environment: Prioritize SSH&lt;/li&gt;
&lt;li&gt;Restricted network environment: Recommend HTTPS&lt;/li&gt;
&lt;li&gt;Team collaboration: Standardize authentication methods to reduce issues&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Backup Important Configurations
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Backup SSH keys&lt;/span&gt;
&lt;span class="nb"&gt;cp&lt;/span&gt; ~/.ssh/id_&lt;span class="k"&gt;*&lt;/span&gt; ~/backup_ssh/

&lt;span class="c"&gt;# Record important Git configurations&lt;/span&gt;
git config &lt;span class="nt"&gt;--list&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; git_config_backup.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Common Variant Problems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Problem 1: Permission denied (publickey)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Regenerate SSH keys and add to GitHub&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 2: Repository not found
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Check repository URL and access permissions&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 3: Authentication failed
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Solution&lt;/strong&gt;: Update Personal Access Token&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting Commands Summary
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Essential Diagnostic Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check current configuration&lt;/span&gt;
git config &lt;span class="nt"&gt;--list&lt;/span&gt;
git remote &lt;span class="nt"&gt;-v&lt;/span&gt;
git status

&lt;span class="c"&gt;# Test connections&lt;/span&gt;
ssh &lt;span class="nt"&gt;-T&lt;/span&gt; git@github.com
git ls-remote origin

&lt;span class="c"&gt;# Clear authentication cache (macOS)&lt;/span&gt;
git config &lt;span class="nt"&gt;--global&lt;/span&gt; &lt;span class="nt"&gt;--unset&lt;/span&gt; credential.helper
security delete-internet-password &lt;span class="nt"&gt;-s&lt;/span&gt; github.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Quick Fix Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Switch to HTTPS (most reliable)&lt;/span&gt;
git remote set-url origin https://github.com/username/repo.git

&lt;span class="c"&gt;# Configure pull strategy&lt;/span&gt;
git config pull.rebase &lt;span class="nb"&gt;false&lt;/span&gt;

&lt;span class="c"&gt;# Handle unrelated histories&lt;/span&gt;
git pull origin main &lt;span class="nt"&gt;--allow-unrelated-histories&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  SSH Troubleshooting Commands
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Generate new SSH key&lt;/span&gt;
ssh-keygen &lt;span class="nt"&gt;-t&lt;/span&gt; ed25519 &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"your-email@example.com"&lt;/span&gt;

&lt;span class="c"&gt;# Add to SSH agent&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;ssh-agent &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
ssh-add ~/.ssh/id_ed25519

&lt;span class="c"&gt;# View public key&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; ~/.ssh/id_ed25519.pub
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Authentication Method Selection
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;For personal projects&lt;/strong&gt;: SSH is convenient after initial setup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For corporate environments&lt;/strong&gt;: HTTPS often works better with proxy/firewall&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;For CI/CD&lt;/strong&gt;: Use deploy keys or token-based authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Security Considerations
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Regularly rotate Personal Access Tokens&lt;/li&gt;
&lt;li&gt;Use minimal required permissions for tokens&lt;/li&gt;
&lt;li&gt;Keep SSH private keys secure and backed up&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Team Workflow
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Document authentication methods used by the team&lt;/li&gt;
&lt;li&gt;Standardize on one method when possible&lt;/li&gt;
&lt;li&gt;Provide clear setup instructions for new team members&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The root causes of this problem were multifold:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Incorrect remote repository URL&lt;/strong&gt; - Pointing to wrong user repository&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unstable SSH connection&lt;/strong&gt; - Network environment causing SSH protocol connection failures&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unrelated history records&lt;/strong&gt; - Local and remote repositories created independently, lacking common ancestors&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Final Solution&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Switch to HTTPS protocol for authentication&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;--allow-unrelated-histories&lt;/code&gt; to merge independent histories&lt;/li&gt;
&lt;li&gt;Configure appropriate pull strategy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This systematic troubleshooting and resolution approach can be applied to most Git authentication-related problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/get-started/getting-started-with-git/managing-remote-repositories" rel="noopener noreferrer"&gt;GitHub Documentation - Managing remote repositories&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.github.com/en/authentication/connecting-to-github-with-ssh" rel="noopener noreferrer"&gt;GitHub Documentation - Connecting to GitHub with SSH&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage" rel="noopener noreferrer"&gt;Git Documentation - Git Credential Storage&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;This document is based on actual problem-solving process, applicable to macOS and Linux environments. Windows environment commands may vary slightly.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>troubleshooting</category>
      <category>git</category>
      <category>authentication</category>
    </item>
    <item>
      <title>😵‍💫 Integrating Alibaba DeepSeek AI in a Frontend Project — Why `netlify dev` Breaks Streaming and How to Fix It</title>
      <dc:creator>yao tang</dc:creator>
      <pubDate>Fri, 18 Apr 2025 05:37:23 +0000</pubDate>
      <link>https://dev.to/diana_tang/integrating-alibaba-deepseek-ai-in-a-frontend-project-why-netlify-dev-breaks-streaming-and-3j97</link>
      <guid>https://dev.to/diana_tang/integrating-alibaba-deepseek-ai-in-a-frontend-project-why-netlify-dev-breaks-streaming-and-3j97</guid>
      <description>&lt;p&gt;🧾 Background&lt;/p&gt;

&lt;p&gt;While integrating the &lt;strong&gt;Alibaba Cloud DeepSeek Assistant API&lt;/strong&gt; into a frontend project, I wanted real-time AI responses via &lt;code&gt;fetch&lt;/code&gt; + stream (&lt;code&gt;ReadableStream&lt;/code&gt;). Backend used Express to call DashScope’s streaming endpoint with &lt;code&gt;X-DashScope-SSE: enable&lt;/code&gt;, and the frontend expected to receive incremental AI tokens like a chat assistant.&lt;/p&gt;

&lt;p&gt;This setup &lt;strong&gt;worked perfectly in production&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But in local development with &lt;code&gt;netlify dev&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;❌ &lt;strong&gt;Streaming completely failed&lt;/strong&gt;, frontend received nothing, and eventually crashed with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; net::ERR_EMPTY_RESPONSE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🧨 Problem Summary&lt;/p&gt;

&lt;p&gt;Even though the backend successfully received and printed streaming chunks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;output&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The frontend never got them. Instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;fetch().body.getReader().read()&lt;/code&gt; was never triggered&lt;/li&gt;
&lt;li&gt;The browser hung waiting for data&lt;/li&gt;
&lt;li&gt;Connection dropped with &lt;code&gt;ERR_EMPTY_RESPONSE&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;🔍 Root Cause&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;❌ Suspected Issue&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Backend forgot &lt;code&gt;res.end()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Nope — it's there&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Streaming from DashScope failed&lt;/td&gt;
&lt;td&gt;Nope — chunks are printed in the backend logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;✅ &lt;code&gt;netlify dev&lt;/code&gt; local proxy strips streaming&lt;/td&gt;
&lt;td&gt;✔️ &lt;strong&gt;Yes — this is the real issue&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;The Netlify CLI (&lt;code&gt;netlify dev&lt;/code&gt;) emulates serverless locally, but &lt;strong&gt;its internal proxy does not support chunked transfer encoding&lt;/strong&gt;, which is required for streaming with &lt;code&gt;res.write()&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;✅ Solution: Bypass Netlify CLI, Run Express Locally&lt;/p&gt;

&lt;p&gt;✅ Step 1: Run your backend manually&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ts-node src/server.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Make sure your Express server listens on a custom port (e.g. &lt;code&gt;3001&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.0.0.0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Running at http://localhost:3001&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Step 2: Configure frontend proxy (Vite)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vite.config.ts&lt;/span&gt;
&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;proxy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/chat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:3001&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;changeOrigin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your frontend code still calls &lt;code&gt;/chat&lt;/code&gt;, but under the hood it hits your local Express server instead of the broken &lt;code&gt;netlify dev&lt;/code&gt; proxy.&lt;/p&gt;

&lt;p&gt;✅ Step 3: Make sure your backend properly streams&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;externalRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chunk&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Stream directly to frontend&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;externalRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;end&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;end&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Always close stream&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;💡 Use &lt;code&gt;res.setHeader('Content-Type', 'text/event-stream')&lt;/code&gt; for best results if you’re mimicking SSE.&lt;/p&gt;

&lt;p&gt;✅ Alternative: Deploy to Netlify&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Deployed Netlify Functions &lt;strong&gt;do support streaming&lt;/strong&gt;!&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;netlify deploy &lt;span class="nt"&gt;--prod&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But don't rely on local dev for anything stream-based.&lt;/p&gt;

&lt;p&gt;🧠 Summary&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Streaming Supported?&lt;/th&gt;
&lt;th&gt;Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;netlify dev&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;❌ No&lt;/td&gt;
&lt;td&gt;❌ Never use for streaming/debugging SSE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ts-node&lt;/code&gt; + Express&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Local dev (DeepSeek, OpenAI, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployed Netlify&lt;/td&gt;
&lt;td&gt;✅ Yes&lt;/td&gt;
&lt;td&gt;✅ Production use with DeepSeek or DashScope&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;📝 Takeaway&lt;/p&gt;

&lt;p&gt;If you're building real-time chat UIs, AI copilots, or stream-based assistants using &lt;strong&gt;Alibaba DeepSeek&lt;/strong&gt;, &lt;strong&gt;OpenAI&lt;/strong&gt;, or similar APIs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Don't use &lt;code&gt;netlify dev&lt;/code&gt; during development.&lt;br&gt;&lt;br&gt;
✅ Use Express locally + Vite proxy for a reliable streaming experience.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
  </channel>
</rss>
