| name | debug-extraction |
| description | This skill should be used when the user asks to "debug extraction", "why isn't CSS being extracted", "build plugin not working", "styles missing after build", "analyze AST", or needs to troubleshoot the build-time CSS extraction pipeline. |
Debug Seams CSS Extraction
Troubleshoot build-time CSS extraction issues by tracing through the analysis, extraction, transformation, and generation pipeline.
Extraction Pipeline Overview
The build plugin processes files through four stages:
Source Code → Analyzer → Extractor → Transformer → CSS Generator
↓ ↓ ↓ ↓
AST analysis Static CSS Dynamic vars Final CSS
Quick Diagnostic
Check if File is Being Processed
Add debug logging to plugin config:
Next.js:
const withSeams = require("@artmsilva/seams-next-plugin");
module.exports = withSeams({
include: ["src", "app", "components"],
exclude: ["node_modules"],
})({
webpack: (config, { isServer }) => {
console.log("Processing files with extensions:", [".tsx", ".ts", ".jsx", ".js"]);
return config;
},
});
Vite:
import seams from "@artmsilva/seams-vite-plugin";
export default defineConfig({
plugins: [
seams({
include: ["src"],
exclude: ["node_modules"],
}),
],
});
Verify Stitches Import Detection
The analyzer looks for these import patterns:
import { styled, css } from "@artmsilva/seams-react";
import { createStitches } from "@artmsilva/seams-react";
import * as Stitches from "@artmsilva/seams-react";
import { styled } from "./stitches.config";
import { css } from "../lib/stitches";
Stage-by-Stage Debugging
Stage 1: Analyzer
The analyzer parses source code and finds Seams usage.
Debug with:
import { analyzeSource } from "@artmsilva/seams-plugin-common";
const source = `
import { styled } from '@artmsilva/seams-react';
const Button = styled('button', {
backgroundColor: 'blue',
});
`;
const analysis = analyzeSource(source, "Button.tsx");
console.log("Has Seams import:", analysis.hasStitchesImport);
console.log("Configs found:", analysis.configs.length);
console.log("Usages found:", analysis.usages.length);
for (const usage of analysis.usages) {
console.log("Usage:", {
type: usage.type,
name: usage.name,
start: usage.start,
hasDynamicValues: usage.hasDynamicValues,
});
}
Common issues:
hasStitchesImport: false → Import path not recognized
usages.length === 0 → Seams calls not detected
hasDynamicValues: true → Contains non-static values
Stage 2: Extractor
The extractor converts static usages to CSS rules.
Debug with:
import { analyzeSource, extractCss } from "@artmsilva/seams-plugin-common";
const analysis = analyzeSource(source, "Button.tsx");
const extraction = extractCss(analysis, {
config: {
prefix: "app",
theme: {
colors: { primary: "#0070f3" },
},
},
});
console.log("Rules extracted:", extraction.rules.length);
console.log("Class names:", [...extraction.classNames.entries()]);
for (const rule of extraction.rules) {
console.log("Rule:", {
layer: rule.layer,
selector: rule.selector,
css: rule.css,
});
}
Common issues:
rules.length === 0 → All usages have dynamic values
- Missing theme tokens → Config not passed correctly
- Wrong class names → Hash collision or naming issue
Stage 3: Transformer
The transformer converts dynamic values to CSS variables.
Debug with:
import { analyzeSource, extractCss, transformSource } from "@artmsilva/seams-plugin-common";
const analysis = analyzeSource(source, "Button.tsx");
const extraction = extractCss(analysis, {});
const transformed = transformSource({
analysis,
extraction,
});
console.log("Transformed code:", transformed.code);
console.log("Dynamic variables:", transformed.dynamicVariables);
for (const dynVar of transformed.dynamicVariables) {
console.log("Dynamic var:", {
variableName: dynVar.variableName,
expression: dynVar.expression,
className: dynVar.className,
});
}
Common issues:
- Dynamic variables not created → Expression not detected as dynamic
- Wrong expression captured → AST traversal issue
Stage 4: CSS Generator
The generator produces final CSS with layers and scope.
Debug with:
import { generateFullCss } from "@artmsilva/seams-plugin-common";
const css = generateFullCss(extraction, {
useScope: true,
useLayers: true,
minify: false,
layerPrefix: "stitches",
});
console.log("Generated CSS:\n", css);
Common issues:
- No
@layer → useLayers: false
- No
@scope → useScope: false
- Minified output hard to read → Set
minify: false
Full Pipeline Debug Script
Create debug-extraction.ts:
import { readFileSync } from "fs";
import {
analyzeSource,
extractCss,
transformSource,
generateFullCss,
} from "@artmsilva/seams-plugin-common";
const filename = process.argv[2];
if (!filename) {
console.error("Usage: npx tsx debug-extraction.ts <file>");
process.exit(1);
}
const source = readFileSync(filename, "utf-8");
console.log("=== STAGE 1: ANALYSIS ===");
const analysis = analyzeSource(source, filename);
console.log("Has import:", analysis.hasStitchesImport);
console.log("Usages:", analysis.usages.length);
analysis.usages.forEach((u, i) => {
console.log(` [${i}] ${u.type} "${u.name}" dynamic=${u.hasDynamicValues}`);
});
console.log("\n=== STAGE 2: EXTRACTION ===");
const extraction = extractCss(analysis, {});
console.log("Rules:", extraction.rules.length);
extraction.rules.forEach((r, i) => {
console.log(` [${i}] ${r.layer}: ${r.selector}`);
});
console.log("\n=== STAGE 3: TRANSFORMATION ===");
const transformed = transformSource({ analysis, extraction });
console.log("Dynamic vars:", transformed.dynamicVariables.length);
transformed.dynamicVariables.forEach((v, i) => {
console.log(` [${i}] ${v.variableName} = ${v.expression}`);
});
console.log("\n=== STAGE 4: CSS OUTPUT ===");
const css = generateFullCss(extraction, {
useScope: true,
useLayers: true,
minify: false,
});
console.log(css);
Run with:
npx tsx debug-extraction.ts src/components/Button.tsx
Common Problems and Solutions
Problem: "No Seams import detected"
Cause: Import path doesn't match expected patterns
Solution: Use standard import paths:
import { styled } from "@artmsilva/seams-react";
Problem: "Usage has dynamic values, skipping extraction"
Cause: Non-literal values in style object
Solution: Make values static or let them become CSS variables:
const Box = styled("div", {
margin: dynamicValue,
});
const Box = styled("div", {
margin: "16px",
});
Problem: "Token not found in theme"
Cause: Theme config not passed to extractor
Solution: Ensure config is provided:
const extraction = extractCss(analysis, {
config: {
theme: {
colors: { primary: "#0070f3" },
},
},
});
Problem: "CSS not appearing in build output"
Causes:
- File not in include path
- File in exclude path
- Build plugin not configured
Solution: Check plugin config paths match your file structure.
Additional Resources
See references/ast-patterns.md for AST detection patterns.