iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Bootcamp

A guided 60-minute bootcamp that converts a legacy SCSS stylesheet to modern modules, introduces a token map, and ships a Stylelint config that prevents drift. Run it on a real branch in an hour.

A 60-minute SCSS modernisation bootcamp

EXAMPLE
# ===== Bootcamp objectives =====
# 1. Replace @import with @use / @forward
# 2. Introduce a token map and a token() function
# 3. Add a respond-to mixin from a breakpoints map
# 4. Lock in conventions with Stylelint + a CI rule

# ===== 0-5 min: pick the target stylesheet =====
# One feature folder. Counts < 1000 lines so you finish in the hour.
# Open the entry point styles.scss (or app.scss) in VS Code.

# ===== 5-20 min: migrate @import -> @use =====
npm i -g sass-migrator
sass-migrator module --migrate-deps styles.scss
git diff   # review

# Things to fix manually
# - @use 'tokens' as t;  variables become t.$primary
# - Global functions are now sass:color, sass:math, sass:list, sass:map
# - Configuration of imported modules uses 'with ($primary: red)'

# ===== 20-35 min: introduce design tokens as data =====
# Create _tokens.scss
cat > _tokens.scss <<'EOF'
@use 'sass:map';

$tokens: (
  'color': (
    'brand': (500: #2563eb, 600: #1e40af),
    'gray':  (50: #f8fafc, 900: #0f172a),
  ),
  'space': ('xs': .25rem, 'sm': .5rem, 'md': 1rem, 'lg': 2rem, 'xl': 4rem),
  'radius': ('sm': 4px, 'md': 8px, 'lg': 16px, 'pill': 999px),
);

@function token($path...) {
  $v: $tokens;
  @each $k in $path { $v: map.get($v, $k); }
  @if $v == null { @error 'Unknown token: #{$path}'; }
  @return $v;
}
EOF

# Replace one-off hex codes / pixel values with token() calls in the migrated file.
# Aim for 80% replaced; the last 20% are usually genuine one-offs.

# ===== 35-50 min: add a responsive breakpoint mixin =====
cat >> _tokens.scss <<'EOF'

$bp: ('sm': 480px, 'md': 768px, 'lg': 1024px, 'xl': 1280px);

@mixin respond-to($name) {
  @if not map.has-key($bp, $name) { @error 'Unknown bp #{$name}'; }
  @media (min-width: map.get($bp, $name)) { @content; }
}
EOF

# Replace ad-hoc @media (min-width: 768px) blocks with @include respond-to('md').

# ===== 50-60 min: enforce the new style with Stylelint =====
npm i -D stylelint stylelint-config-standard-scss stylelint-config-recess-order

# .stylelintrc.json
{
  "extends": ["stylelint-config-standard-scss", "stylelint-config-recess-order"],
  "rules": {
    "at-rule-disallowed-list": ["import"],            // ban legacy @import
    "scss/at-import-no-partial-leading-underscore": true,
    "scss/dollar-variable-pattern": "^[a-z][a-zA-Z0-9]+$",
    "declaration-block-no-redundant-longhand-properties": null,
    "unit-allowed-list": ["px", "rem", "%", "em", "s", "ms", "deg", "vh", "vw"],
    "color-no-hex": [true, { "message": "Use token() instead of literal hex." }]
  },
  "overrides": [{ "files": ["_tokens.scss"], "rules": { "color-no-hex": null } }]
}

# Add to package.json
# {
#   "scripts": {
#     "lint:scss": "stylelint 'resources/scss/**/*.scss'",
#     "lint:scss:fix": "stylelint --fix 'resources/scss/**/*.scss'"
#   }
# }

# CI step
# - name: stylelint
#   run: npm run lint:scss

# ===== Post-bootcamp =====
# - Open a PR titled 'SCSS migration to modules + tokens'
# - Write the conventions in CONTRIBUTING.md so the next contributor follows them
# - Plan a follow-up to migrate another feature folder next week

# ===== Common surprises during migration =====
# - Variables that LOOK global were leaking across files; @use scope makes
#   the dependency explicit and refactors easier
# - Division ($x / 2) now warns -> rewrite as 'math.div($x, 2)' or '$x * .5'
# - 'darken'/'lighten' deprecation -> use color.adjust($c, $lightness: -10%)

Why it matters

Run sass-migrator first, before any hand edits. It rewrites 90% of the migration mechanically and surfaces the few hand-fix cases in a clean diff — the alternative is a week of slow conversion where every commit risks visual regressions because the SCSS module boundary changes in subtle ways.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
// 30-day plan in the lesson body.
Try it Yourself »

Discussion

Loading…