# What Is the readPatterns Function in Impeccable? Parsing DO/DON'T Design Patterns

> Uncover the purpose of the readPatterns function in Impeccable. Learn how it parses DO/DON'T design patterns from markdown to power its web interface.

- Repository: [Paul Bakaus/impeccable](https://github.com/pbakaus/impeccable)
- Tags: how-to-guide
- Published: 2026-03-09

---

**The `readPatterns` function parses the [`frontend-design/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/frontend-design/SKILL.md) markdown file to extract structured DO and DON'T design guidelines, returning a JSON object that powers the Patterns and Anti-Patterns tabs in the Impeccable web interface.**

The `readPatterns` function in the [pbakaus/impeccable](https://github.com/pbakaus/impeccable) repository serves as the data bridge between human-written markdown guidelines and machine-readable API responses. Located in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js), this utility transforms static design rules documented in the skill file into dynamic content for the application's frontend. By programmatically extracting checklist items marked with `**DO**:` and `**DON'T**:` prefixes, Impeccable maintains a single source of truth for frontend design standards.

## What Does readPatterns Do?

The `readPatterns` function is a markdown parser utility that reads [`source/skills/frontend-design/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/source/skills/frontend-design/SKILL.md) and isolates design guidelines organized under category headings (e.g., Typography, Color & Contrast). It categorizes items based on whether they follow the `**DO**:` or `**DON'T**:` convention used throughout the skill documentation.

### Returned Data Structure

The function returns an object containing two parallel arrays:

```json
{
  "patterns": [
    { "name": "Typography", "items": ["Use a maximum of two font families", "..."] },
    { "name": "Color & Contrast", "items": ["Maintain a contrast ratio of at least 4.5:1", "..."] }
  ],
  "antipatterns": [
    { "name": "Typography", "items": ["Use more than two font families", "..."] },
    { "name": "Color & Contrast", "items": ["Rely solely on color to convey information", "..."] }
  ]
}

```

This structure separates positive recommendations (**patterns**) from prohibitions (**antipatterns**), preserving the section order defined in the original markdown.

## How readPatterns Parses DO and DON'T Items

As implemented in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) (lines 92-162), the function follows a deterministic line-by-line scanning algorithm:

1. **File Resolution**: The function constructs the absolute path to [`source/skills/frontend-design/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/source/skills/frontend-design/SKILL.md) using `path.join(rootDir, 'source/skills/frontend-design/SKILL.md')` (lines 97-99).

2. **Line Tokenization**: It reads the file with `fs.readFileSync(..., 'utf-8')` and splits the content into an array of lines using `content.split('\n')` (lines 104-106).

3. **Heading Detection**: The parser tracks the current category by detecting lines starting with `### ` (markdown H3 headings). When found, it strips the prefix and stores the section name (lines 114-119).

4. **DO Pattern Extraction**: Lines beginning with `**DO**:` have their prefix removed and the remaining text appended to the `patternsMap` under the current section key (lines 124-130).

5. **DON'T Pattern Extraction**: Similarly, lines starting with `**DON'T**:` are cleaned and pushed to the `antipatternsMap` for the active section (lines 134-140).

6. **Array Conversion**: After scanning completes, the function converts the internal maps into ordered arrays based on `sectionOrder`, ensuring the UI receives categories in a consistent sequence (lines 146-158).

7. **Return Value**: Finally, it returns the structured object containing `patterns` and `antipatterns` arrays (lines 160-162).

## Where readPatterns Is Used in the Impeccable Architecture

The function operates as the backend data source for the application's design guidelines API.

### The API Handler Layer

In [`server/lib/api-handlers.js`](https://github.com/pbakaus/impeccable/blob/main/server/lib/api-handlers.js) (lines 33-38), the `getPatterns` function acts as a thin wrapper that calls `readPatterns(PROJECT_ROOT)` and returns the result. This abstraction allows the API layer to remain agnostic of the file parsing implementation.

### The Web Server Route

The main server entry point in [`server/index.js`](https://github.com/pbakaus/impeccable/blob/main/server/index.js) (lines 86-92) registers the `/api/patterns` endpoint. When a client requests this route, the server invokes `getPatterns()` and serves the JSON payload directly to the frontend.

### The Frontend Consumer

The client-side application in [`public/app.js`](https://github.com/pbakaus/impeccable/blob/main/public/app.js) fetches from `/api/patterns` to populate the "Patterns" and "Anti-Patterns" tabs. By consuming this API instead of hardcoding guidelines, the UI automatically reflects any updates to [`source/skills/frontend-design/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/source/skills/frontend-design/SKILL.md) after a server restart.

## Code Examples: Working with readPatterns

### Direct Usage in Node.js or Bun

You can import and execute `readPatterns` directly in scripts to access the design guidelines programmatically:

```javascript
import { readPatterns } from './scripts/lib/utils.js';
import { fileURLToPath } from 'node:url';
import { dirname, join } from 'node:path';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const ROOT = join(__dirname, '..');

const { patterns, antipatterns } = readPatterns(ROOT);

console.log('Design DOs:');
patterns.forEach(section => {
  console.log(`\n${section.name}:`);
  section.items.forEach(item => console.log(`  ✓ ${item}`));
});

console.log('\nDesign DON\'Ts:');
antipatterns.forEach(section => {
  console.log(`\n${section.name}:`);
  section.items.forEach(item => console.log(`  ✗ ${item}`));
});

```

### Consuming the JSON API

For browser-based applications or external tools, consume the exposed endpoint:

```javascript
async function renderDesignGuidelines() {
  const response = await fetch('/api/patterns');
  if (!response.ok) {
    throw new Error(`HTTP error! status: ${response.status}`);
  }
  
  const { patterns, antipatterns } = await response.json();
  
  // Render patterns tab
  const patternsContainer = document.getElementById('patterns');
  patterns.forEach(section => {
    const details = document.createElement('details');
    details.innerHTML = `
      <summary>${section.name}</summary>
      <ul>${section.items.map(i => `<li>${i}</li>`).join('')}</ul>
    `;
    patternsContainer.appendChild(details);
  });
}

```

## Summary

- The `readPatterns` function in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) parses [`source/skills/frontend-design/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/source/skills/frontend-design/SKILL.md) to extract structured design guidelines.
- It identifies **DO** items as patterns and **DON'T** items as antipatterns, grouping them by markdown H3 headings.
- The function returns a JSON object with `patterns` and `antipatterns` arrays, each containing section names and checklist items.
- It serves as the data foundation for the `/api/patterns` endpoint, enabling dynamic rendering of design guidelines without hardcoded content.
- Changes to the markdown source automatically propagate to the API output, ensuring the single source of truth remains synchronized.

## Frequently Asked Questions

### What file format does readPatterns expect?

The `readPatterns` function expects a markdown file located at [`source/skills/frontend-design/SKILL.md`](https://github.com/pbakaus/impeccable/blob/main/source/skills/frontend-design/SKILL.md) relative to the provided root directory. Specifically, it parses H3 headings (`### Category Name`) as section delimiters and looks for list items prefixed with `**DO**:` or `**DON'T**:` to populate the patterns and antipatterns arrays.

### How does readPatterns handle section ordering?

According to the implementation in [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js) (lines 146-158), the function maintains section order using a predefined `sectionOrder` array. After parsing the markdown into temporary maps, it iterates through this ordered list to construct the final arrays, ensuring the API returns categories in a consistent, predictable sequence regardless of their physical order in the file.

### Can readPatterns be used outside of the Impeccable server?

Yes. While `readPatterns` is primarily consumed by the API handlers in [`server/lib/api-handlers.js`](https://github.com/pbakaus/impeccable/blob/main/server/lib/api-handlers.js), it is exported as a standalone utility from [`scripts/lib/utils.js`](https://github.com/pbakaus/impeccable/blob/main/scripts/lib/utils.js). You can import it into build scripts, documentation generators, or testing frameworks to access the design guidelines programmatically without starting the web server, as demonstrated in the Node.js usage example above.

### What is the difference between patterns and antipatterns in the return value?

The `patterns` array contains items marked with `**DO**:`, representing recommended frontend design practices, while the `antipatterns` array contains items marked with `**DON'T**:`, representing practices to avoid. Both arrays share the same section structure—objects with `name` and `items` properties—but are kept separate to support the tabbed UI interface in the Impeccable application.