Skip to main content
Glama

analyze_code

Analyze frontend source code to identify accessibility issues, CSS problems, component complexity, design inconsistencies, and performance concerns for quality improvement.

Instructions

Analyze frontend source code for quality issues: accessibility anti-patterns, CSS problems, component complexity, design inconsistencies, and performance concerns.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
directoryYesAbsolute path to the frontend source directory (e.g., /Users/me/project/src)

Implementation Reference

  • The primary handler function `analyzeCode` that executes code analysis on a given directory. It scans files for various patterns, applies rules, and aggregates findings.
    export async function analyzeCode(
      directory: string
    ): Promise<CodeAnalysisResult> {
      const { config, loaded, path: configPath } = await loadConfig(directory);
    
      const framework = await detectFramework(directory);
    
      // Convert config ignore patterns to glob-compatible patterns
      const configIgnoreGlobs = config.ignore.map((pattern) => {
        // If pattern has no glob chars and no extension, treat as a directory
        if (!pattern.includes("*") && !pattern.includes(".")) {
          return `${pattern}/**`;
        }
        // If it's a glob pattern like "*.test.*", ensure it matches in all directories
        if (pattern.startsWith("*.")) {
          return `**/${pattern}`;
        }
        return pattern;
      });
    
      const files = await collectFrontendFiles(directory, 200, configIgnoreGlobs);
    
      // Filter RULES based on config (immutable — create a new filtered array)
      const activeRules = RULES.filter((rule) => config.rules[rule.id] !== "off");
    
      // Build a list of disabled rule IDs for reporting
      const rulesDisabled = Object.entries(config.rules)
        .filter(([, status]) => status === "off")
        .map(([id]) => id);
    
      // Build a list of severity-overridden rule IDs for reporting
      const severityOverrides = Object.keys(config.severity);
    
      const findings: CodeFinding[] = [];
      let totalLines = 0;
      let componentCount = 0;
      let stylesheetCount = 0;
    
      for (const file of files) {
        totalLines += file.lineCount;
    
        // Count components and stylesheets
        if ([".tsx", ".jsx", ".vue", ".svelte"].includes(file.extension)) {
          componentCount++;
        }
        if ([".css", ".scss", ".sass", ".less"].includes(file.extension)) {
          stylesheetCount++;
        }
    
        // Run pattern-based rules (using filtered activeRules)
        for (const rule of activeRules) {
          if (!rule.fileTypes.includes(file.extension)) continue;
    
          const matches = file.content.matchAll(rule.pattern);
          let matchCount = 0;
    
          // Determine the effective severity: config override takes precedence
          const effectiveSeverity = config.severity[rule.id] ?? rule.severity;
    
          for (const match of matches) {
            matchCount++;
            if (matchCount > 5) break; // Limit findings per rule per file
    
            // Find line number
            const beforeMatch = file.content.slice(0, match.index);
            const lineNumber = beforeMatch.split("\n").length;
    
            findings.push({
              file: file.relativePath,
              line: lineNumber,
              severity: effectiveSeverity,
              category: rule.category,
              rule: rule.id,
              message: rule.message,
              suggestion: rule.suggestion,
            });
          }
        }
    
        // Run file-level checks
        const sizeCheck = checkFileSize(file);
        if (sizeCheck) findings.push(sizeCheck);
    
        const nestingCheck = checkDeepNesting(file);
        if (nestingCheck) findings.push(nestingCheck);
      }
    
      // Run project-level checks
      const errorBoundaryCheck = checkMissingErrorBoundary(files);
      if (errorBoundaryCheck) findings.push(errorBoundaryCheck);
    
      // Sort findings by severity
      const severityOrder: Record<Severity, number> = {
        critical: 0,
        high: 1,
        medium: 2,
        low: 3,
      };
      const sortedFindings = [...findings].sort(
        (a, b) => severityOrder[a.severity] - severityOrder[b.severity]
      );
    
      // Find largest files
      const sortedFiles = [...files].sort((a, b) => b.lineCount - a.lineCount);
      const largestFiles = sortedFiles.slice(0, 5).map((f) => ({
        file: f.relativePath,
        lines: f.lineCount,
      }));
    
      const avgFileSize =
        files.length > 0
          ? Math.round(totalLines / files.length)
          : 0;
    
      return {
        directory,
        timestamp: new Date().toISOString(),
        framework,
        totalFiles: files.length,
        totalLines,
        findings: sortedFindings,
        summary: {
          components: componentCount,
          stylesheets: stylesheetCount,
          avgFileSize,
          largestFiles,
        },
        configStatus: {
          loaded,
          path: configPath,
          rulesDisabled,
          severityOverrides,
        },
      };
    }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/prembobby39-gif/uimax-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server