Validating React Components Using AST-Based Validators in Stitch-Skills
Stitch-Skills provides command-line validators that parse React components using @swc/core to enforce architectural standards like Props interface naming and theme adherence through static AST analysis.
The google-labs-code/stitch-skills repository ships with dedicated validation scripts for the React Components and React Native skill packs. These tools perform static analysis on TypeScript files to catch structural violations—such as missing Props interfaces or hard-coded color values—before code reaches production.
How the AST Validators Work
The validators generate an Abstract Syntax Tree (AST) from component source code using await swc.parse(code, { syntax: "typescript", tsx: true }). A recursive walk function performs a depth-first traversal of the tree, inspecting node types and properties while ignoring the span property (which contains location metadata).
All checks execute purely through AST inspection without type-checking or runtime execution. After traversal completes, the validator aggregates violations and exits with status 0 for valid components or 1 for invalid ones, enabling CI pipeline integration.
Validation Rules for React Components
The validator enforces specific architectural patterns by targeting distinct AST node types.
Props Interface Naming
The tool searches for TsInterfaceDeclaration nodes where the identifier ends with Props.
- Pass: "Props declaration found."
- Fail: "Missing Props interface (must end in 'Props')"
For React Native components, the validator additionally checks whether the interface is a child of an ExportDeclaration, requiring the Props interface to be exported.
Hard-Coded Colour Detection
The validator flags StringLiteral nodes matching hex patterns /#[0-9A-Fa-f]{3,8}\b/ or RGB/RGBA patterns /^rgba?\(/.
- Pass: "No hardcoded colour values found."
- Fail: "Found X hardcoded colours. Use
theme.tsinstead."
React Native Specific Rules
React Native components face additional constraints:
- Exported Props Interface: Requires
TsInterfaceDeclarationto be exported or warns "Props interface found but not exported" - HTML Element Usage: Scans
JSXOpeningElementnodes against a whitelist of HTML tags (div,span,p, etc.) and fails if found, requiring replacement with React Native primitives
Class Name Validation (Web Only)
For React web components, the validator examines JSXAttribute nodes with name className, checking their values against the hex color regex to prevent inline style hard-coding.
Running the Validators
Execute validation from the project root using Node.js:
# Validate a React web component
node plugins/stitch-build/skills/react-components/scripts/validate.js src/components/Button.tsx
# Validate a React Native component
node plugins/stitch-build/skills/react-native/scripts/validate.js src/components/Card.tsx
Example Output
Valid component:
--- Validation for: Button.tsx ---
✅ Props declaration found.
✅ No hardcoded hex values found.
✨ COMPONENT VALID.
Invalid component:
--- Validation for: Card.tsx ---
FAIL: Missing Props interface (must end in 'Props' and be exported).
FAIL: Found 2 hardcoded colours. Use theme.ts instead.
FAIL: Found HTML elements: div, img. Replace with React Native components.
VALIDATION FAILED.
Implementation Details
The validation logic resides in two primary entry points:
plugins/stitch-build/skills/react-components/scripts/validate.js– Web-focused validationplugins/stitch-build/skills/react-native/scripts/validate.js– React Native validation with additional export and HTML checks
Both scripts use the same core traversal engine. The walk function recursively visits each AST node, applying rule-specific predicates to node types like TsInterfaceDeclaration, StringLiteral, and JSXOpeningElement. Violations accumulate in an array and render as structured console output after traversal completes.
Summary
- AST-based validation in Stitch-Skills uses @swc/core to parse TypeScript/TSX without execution.
- Props interfaces must end with "Props" and be exported (React Native requirement).
- Colour values must reference theme files; hex and rgba literals trigger failures.
- React Native components cannot use HTML elements like
divorspan. - Exit codes (0 or 1) enable integration with CI/CD pipelines for automated quality gates.
Frequently Asked Questions
What is AST-based validation?
AST-based validation analyzes source code by parsing it into an Abstract Syntax Tree—a hierarchical representation of the code's structure. This approach allows tools to inspect component architecture, naming conventions, and style patterns without executing the code or performing full type-checking.
How does the validator detect hard-coded colors?
The validator scans StringLiteral AST nodes using regular expressions: /#[0-9A-Fa-f]{3,8}\b/ for hex codes and /^rgba?\(/ for RGB/RGBA values. When these patterns match attribute values—particularly in className or style props—the validator flags them as violations requiring theme reference migration.
What distinguishes the React and React Native validators?
While both share the core AST traversal engine, the React Native validator (plugins/stitch-build/skills/react-native/scripts/validate.js) enforces additional rules: it requires Props interfaces to be exported via ExportDeclaration nodes and prohibits HTML elements in JSXOpeningElement tags. The web validator (plugins/stitch-build/skills/react-components/scripts/validate.js) focuses on interface naming and className color detection.
Can these validators run in CI pipelines?
Yes. The validators exit with status code 0 when components pass all checks and 1 when violations exist. This design allows build systems to halt deployments when components violate architectural standards, ensuring consistent code quality across automated workflows.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →