Skip to content

Structure Planner

Planner

Functions

planStructure

async function planStructure(elements: APIElement[], topology: TopologyAnalysis, client: LLMClient): Promise<DocStructure>
TypeScript

Use planStructure to let an LLM analyze your scanned API surface and decide how documentation should be organized — which pages to create, what to group together, and how navigation should flow.

Reach for this after you've scanned a codebase and run topology analysis. Rather than dumping every exported symbol into a flat list, planStructure reasons about relationships between elements and produces a coherent information architecture before any docs are written.

It sends a summary of your API surface and its dependency topology to the LLM, which returns a structured plan: pages, groupings, and a navigation tree. That plan then drives the actual doc generation step.

Parameters

NameTypeRequiredDescription
elementsAPIElement[]YesThe full list of scanned API symbols (functions, classes, types) extracted from your source. Pass the output of your scanner directly — order doesn't matter.
topologyTopologyAnalysisYesDependency and relationship graph between elements, produced by topology analysis. Gives the LLM the context it needs to group related symbols intelligently.
clientLLMClientYesConfigured LLM client that handles the actual AI call. Controls which model and provider are used for planning.

Returns

Returns a DocStructure containing the planned pages, element groupings, and navigation tree. Pass this directly to your doc generation step — each PagePlan in the structure maps a set of APIElements to an output file, and the NavigationNode tree defines the sidebar hierarchy.

Heads up

  • The quality of the structure depends heavily on the topology analysis. If topology is sparse or missing relationships, the LLM will fall back to grouping by file — run a full topology pass before calling this.
  • This makes an LLM call and can be slow for large APIs (500+ elements). Consider caching the returned DocStructure to disk so you don't re-plan on every generation run.

Example:

// Inline types — do not import from autodocs
type APIElement = {
  name: string;
  kind: "function" | "class" | "type" | "interface";
  filePath: string;
  signature: string;
  description?: string;
};

type TopologyAnalysis = {
  clusters: Array<{ label: string; elementNames: string[] }>;
  dependencies: Record<string, string[]>;
};

type PagePlan = {
  slug: string;
  title: string;
  elementNames: string[];
};

type NavigationNode = {
  title: string;
  href?: string;
  children?: NavigationNode[];
};

type DocStructure = {
  pages: PagePlan[];
  navigation: NavigationNode[];
};

type LLMClient = {
  complete: (prompt: string) => Promise<string>;
};

// Mock planStructure — mirrors the real implementation's behavior
async function planStructure(
  elements: APIElement[],
  topology: TopologyAnalysis,
  client: LLMClient
): Promise<DocStructure> {
  const summary = elements
    .map((el) => `${el.kind} ${el.name}: ${el.signature}`)
    .join("\n");

  const clusterSummary = topology.clusters
    .map((c) => `${c.label}: ${c.elementNames.join(", ")}`)
    .join("\n");

  const prompt = `
You are planning documentation structure for an API.

API elements:
${summary}

Detected clusters:
${clusterSummary}

Return a JSON object with:
- pages: array of { slug, title, elementNames[] }
- navigation: array of { title, href?, children? }
`;

  const raw = await client.complete(prompt);
  return JSON.parse(raw) as DocStructure;
}

// Mock LLM client — replace with your real provider
const mockLLMClient: LLMClient = {
  complete: async (_prompt: string): Promise<string> => {
    const structure: DocStructure = {
      pages: [
        {
          slug: "authentication",
          title: "Authentication",
          elementNames: ["createToken", "revokeToken", "validateToken"],
        },
        {
          slug: "users",
          title: "Users",
          elementNames: ["createUser", "getUser", "deleteUser"],
        },
      ],
      navigation: [
        {
          title: "API Reference",
          children: [
            { title: "Authentication", href: "/docs/authentication" },
            { title: "Users", href: "/docs/users" },
          ],
        },
      ],
    };
    return JSON.stringify(structure);
  },
};

const elements: APIElement[] = [
  { name: "createToken", kind: "function", filePath: "src/auth/token.ts", signature: "createToken(userId: string): Promise<string>" },
  { name: "revokeToken", kind: "function", filePath: "src/auth/token.ts", signature: "revokeToken(token: string): Promise<void>" },
  { name: "validateToken", kind: "function", filePath: "src/auth/token.ts", signature: "validateToken(token: string): Promise<boolean>" },
  { name: "createUser", kind: "function", filePath: "src/users/user.ts", signature: "createUser(email: string): Promise<User>" },
  { name: "getUser", kind: "function", filePath: "src/users/user.ts", signature: "getUser(id: string): Promise<User>" },
  { name: "deleteUser", kind: "function", filePath: "src/users/user.ts", signature: "deleteUser(id: string): Promise<void>" },
];

const topology: TopologyAnalysis = {
  clusters: [
    { label: "Authentication", elementNames: ["createToken", "revokeToken", "validateToken"] },
    { label: "Users", elementNames: ["createUser", "getUser", "deleteUser"] },
  ],
  dependencies: {
    createToken: ["createUser"],
    revokeToken: [],
    validateToken: [],
    createUser: [],
    getUser: [],
    deleteUser: [],
  },
};

async function main() {
  try {
    const structure = await planStructure(elements, topology, mockLLMClient);

    console.log("Planned pages:");
    structure.pages.forEach((page) => {
      console.log(`  /${page.slug} — "${page.title}" (${page.elementNames.length} elements)`);
    });

    console.log("\nNavigation tree:");
    console.log(JSON.stringify(structure.navigation, null, 2));

    // Expected output:
    // Planned pages:
    //   /authentication — "Authentication" (3 elements)
    //   /users — "Users" (3 elements)
    //
    // Navigation tree:
    // [
    //   {
    //     "title": "API Reference",
    //     "children": [
    //       { "title": "Authentication", "href": "/docs/authentication" },
    //       { "title": "Users", "href": "/docs/users" }
    //     ]
    //   }
    // ]
  } catch (err) {
    console.error("Failed to plan structure:", err);
  }
}

main();
TypeScript
Was this helpful?