VS Code

Status: 🟩 COMPLETE (🟦 LIVING — VS Code ships changes monthly) Last updated: 2026-06-19 Plain-English tagline: Microsoft’s free code editor — the dominant tool for modern web development, with built-in TypeScript, terminal, debugger, and Git, plus a massive extension ecosystem that handles almost any specific need.


In plain English

Visual Studio Code (universally called VS Code, sometimes abbreviated to vscode) is a code editor: a program for reading, writing, and navigating code. It’s NOT an IDE in the heaviest sense (no built-in compilers, no opinionated project structure), but it’s much more than a plain text editor. It comes with:

  • Syntax highlighting for ~100 languages out of the box
  • IntelliSense (autocomplete) that’s exceptional for TypeScript/JavaScript
  • Built-in terminal
  • Built-in Git client
  • Built-in debugger
  • An extension marketplace with ~50,000 published extensions

It’s free, cross-platform (Windows, macOS, Linux), and Microsoft updates it monthly. Since ~2018, it has been the dominant code editor in JavaScript/TypeScript-land. The 2025 Stack Overflow Developer Survey shows ~75% of web developers using it daily.

The closest competitors in 2026:

  • Cursor — a fork of VS Code with deeper AI integration (chat, multi-file edits, agentic flows). Free tier; paid Pro tier. Increasingly common among AI-heavy developers.
  • Zed — a newer, faster, Rust-based editor with collaborative features. Smaller ecosystem.
  • JetBrains WebStorm / IntelliJ — paid; better refactoring; heavier; favored in enterprise.
  • Neovim — terminal-based; for terminal natives.

For a non-programmer building modern webapps with AI assistance (George’s profile), Cursor or VS Code are the right defaults — both ship with great AI workflows; Cursor is more polished, VS Code is more universal.

This entry focuses on VS Code. Most of what’s here applies to Cursor too (since it’s a VS Code fork).


Why it matters

Three concrete reasons VS Code is foundational:

  1. It’s the editor every tutorial assumes. If you’re following a Next.js / React / TypeScript tutorial in 2026, the screenshots and shortcuts are VS Code. Familiarity saves friction.

  2. TypeScript support is unrivalled. Microsoft makes both VS Code and TypeScript — IntelliSense, “Go to Definition,” refactoring, and inline diagnostics are deeply integrated. The same code in a plain editor would lose much of its safety.

  3. The extension ecosystem covers everything. Specific frameworks, tools, languages, linters, formatters, debuggers, AI assistants — each has an extension. Most are free and well-maintained.

The trade-off: VS Code is heavier than a plain text editor and lighter than a full IDE. For very large codebases (~1M+ lines), it can feel sluggish. For typical webapp projects (10k-100k lines), it’s responsive and rich.


The mental model

Think of VS Code as four overlapping layers:

  1. The editor — where you read and write code
  2. The activity bar — left side, with Explorer (files), Search, Source Control, Run/Debug, Extensions
  3. The panel — bottom, with Terminal, Problems (errors/warnings), Output, Debug Console
  4. The status bar — bottom edge, with Git branch, errors count, language, line/column

Most daily work happens in the editor + terminal + Git panel. Everything else is one click away.

The two killer shortcuts:

  • Cmd/Ctrl+P — quick open by filename. Type any part of a filename; pick from the list. Faster than navigating the Explorer tree.
  • Cmd/Ctrl+Shift+P — command palette. Every command in VS Code (and every extension’s commands) is searchable here. “Toggle dark mode,” “Format document,” “Git: Commit,” “Reload window,” etc.

Master those two shortcuts and you replace 80% of mouse usage.


A solid baseline settings.json

VS Code is configurable. Settings live in Code → Preferences → Settings (macOS) or File → Preferences → Settings (Windows/Linux). The JSON view (Preferences: Open User Settings (JSON) from the command palette) is where power users live.

A practical baseline for modern Next.js / TypeScript work:

{
  // Editor
  "editor.fontSize": 14,
  "editor.fontFamily": "'JetBrains Mono', 'Geist Mono', Menlo, Consolas, monospace",
  "editor.fontLigatures": true,
  "editor.lineHeight": 1.6,
  "editor.tabSize": 2,
  "editor.insertSpaces": true,
  "editor.minimap.enabled": false,
  "editor.bracketPairColorization.enabled": true,
  "editor.guides.bracketPairs": "active",
  "editor.cursorBlinking": "smooth",
 
  // Formatting on save
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit",
    "source.organizeImports": "explicit"
  },
 
  // Files
  "files.trimTrailingWhitespace": true,
  "files.insertFinalNewline": true,
  "files.eol": "\n",
  "files.autoSave": "onFocusChange",
  "files.exclude": {
    "**/.next": true,
    "**/node_modules": true
  },
 
  // Terminal
  "terminal.integrated.fontSize": 13,
  "terminal.integrated.fontFamily": "'JetBrains Mono', monospace",
  "terminal.integrated.defaultProfile.windows": "PowerShell",
  "terminal.integrated.defaultProfile.osx": "zsh",
 
  // TypeScript
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true,
  "typescript.preferences.importModuleSpecifier": "non-relative",
  "typescript.updateImportsOnFileMove.enabled": "always",
  "typescript.inlayHints.parameterNames.enabled": "literals",
 
  // Search
  "search.exclude": {
    "**/.next": true,
    "**/node_modules": true,
    "**/dist": true,
    "**/build": true,
    "**/.git": true,
    "**/coverage": true
  },
 
  // Git
  "git.autofetch": true,
  "git.confirmSync": false,
  "git.enableSmartCommit": true,
 
  // Theme
  "workbench.colorTheme": "Default Dark Modern",
  "workbench.iconTheme": "vscode-icons"
}

A few highlights:

  • editor.formatOnSave: true — every save runs Prettier. Code is always formatted.
  • source.fixAll.eslint — auto-fixes ESLint issues on save (unused imports, etc.).
  • source.organizeImports — sorts imports automatically.
  • typescript.tsdk: node_modules/typescript/lib — uses the project’s TypeScript version, not VS Code’s bundled one. Critical: ensures the editor’s diagnostics match tsc in CI.
  • files.eol: "\n" — Unix line endings (LF). On Windows, default is CRLF — this normalizes.
  • search.exclude — speeds up project-wide search by ignoring build artifacts.

This setup is roughly equivalent to a Bible Quest-style project default.


The extensions that actually pay off

VS Code has ~50,000 extensions. You need ~10. The high-value list:

ExtensionWhat it does
Prettier - Code formatterThe dominant formatter; works with editor.formatOnSave
ESLintIn-editor lint warnings/errors
Tailwind CSS IntelliSenseAutocomplete + hover docs for Tailwind classes
GitLensGit integration on steroids (blame inline, commit history per line)
Error LensShows error/warning messages inline on the offending line
Code Spell CheckerSpell-check in code (catches typos in variable names, comments)
Pretty TypeScript ErrorsReformats verbose TS errors into something readable
Auto Rename TagRename one side of an HTML/JSX tag, the other follows
vscode-iconsDistinct file-type icons in the Explorer
GitHub Pull Requests and IssuesView / review / create PRs in VS Code

For AI assistance:

  • GitHub Copilot — Microsoft’s AI assistant; inline suggestions + chat
  • Claude Dev / Continue / Cline — Claude / OpenAI / open-model alternatives
  • Cursor — separate editor, but worth knowing about as an alternative

For specific stacks, add:

  • Supabase VS Code extension — schema browsing, SQL execution
  • Prisma — if using Prisma
  • MDX — if writing MDX content
  • YAML — for .github/workflows/*.yml files

Avoid extension bloat. Every extension is a startup cost. Pick the ones you actually use; uninstall the rest periodically.


The shortcuts worth memorizing

Cmd/Ctrl + P              Quick open file by name
Cmd/Ctrl + Shift + P      Command palette
Cmd/Ctrl + Shift + F      Search across the project
Cmd/Ctrl + ,              Settings
Cmd/Ctrl + B              Toggle file explorer
Cmd/Ctrl + `              Toggle integrated terminal
Cmd/Ctrl + J              Toggle bottom panel
Cmd/Ctrl + /              Toggle line comment
Cmd/Ctrl + D              Add cursor at next occurrence (multi-cursor)
Cmd/Ctrl + Shift + L      Add cursor at ALL occurrences
Cmd/Ctrl + L              Select current line
Alt + ↑/↓                 Move line up/down
Shift + Alt + ↑/↓         Copy line up/down
Alt + Click               Add cursor at click position
Cmd/Ctrl + F              Find in file
Cmd/Ctrl + H              Find + Replace in file
F2                        Rename symbol (rename everywhere it's used)
F12                       Go to definition
Cmd/Ctrl + Click          Same as F12
Alt + F12                 Peek definition (popup, no navigation)
Shift + F12               Find all references
Cmd/Ctrl + K, Z           Zen mode (focus mode)
Cmd/Ctrl + K, S           Open keyboard shortcuts

The 4-5 you’ll use constantly: Cmd+P, Cmd+Shift+P, Cmd+F, Cmd+/, F2 (rename).


Workspaces & multi-root projects

A workspace in VS Code is just “the folder you opened.” code /path/to/project opens that folder as the workspace.

For more advanced setups, a .code-workspace file can include multiple folders:

{
  "folders": [
    { "path": "./apps/web" },
    { "path": "./apps/admin" },
    { "path": "./packages/shared" }
  ],
  "settings": {
    "editor.tabSize": 2
  }
}

Opening this .code-workspace shows all three folders in one window. Useful for monorepos.

For typical solo projects, just open the project folder; you don’t need a workspace file.


Project-level settings

Settings can live in .vscode/settings.json inside your project. These OVERRIDE user-level settings for that project specifically.

A typical .vscode/settings.json for a Next.js project:

{
  "editor.formatOnSave": true,
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.codeActionsOnSave": {
    "source.fixAll.eslint": "explicit"
  },
  "typescript.tsdk": "node_modules/typescript/lib",
  "tailwindCSS.experimental.classRegex": [
    ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
    ["cx\\(([^)]*)\\)", "(?:'|\"|`)([^']*)(?:'|\"|`)"]
  ]
}

Commit .vscode/settings.json to git. Every contributor (and Claude Code) gets the same baseline.

You can also commit .vscode/extensions.json recommending specific extensions:

{
  "recommendations": [
    "esbenp.prettier-vscode",
    "dbaeumer.vscode-eslint",
    "bradlc.vscode-tailwindcss",
    "eamodio.gitlens"
  ]
}

When someone opens the project, VS Code prompts them to install missing recommended extensions. A small UX win for team projects.


Integrated terminal

VS Code’s terminal is a full shell embedded in the window. Open with Ctrl+` (backtick).

What you can do:

  • Run npm run dev and see output without leaving the editor
  • Split terminals (multiple shells side by side)
  • Pin one terminal for the dev server, another for git commands
  • Set the default shell per OS in settings
  • Switch between PowerShell, Bash, zsh, etc. via the dropdown

The terminal respects your project’s .envrc (if you use direnv) and PATH overrides. It’s the same as opening a separate Terminal app and cd-ing to your project — just integrated.

For Windows specifically: the default profile is PowerShell. Git Bash, WSL bash, and cmd are all available via the profile dropdown. See Windows dev environment.


Source control (Git) in VS Code

The Source Control panel (Cmd/Ctrl+Shift+G) is a graphical Git client:

  • See changed files
  • Stage / unstage hunks (chunks of changes) inline
  • View diffs side-by-side
  • Commit with a message
  • Push, pull, fetch
  • View branch history
  • Resolve merge conflicts with built-in 3-way merge view

For most operations, the panel is faster than the terminal. For complex git surgery (rebases, cherry-picks, reflog), use the terminal.

GitLens (extension) supercharges this: inline blame (“this line by George, 3 weeks ago, commit abc123”), file history navigation, comparison views.


Debugging

VS Code has a built-in JavaScript/TypeScript debugger. Set breakpoints by clicking the gutter (left of line numbers). Hit F5 to start debugging.

For Next.js specifically, the debug configuration in .vscode/launch.json:

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Next.js: debug full stack",
      "type": "node-terminal",
      "request": "launch",
      "command": "npm run dev",
      "serverReadyAction": {
        "pattern": "started server on .+, url: (https?://.+)",
        "uriFormat": "%s",
        "action": "debugWithChrome"
      }
    }
  ]
}

Hit F5. Next.js starts, Chrome opens to localhost:3000, breakpoints work in both server and client code. The integration is best-in-class.

In practice, many AI-era developers don’t use the debugger as heavily as they used to — console.log + reading the output is enough for most cases. But for tricky bugs, the debugger is still the right tool.


A concrete example: opening Bible Quest in VS Code

cd C:\Users\georg\st-marks-bible-quest
code .

code . opens the current directory in VS Code. (Requires the code CLI to be installed — on macOS, run “Shell Command: Install ‘code’ command in PATH” from the command palette.)

VS Code opens. Activity bar shows file explorer. Bottom shows terminal (run npm run dev). Right shows the file currently open. Status bar at the bottom shows the Git branch.

Type Cmd+P, type home, hit Enter — opens app/page.tsx. Cmd+/, the line comments out. F2 on a function name, type a new name, hit Enter — renames everywhere it’s referenced. Cmd+Click on a <Button> component — jumps to its definition. Cmd+Shift+F, type “supabase”, see every place “supabase” appears across the project.

That’s an hour into using VS Code. The rest is muscle memory and gradual extension adoption.


Cursor — the AI-native fork

Cursor is a fork of VS Code optimized for AI workflows. Settings, extensions, and shortcuts are nearly identical. The differences:

  • Built-in Composer (multi-file AI edits)
  • Built-in Chat (Cmd+L) for asking questions about code
  • Tab-complete-aware AI that uses Claude / GPT models for inline suggestions
  • Agent mode — let AI run multi-step tasks
  • Free tier + Pro tier ($20/mo)

Cursor’s value prop: “VS Code but with AI baked deeper.” For developers using AI heavily (which describes George’s workflow), Cursor is often more frictionless than VS Code + Copilot extension.

The catch: Cursor is closed-source (only the VS Code fork base is open). Privacy / telemetry trade-offs differ from VS Code. Settings sync separately.

Either tool works. Pick based on workflow preference; switching between them is easy.


Common gotchas

  • Don’t forget typescript.tsdk: node_modules/typescript/lib. Without it, VS Code uses ITS bundled TypeScript version, not your project’s. Diagnostics will diverge from CI.

  • Extensions slow down startup. A laptop with 50 extensions installed takes noticeably longer to open files. Audit periodically; uninstall the unused.

  • Workspace settings override user settings. A .vscode/settings.json in a project wins. Be aware when settings feel “wrong” — check the workspace file first.

  • Format on save can fight with itself. If TWO formatters compete (Prettier vs Beautify, say), your file may be reformatted twice on each save. Set editor.defaultFormatter explicitly.

  • The “Save Without Formatting” command exists. Cmd+K Cmd+S — useful when you genuinely don’t want Prettier to touch a file.

  • code command not in PATH. On macOS, install via command palette. On Windows, the installer asks; if you skipped it, reinstall or set PATH manually.

  • Git Bash and PowerShell are different shells. A npm install works in both, but bash-specific commands (export, heredocs) don’t work in PowerShell, and vice versa. See PowerShell vs Bash.

  • VS Code’s “Open Recent” can leak repos. If you open multiple projects, the recent list grows. Manually prune for privacy.

  • The Explorer file watcher can hammer disks. Large node_modules cause excessive file-watcher events. The files.watcherExclude setting prevents this; modern defaults handle it, but old configs may not.

  • GitLens is amazing AND noisy. Default settings show inline blame on every line. Many users disable inline blame and keep only the “blame this line” hover. Tune to taste.

  • Multiple TypeScript versions in one workspace = drama. If two packages in a monorepo declare different TypeScript versions, VS Code picks one. Use a workspace-level TypeScript version.

  • Auto-saving + format-on-save is opinionated. Saves trigger format which can shift cursor position mid-edit. files.autoSave: "onFocusChange" (only save when leaving the file) is a popular compromise.

  • The integrated terminal is NOT exactly the same as your system terminal. PATH, env vars, profile scripts may differ. Set terminal.integrated.env.* explicitly for known differences.

  • Long files slow down IntelliSense. A 5,000-line component slows everything. Refactor into smaller files.

  • Crash recovery is good, not perfect. VS Code recovers most unsaved work; not always. Save frequently; commit often.

  • Live Share (Microsoft’s pair-programming feature) is excellent for collaborative debugging. Underused.

  • The “Welcome” tab can be turned off. workbench.startupEditor: "none" removes it.

  • Theme matters for long hours. Dark themes reduce eye strain in low light. Default Dark Modern (2023+) is a good neutral choice. Avoid “fun” themes for production work — color choices should be informative, not decorative.

  • Font choice matters for code reading. Monospace fonts with ligatures (JetBrains Mono, Fira Code, Geist Mono) make =>, !=, &&, etc. render as nicer glyphs. Highly recommended.

  • The minimap (right side) is divisive. Useful for some, distracting for others. Disable with editor.minimap.enabled: false if it bothers you.

  • The “breadcrumbs” bar (top of editor) is useful for jumping around large files. Show with breadcrumbs.enabled: true.

  • Settings sync is built in. Sign in with GitHub/Microsoft — your settings, extensions, keybindings sync across machines.

  • The “Restricted Mode” prompt appears when you open a folder you’ve never opened. It limits some extension behavior for security. Trust the folder if it’s your own code.

  • AI-generated code may not match your formatting. Prettier on save fixes most; some AI generations include intentional formatting (e.g. multi-line function signatures) that fight Prettier. Adjust Prettier config rather than the AI output.

  • Settings JSON has comments. VS Code’s JSON parser accepts // and /* */ comments. Standard JSON doesn’t. This sometimes confuses outside tools that read VS Code settings.

  • Extension marketplace has malicious entries. Rare but happens. Stick to popular, verified extensions; check publisher and download counts.

  • code-server and vscode.dev let you run VS Code in a browser. Useful for remote development; same UI, fewer extensions.

  • Tabs vs spaces battles are settled by Prettier in modern projects. Spaces (2) is the JS/TS default. Pick once; don’t relitigate.

  • AI tools sometimes leak project-specific paths into edits. Watch for hardcoded C:\Users\... paths in generated code. Use environment-relative paths.


See also


Sources