# How to Fix Section Ordering Issues Automatically with the Fixer API

> Automatically fix DESIGN.md section ordering issues with the Fixer API. Preserve preludes and custom sections. Get a corrected document string via the fixSectionOrder function.

- Repository: [Google Labs Code/design.md](https://github.com/google-labs-code/design.md)
- Tags: how-to-guide
- Published: 2026-06-27

---

**The Fixer API deterministically reorders DESIGN.md sections according to canonical specifications while preserving preludes and custom sections, returning a corrected document string via the `fixSectionOrder` function.**

The Fixer API in the google-labs-code/design.md repository provides a programmatic interface to automatically fix section ordering issues in DESIGN.md files. This API wraps the same validation logic used by the linter, ensuring your documentation follows the canonical structure defined in the project configuration.

## How the Fixer API Works

The `fixSectionOrder` function in [`packages/cli/src/linter/fixer/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/handler.ts) processes documents through a five-stage pipeline that guarantees deterministic output.

### Input Validation

The API strictly enforces the `FixerInputSchema` defined in [`packages/cli/src/linter/fixer/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/spec.ts). The input must contain the original `content` string and a `sections` array, where each section object includes a `heading` (the section title) and its raw `content`.

### Prelude Preservation

Any section with an empty string heading is identified as the "prelude" and locked to the top of the document. As implemented in [`handler.ts`](https://github.com/google-labs-code/design.md/blob/main/handler.ts) at line 21, this ensures introductory material such as front-matter or free-form text remains unchanged.

### Section Classification

The fixer separates sections into known and unknown categories. Known sections are those whose canonical heading appears in `CANONICAL_ORDER`, the ordered list derived from [`spec-config.yaml`](https://github.com/google-labs-code/design.md/blob/main/spec-config.yaml). The `resolveAlias` helper in [`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts) (line 60) expands aliases to canonical forms before checking. Unknown sections—custom or future sections not in the specification—are identified but left unsorted.

### Canonical Sorting

Known sections are sorted according to their index within `CANONICAL_ORDER`. The implementation in [`handler.ts`](https://github.com/google-labs-code/design.md/blob/main/handler.ts) (lines 33-36) uses this index to determine the correct sequence, ensuring consistent ordering across all documents.

### Document Reassembly

The final document is reconstructed by concatenating the prelude, followed by sorted known sections, then unknown sections. Each section is joined with a single newline. The function returns an object containing `fixedContent` (the reordered document) and optional `details` showing the before and after heading orders for debugging purposes (lines 51-60).

## Implementing the Fixer API

You can integrate the fixer into your workflow through direct programmatic access, CLI commands, or web services.

### Direct API Usage

Import `fixSectionOrder` from the handler module and provide a valid `FixerInput` object:

```typescript
import { fixSectionOrder } from
  '@design-md/cli/src/linter/fixer/handler.js';
import type { FixerInput } from
  '@design-md/cli/src/linter/fixer/spec.js';

// Assume `parseDesignMd` splits a DESIGN.md file into the required shape
const { sections, rawContent } = parseDesignMd('my-design.md');

const input: FixerInput = {
  content: rawContent,
  sections,
};

const result = fixSectionOrder(input);

if (result.success) {
  console.log('Fixed document:', result.fixedContent);
  console.log('Before order:', result.details?.beforeOrder);
  console.log('After order:', result.details?.afterOrder);
} else {
  console.error('Fix failed:', result.error);
}

```

### CLI Shortcut

For command-line usage, the `design-md fix` command wraps the API functionality:

```bash
design-md fix path/to/DESIGN.md --output fixed.md

```

This command parses the file into sections, invokes `fixSectionOrder`, and writes the `fixedContent` to the specified output file.

### Web Service Integration

Deploy the fixer as an HTTP endpoint using Express:

```typescript
import express from 'express';
import { fixSectionOrder } from
  '@design-md/cli/src/linter/fixer/handler.js';
import type { FixerInput } from
  '@design-md/cli/src/linter/fixer/spec.js';

const app = express();
app.use(express.json());

app.post('/api/fix-section-order', (req, res) => {
  const input: FixerInput = req.body;
  const result = fixSectionOrder(input);
  res.json(result);
});

app.listen(3000);

```

## Configuration and Alias Resolution

The sorting logic relies on `CANONICAL_ORDER` defined in [`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts). This configuration determines the canonical sequence of sections. The `resolveAlias` function handles heading variations by mapping aliases to their canonical forms before sorting, ensuring that documents using synonyms or alternate titles are correctly ordered according to the specification.

## Summary

- The Fixer API automatically reorders DESIGN.md sections to match canonical specifications via the `fixSectionOrder` function.
- Input requires validated `FixerInput` with `content` and `sections` array as defined in [`packages/cli/src/linter/fixer/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/spec.ts).
- Prelude sections (empty headings) remain fixed at the top of the document according to [`handler.ts`](https://github.com/google-labs-code/design.md/blob/main/handler.ts) line 21.
- Unknown sections are preserved and appended after known sections rather than being discarded.
- The API returns both the corrected `fixedContent` string and optional debugging details showing the transformation.

## Frequently Asked Questions

### How does the Fixer API handle custom sections not in the canonical order?

Unknown sections—those whose headings do not match entries in `CANONICAL_ORDER`—are not deleted or modified. Instead, they are appended after all known sections in their original relative order, preserving custom content while standardizing the core structure.

### What happens to the prelude or front-matter when fixing section order?

The fixer identifies any section with an empty string heading as the prelude. This section is always kept at the very top of the output document, ensuring that introductory content, front-matter, or free-form text remains unchanged regardless of the sorting operation.

### Can I use the Fixer API without the CLI?

Yes. The `fixSectionOrder` function is exported from [`packages/cli/src/linter/fixer/handler.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/fixer/handler.ts) and can be imported directly into Node.js or TypeScript applications. This allows integration into custom build pipelines, pre-commit hooks, or web services without invoking the command-line interface.

### How does the API resolve section aliases before sorting?

The `resolveAlias` helper in [`packages/cli/src/linter/spec-config.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/spec-config.ts) (line 60) maps alternate section titles to their canonical forms before checking against `CANONICAL_ORDER`. This ensures that documents using synonyms or legacy heading names are correctly positioned according to the specification.