5 min read
On this page

Snippets & Templates

Stop Typing Boilerplate

You write the same patterns dozens of times a week. A new test file needs the same import block, describe block, and basic structure every time. A new React component needs the same function signature, export, and type definition. An error handling block follows the same try/catch/log pattern across your entire codebase.

Every time you type this boilerplate from scratch, two things happen. First, you waste time on text that carries zero intellectual value — the structure is predetermined, only the specifics change. Second, you introduce inconsistency. The boilerplate you type on Tuesday morning when you're fresh looks subtly different from what you type on Friday afternoon when you're tired. Import orders vary, naming conventions drift, error handling patterns diverge.

Snippets eliminate both problems. You define the pattern once, with placeholders for the parts that change, and invoke it with a short trigger. The boilerplate is instant and perfectly consistent.

How Snippets Work

Every major editor supports snippets with the same basic mechanics:

  1. You type a trigger prefix (e.g., tst)
  2. The editor suggests the snippet from autocomplete
  3. You press Tab to expand it
  4. The cursor lands on the first placeholder
  5. You type the value for that placeholder
  6. You press Tab to jump to the next placeholder
  7. Repeat until done

The snippet body uses a simple syntax for placeholders, defaults, and cursor positions:

$1, $2, $3        Numbered tab stops (cursor jumps to these in order)
${1:defaultValue}  Tab stop with a default value
$0                 Final cursor position
${1|one,two,three|} Choice menu at a tab stop

VS Code snippet syntax

{
  "Test Block": {
    "prefix": "tst",
    "scope": "typescript,javascript",
    "body": [
      "describe('${1:subject}', () => {",
      "  it('should ${2:behavior}', () => {",
      "    $0",
      "  });",
      "});"
    ]
  }
}

JetBrains uses live templates with $VARIABLE$ syntax, and Neovim has LuaSnip. The syntax varies across editors but the concept is universal: trigger, body with placeholders, tab between them.

High-Value Snippet Categories

Test scaffolding

These are the highest-ROI snippets because test files are extremely repetitive.

# Trigger: tfile (test file scaffold)
# Expands to:

import { describe, it, expect } from 'vitest';
import { [subject] } from '../[path]';

describe('[subject]', () => {
  describe('[method]', () => {
    it('should [behavior]', () => {
      [cursor]
    });
  });
});
# Trigger: it (single test case)
# Expands to:

it('should [behavior]', () => {
  // Arrange
  [cursor]

  // Act

  // Assert
});
# Trigger: ite (test with expected error)
# Expands to:

it('should throw when [condition]', () => {
  expect(() => {
    [cursor]
  }).toThrow([errorMessage]);
});

Component patterns

# Trigger: rfc (React functional component)
# Expands to:

interface [Name]Props {
  [cursor]
}

export function [Name]({ }: [Name]Props) {
  return (
    <div>
      
    </div>
  );
}

Error handling

# Trigger: try (try/catch block)
# Expands to:

try {
  [cursor]
} catch (error) {
  logger.error('[context] failed', { error, [details] });
  throw error;
}

Function patterns

# Trigger: afn (async function)
# Expands to:

async function [name]([params]): Promise<[returnType]> {
  [cursor]
}

Logging

# Trigger: cl (console.log with label)
# Expands to:

console.log('[label]:', [variable]);

Building Language-Specific Snippet Sets

The snippets above are JavaScript/TypeScript examples, but the same categories apply to every language. Here's what a Go engineer's snippet set might look like:

# Trigger: iferr (Go error handling)
if err != nil {
    return [zeroValue], fmt.Errorf("[context]: %w", err)
}

# Trigger: httph (Go HTTP handler)
func [name]Handler(w http.ResponseWriter, r *http.Request) {
    [cursor]
}

# Trigger: trun (Go table-driven test)
tests := []struct {
    name string
    [fields]
}{
    {
        name: "[testName]",
        [cursor]
    },
}
for _, tt := range tests {
    t.Run(tt.name, func(t *testing.T) {
        
    })
}

And for Python:

# Trigger: def (typed function)
def [name]([params]) -> [returnType]:
    """[docstring]"""
    [cursor]

# Trigger: cls (class with init)
class [Name]:
    """[docstring]"""
    
    def __init__(self, [params]) -> None:
        [cursor]

# Trigger: test (pytest test function)
def test_[name]([fixtures]):
    # Arrange
    [cursor]
    
    # Act
    
    # Assert

Project-Level Templates

Snippets handle boilerplate within a file. Templates handle boilerplate at the file level — generating entire files with the right structure.

VS Code file templates

VS Code doesn't have built-in file templates, but several extensions provide them. You can also achieve this with a simple shell script:

#!/usr/bin/env bash
set -euo pipefail

# new-component.sh - Create a new React component with test file
NAME="$1"
DIR="src/components/$NAME"

mkdir -p "$DIR"

cat > "$DIR/$NAME.tsx" << EOF
interface ${NAME}Props {

}

export function $NAME({  }: ${NAME}Props) {
  return (
    <div>

    </div>
  );
}
EOF

cat > "$DIR/$NAME.test.tsx" << EOF
import { render, screen } from '@testing-library/react';
import { $NAME } from './$NAME';

describe('$NAME', () => {
  it('should render', () => {
    render(<$NAME />);
  });
});
EOF

cat > "$DIR/index.ts" << EOF
export { $NAME } from './$NAME';
EOF

echo "Created component: $DIR"

Run new-component UserProfile and you get three properly structured files in seconds.

For teams, tools like Plop.js formalize template generation with interactive prompts and consistent output. This ensures every team member generates files with the same structure, naming conventions, and patterns.

Managing Your Snippet Collection

Start small

Don't create 50 snippets on day one. Start with the 5 patterns you type most frequently. Use them for a week. Then add 5 more. A collection built from actual need is worth far more than one built from imagination.

Use consistent triggers

Develop a naming convention for your triggers so you can predict them without checking:

Convention:     Category abbreviation + specific type
Test snippets:  t + type   (tst = test, tfile = test file, trun = test run)
Functions:      f + type   (fn = function, afn = async function)
Components:     c + type   (rfc = react functional component)
Logging:        l + type   (cl = console.log, le = log error)

Keep snippets in version control

Store your snippet definitions in your dotfiles repository. In VS Code, user snippets live in:

# macOS
~/Library/Application Support/Code/User/snippets/

# Linux
~/.config/Code/User/snippets/

Symlink these from your dotfiles repo so they're backed up and portable.

Audit periodically

Every few months, review your snippets. Remove ones you never use. Update ones that have drifted from your team's current patterns. Add ones for new patterns that have become repetitive.

Common Pitfalls

Creating snippets for things you rarely type. The overhead of maintaining a snippet isn't justified for patterns you use once a week. Focus on patterns you type multiple times per day.

Making snippets too complex. A snippet with 15 tab stops and complex logic is harder to use than typing the code manually. Keep snippets simple — they should handle the structural boilerplate while you fill in the meaningful parts.

Not sharing useful snippets with your team. If the whole team types the same error handling pattern, that should be a project-level snippet in the repo, not 8 individual copies with slight variations.

Forgetting snippets exist. If you create a snippet and then keep typing the pattern manually out of habit, the snippet is wasted. When you create a new snippet, use it immediately and deliberately for the first few days until it's in your muscle memory.

Over-templating. Not everything needs a template. If a file type has substantial variation between instances, a template might impose unnecessary structure. Templates work best for files that are 70%+ identical every time.

Key Takeaways

Snippets eliminate repetitive typing and enforce consistency. The time savings compound: a snippet you use 10 times a day saves 30+ hours per year.

Start with test scaffolds, error handling, and function signatures — these are the highest-frequency boilerplate patterns in most codebases.

File-level templates extend the concept to entire files. Use shell scripts for personal templates and tools like Plop for team-wide generation.

Keep snippet triggers short and predictable. A naming convention lets you guess the trigger for a snippet you haven't used in weeks.

Build your collection gradually from actual need. Five snippets you use daily are worth more than fifty you forget about.