DEV Community

Cover image for How UIQuarter analyzes UI codebases and what it finds
Fuat Keleş
Fuat Keleş

Posted on

How UIQuarter analyzes UI codebases and what it finds

I've been working on a CLI tool called UIQuarter that does static analysis on UI codebases. It uses AST parsing to understand component structures, map dependencies, detect styling patterns, and find architectural issues. Then it can generate context files for AI coding tools, but the analysis itself is useful on its own.

I wanted to write about what the tool actually detects and how, since "static analysis for UI codebases" is pretty vague.

What it analyzes

UIQuarter has 20 analyzers. When you run uiquarter init on a project, here's what happens under the hood.

Component detection

The ComponentAnalyzer uses ts-morph to parse the AST of every file. For React, it finds functional components by looking for functions that return JSX. For each one it extracts:

  • Component name and file path
  • Props (with TypeScript types if available)
  • Hooks used (useState, useEffect, custom hooks)
  • Whether it's a default or named export

On Vue it parses Single File Components — <script setup> and Options API. On Svelte it parses .svelte files. Angular gets special treatment for decorators (@Component, @Injectable, etc.).

The point isn't just listing files. It's understanding what each component is — what it accepts, what it depends on, where it lives.

Dependency graph

The DependencyAnalyzer builds a graph with typed edges:

  • Render edges: Component A renders Component B in its JSX
  • Hook edges: Component A uses a hook exported from module B
  • HOC edges: Component A is wrapped by a higher-order component from B
  • Provider edges: Component A provides context consumed by Component B

This graph is what powers the query commands:

uiquarter query deps Dashboard      # what Dashboard depends on
uiquarter query dependents Button   # everything that renders Button
uiquarter query hubs                # most-connected components
uiquarter query chains              # deepest dependency chains
Enter fullscreen mode Exit fullscreen mode

Hub components are interesting — they're the nodes with the highest connectivity. Everything depends on them, so they're risky to change. UIQuarter flags these as architectural insights.

Styling patterns

The StylingAnalyzer detects which approach your project uses:

  • Tailwind — reads your tailwind.config.js to understand custom classes. Captures the actual tokens used in the codebase: bg-[#0A0A10], rounded-2xl, text-[#B4A5BD]. Not just "this project uses Tailwind."
  • CSS Modules — maps which .module.css file belongs to which component
  • styled-components / Emotion — detects template literal styling
  • Plain CSS — tracks stylesheet imports

This matters for AI context generation. When an AI tool knows your project uses rounded-2xl bg-[#0A0A10] border border-white/10 for cards, it generates matching code instead of rounded-lg bg-gray-800.

UX patterns

The UxAnalyzer checks each component for:

  • Error states (try/catch, error boundaries, error message rendering)
  • Loading states (spinner rendering, skeleton UIs, loading flags)
  • Empty states (zero-data handling, empty list messages)
  • Accessibility (ARIA labels, roles, keyboard handlers, focus management)
  • Responsive patterns (media queries, responsive class variants)

This is per-component data. So you can see that DataTable handles loading and empty states but UserCard doesn't have error handling.

Naming and structure

The FileStructureAnalyzer extracts:

  • File naming convention (PascalCase, kebab-case, camelCase)
  • Directory roles (what lives in pages/ vs components/ vs hooks/ vs lib/)
  • Barrel exports (index files that re-export)
  • Import alias patterns (@/components/...)
  • Co-location patterns (test files next to source, styles next to components)

Architecture insights

The InsightEngine processes all analyzer results and detects:

  • Hub components — high connectivity, many dependents. Risky to refactor.
  • Orphan components — nothing renders them. Dead code candidates.
  • Circular dependencies — A imports B imports A.
  • Deep chains — A → B → C → D → E. Long dependency paths.
  • Missing barrel exports — directories without index files.
  • Naming inconsistencies — mixed conventions in the same directory.

Framework-specific analyzers

7 framework analyzers handle framework-specific patterns:

  • Next.js — pages vs app router, API routes, middleware, layouts, server/client components
  • Nuxt — pages, composables, server routes, middleware
  • SvelteKit — routes, load functions, server endpoints
  • Angular — components, services, modules, directives, pipes, routes
  • Solid — signals, effects, resources, stores
  • Lit — custom elements, shadow DOM, reactive properties
  • Qwik — resumable components, server functions

Backend analyzers

4 analyzers for backend patterns:

  • API routes — Express, Fastify, NestJS, Hono, tRPC, GraphQL endpoint detection
  • Database — Prisma, TypeORM, Drizzle, Sequelize, Mongoose model detection
  • Auth — JWT, sessions, OAuth, guards, RBAC patterns
  • Env config — .env parsing, secret detection, validation patterns

The analysis output

Everything goes into a .uiq/ directory:

.uiq/
  index.json      # master intelligence index
  meta.json       # timestamps, stats, build hash
  insights.json   # architectural issues
  snapshot.json   # baseline for drift detection
  cache/          # analyzer result cache (SHA-256)
  patterns/       # per-pattern detail files
Enter fullscreen mode Exit fullscreen mode

The index is a structured JSON with every component, edge, convention, pattern, and insight. You can query it directly or use it to generate context files.

AI context generation

This is the part that connects the analysis to AI coding tools.

uiquarter generate --target all
Enter fullscreen mode Exit fullscreen mode

This reads the analysis index and produces:

Target File Tool
claude CLAUDE.md Claude Code
codex AGENTS.md OpenAI Codex
cursor .cursorrules Cursor
windsurf .windsurfrules Windsurf
cline .clinerules Cline
copilot copilot-instructions.md GitHub Copilot
aider CONVENTIONS.md Aider

Each file is formatted for the specific tool's conventions. The content includes component maps, dependency relationships, styling tokens, naming conventions, and architecture warnings — compressed from the full analysis.

Real numbers

On a React + Tailwind project (11 key files, 71,322 chars of source code):

71,322 characters compressed to 1,299 characters of structured context. 55x compression ratio. The AI reads one file instead of twelve and gets accurate information about every component, dependency, and convention.

Other features

Beyond analysis and context generation:

Task resolver — fuzzy match a description to relevant files:

uiquarter resolve "add dark mode toggle"
# returns scored list of files that are likely relevant
Enter fullscreen mode Exit fullscreen mode

Uses an inverted index with synonym expansion and fuzzy matching.

Drift detection — track architectural changes over time:

uiquarter drift --save     # save current state as baseline
uiquarter drift            # compare current vs baseline
# Patterns: 53 → 58 (+5)
# Insights: 5 → 7 (+2 new)
Enter fullscreen mode Exit fullscreen mode

CI/CD integration:

uiquarter ci --fail-on warning
uiquarter ci --pr 42 --repo owner/repo  # posts as PR comment
uiquarter ci --template                 # generates GitHub Action
Enter fullscreen mode Exit fullscreen mode

Convention linting:

uiquarter lint
# checks: file-naming, barrel-exports, circular-deps,
# max-nesting-depth, single-styling, min-accessibility
Enter fullscreen mode Exit fullscreen mode

MCP server for real-time AI tool integration:

uiquarter serve                              # stdio
uiquarter serve --transport http --port 3100 # HTTP
Enter fullscreen mode Exit fullscreen mode

Exposes tools like uiq_scope_context, uiq_query_component, uiq_resolve_task, uiq_find_insights.

HTML dashboard:

uiquarter report --open
# generates self-contained HTML with dependency graphs and tables
Enter fullscreen mode Exit fullscreen mode

Tech

  • TypeScript (strict mode)
  • ts-morph for AST parsing
  • SHA-256 caching with analyzer versioning
  • Commander for CLI
  • tsup for dual ESM + CJS builds
  • 500+ tests across 36 test files
  • Zero external runtime dependencies
  • Node.js >= 18

Links

If you work on UI projects with AI tools, give it a try. If you have ideas for what else the analyzers should detect, I'd like to hear about it.

Top comments (0)