Alchemy RecipeIntermediateautomation

Technical documentation generation from code

Published

Technical documentation is essential, yet updating it alongside code changes is tedious. Developers write new functions, refactor existing ones, and push updates; meanwhile, documentation falls behind. The gap widens until your docs become unreliable guides that confuse rather than clarify.

Traditional approaches force you to manually update markdown files whenever code changes. You either maintain documentation in a separate repository (prone to drift), embed docstrings that don't scale well, or hire dedicated technical writers. None of these options are cost-effective or truly automatic.

This workflow eliminates that friction by combining three tools into a continuous pipeline: your code repository triggers documentation generation, an AI writes clean markdown documentation, and a design tool creates visual references. The entire process runs without human intervention, keeping your docs in sync with reality.... For more on this, see Code repository documentation generation and architecture....

The Automated Workflow

We'll build this using Claude Code as the orchestration layer (via n8n or Make), with v0 handling visual component documentation and Mintlify publishing the final docs. The workflow triggers whenever code is pushed to your repository.

Architecture Overview

The flow works like this:

  1. GitHub webhook detects a code push
  2. Claude Code extracts function signatures and docstrings from your codebase
  3. Claude generates comprehensive markdown documentation
  4. v0 creates component preview images and code examples
  5. Mintlify publishes the updated documentation site

Setting Up the Orchestration with n8n

We'll use n8n for this workflow because it handles webhooks, API calls, and conditional logic smoothly. You could also use Make or Zapier, but n8n gives you the most control over data transformation.

Step 1: Create a GitHub Webhook Trigger

In n8n, add a Webhook node as your trigger. Configure it to listen for push events:


POST /webhook/github-docs

Set your GitHub repository to send push events to this URL. You can do this in repository settings under "Webhooks". Use this payload to confirm n8n receives the push:

{
  "ref": "refs/heads/main",
  "repository": {
    "full_name": "yourorg/yourrepo",
    "clone_url": "https://github.com/yourorg/yourrepo.git"
  },
  "pusher": {
    "name": "developer-name",
    "email": "dev@example.com"
  },
  "commits": [
    {
      "id": "abc123def456",
      "message": "Add new API endpoint",
      "modified": ["src/api/users.ts"]
    }
  ]
}

Step 2: Clone and Parse Repository

Add an Execute Command node to clone the repository and extract TypeScript/JavaScript file contents:

git clone https://github.com/yourorg/yourrepo.git /tmp/repo
find /tmp/repo -type f \( -name "*.ts" -o -name "*.tsx" -o -name "*.js" \) ! -path "*/node_modules/*" ! -path "*/.next/*" | head -20

Then add a Script node to read and parse these files:

const fs = require('fs');
const path = require('path');

const repoPath = '/tmp/repo';
const files = $input.all().map(item => item.json.file);

const parsed = files.map(filepath => {
  const fullPath = path.join(repoPath, filepath);
  const content = fs.readFileSync(fullPath, 'utf8');
  
  return {
    filename: filepath,
    content: content,
    language: filepath.endsWith('.ts') || filepath.endsWith('.tsx') ? 'typescript' : 'javascript'
  };
});

return parsed;

This extracts function signatures and docstrings from your codebase so Claude Code can analyse them.

Step 3: Call Claude Code for Documentation Generation

Add an HTTP Request node to invoke Claude via the Anthropic API. Configure it as follows:


Method: POST
URL: https://api.anthropic.com/v1/messages
Headers:
  - x-api-key: YOUR_ANTHROPIC_API_KEY
  - content-type: application/json
  - anthropic-version: 2023-06-01

Body (JSON):
{
  "model": "claude-3-5-sonnet-20241022",
  "max_tokens": 4096,
  "messages": [
    {
      "role": "user",
      "content": "Analyse this TypeScript code and generate comprehensive technical documentation in Markdown format. Include function signatures, parameter descriptions, return types, and usage examples.\n\nCode:\n\n{{CODE_CONTENT}}\n\nFormatting requirements:\n- Use proper Markdown syntax\n- Include type definitions in code blocks\n- Provide practical usage examples\n- Document error cases\n- Keep descriptions concise but complete"
    }
  ]
}

In n8n's expression editor, set {{CODE_CONTENT}} to the parsed file contents from Step 2. Claude will return structured markdown documentation.

The response from Claude looks like this:

{
  "content": [
    {
      "type": "text",
      "text": "# API Documentation\n\n

## getUserById()\n\nRetrieves a user record by ID.\n\n

### Parameters\n\n- `id` (string):

The unique user identifier\n- `options` (object, optional): Query options\n\n

### Returns\n\nPromise<User> - User object matching the provided ID\n\n

### Example\n\n

```typescript\nconst user = await getUserById('user_123');\nconsole.log(user.email);\n

```\n\n

### Error Cases\n\nThrows `UserNotFoundError` if the user ID doesn't exist."
    }
  ]
}

Step 4: Generate Component Visuals with v0

For frontend components, add another HTTP Request node to call the v0 API (if you have API access) or use a webhook approach:


Method: POST
URL: https://api.v0.dev/generate
Headers:
  - Authorization: Bearer YOUR_V0_API_KEY
  - Content-Type: application/json

Body (JSON):
{
  "prompt": "Create a visual example component documentation page for this component:\n\n{{COMPONENT_CODE}}\n\nInclude:\n- Component preview\n- Props table\n- Usage examples\n- State management example",
  "outputFormat": "react"
}

v0 returns a React component showing the documentation layout and examples. Save this for the next step.

Step 5: Assemble Documentation and Deploy to Mintlify

Add a final HTTP Request node to push the assembled documentation to Mintlify:


Method: POST
URL: https://api.mintlify.com/v1/docs
Headers:
  - Authorization: Bearer YOUR_MINTLIFY_API_KEY
  - Content-Type: application/json

Body (JSON):
{
  "title": "Auto-Generated API Documentation",
  "version": "{{GITHUB_COMMIT_SHA}}",
  "content": {
    "markdown": "{{CLAUDE_DOCUMENTATION}}",
    "components": "{{V0_COMPONENT_VISUALS}}",
    "metadata": {
      "lastUpdated": "{{CURRENT_TIMESTAMP}}",
      "generatedBy": "automated-workflow",
      "sourceCommit": "{{GITHUB_COMMIT_SHA}}"
    }
  }
}

Mintlify publishes this immediately to your documentation site. You can configure a custom domain, search indexing, and versioning directly in Mintlify's settings.

Practical n8n Workflow Configuration

Here's how to structure the entire workflow in n8n:


[GitHub Webhook Trigger]
    ↓
[Filter: Only on main branch]
    ↓
[Execute Command: Clone repo]
    ↓
[Script: Parse files]
    ↓
[Split: Process each file]
    ↓
[HTTP: Call Claude Code]
    ↓
[HTTP: Generate v0 visuals]
    ↓
[HTTP: Deploy to Mintlify]
    ↓
[Email: Notify team on completion]

In n8n's interface, set the GitHub webhook to "Authentication Type: none" since GitHub provides a signature verification header. Add a Script node after the webhook to verify the signature:

const crypto = require('crypto');
const signature = this.getHeader('x-hub-signature-256');
const secret = process.env.GITHUB_WEBHOOK_SECRET;
const payload = this.getRawBody();

const hash = 'sha256=' + crypto.createHmac('sha256', secret)
  .update(payload)
  .digest('hex');

if (signature !== hash) {
  throw new Error('Invalid GitHub webhook signature');
}

return true;

Error Handling and Retries

Add error handling nodes after API calls:

if (response.status >= 400) {
  // Retry up to 3 times with exponential backoff
  let retries = 0;
  while (retries < 3) {
    await new Promise(resolve => setTimeout(resolve, Math.pow(2, retries) * 1000));
    const retry = await http.post(url, payload);
    if (retry.status < 400) return retry;
    retries++;
  }
  
  // If all retries fail, send alert
  await notify.email({
    to: 'team@example.com',
    subject: 'Documentation generation failed',
    body: `Failed to generate docs for commit ${commitSha}`
  });
}

Rate Limiting Considerations

Claude Code has rate limits (check your API tier). Add a Delay node between requests if processing multiple files:


[For each modified file]
    ↓
[Delay: 2 seconds]
    ↓
[Call Claude]

This prevents hitting rate limits when your workflow processes many files at once.

The Manual Alternative

If you prefer more control, you can invoke each step manually. Clone your repository locally, run this command to extract documentation with Claude:

find src -type f -name "*.ts" | xargs cat | \
  curl https://api.anthropic.com/v1/messages \
    -H "x-api-key: $ANTHROPIC_API_KEY" \
    -H "content-type: application/json" \
    -d '{
      "model": "claude-3-5-sonnet-20241022",
      "max_tokens": 4096,
      "messages": [{"role": "user", "content": "Generate Markdown documentation from this code"}]
    }'

Review the markdown output, then manually upload to Mintlify. This gives you quality assurance but requires human effort each time your codebase changes significantly.

For smaller projects or when you need fine-grained control, this manual approach works. For teams pushing changes daily, the automated workflow saves hours weekly.

Pro Tips

Tip 1: Exclude vendor code from documentation

Modify the file parsing script to skip node_modules, vendor directories, and generated code:

const excluded = [
  'node_modules',
  '.next',
  'dist',
  'build',
  '.venv',
  '__pycache__'
];

const isExcluded = filepath => excluded.some(dir => filepath.includes(dir));
const relevantFiles = allFiles.filter(f => !isExcluded(f));

This keeps your documentation focused on actual product code rather than dependencies.

Tip 2: Cache documentation for unchanged files

Store a hash of each file alongside its generated documentation. Only regenerate docs when file contents change:

const crypto = require('crypto');
const cache = {};

files.forEach(file => {
  const hash = crypto.createHash('sha256').update(file.content).digest('hex');
  
  if (cache[file.path] && cache[file.path].hash === hash) {
    // Use cached documentation
    return cache[file.path].docs;
  }
  
  // Generate new documentation
  const docs = generateDocs(file.content);
  cache[file.path] = { hash, docs };
  return docs;
});

This significantly reduces API calls and costs when only a few files change per commit.

Tip 3: Version documentation with git tags

Configure Mintlify to maintain multiple documentation versions. Update your deployment step to tag releases:

const version = process.env.GITHUB_REF.replace('refs/tags/v', '');
const payload = {
  title: 'API Documentation',
  version: version,
  content: documentationContent
};

This allows users to reference docs for specific library versions they depend on.

Tip 4: Monitor documentation quality

Add a quality check step in your workflow. After Claude generates documentation, analyse it for completeness:

const requiredSections = [
  'Parameters',
  'Returns',
  'Example',
  'Error Cases'
];

const missingCount = requiredSections.filter(section => 
  !documentation.includes(`

### ${section}`)
).length;

if (missingCount > 0) {
  console.warn(`Documentation missing ${missingCount} sections`);
  // Flag for manual review
}

Tip 5: Set up Mintlify custom domain early

Configuring a custom domain (like docs.yourcompany.com) takes a few minutes but should be done before your first automated deployment. Update your DNS records and SSL certificate configuration to avoid downtime later.

Cost Breakdown

ToolPlan NeededMonthly CostNotes
Claude Code APIPay-as-you-go$5–30~$0.003 per 1K input tokens; docs generation uses ~2K tokens per file
n8nProfessional$20Covers 100K executions; most workflows use <10K monthly
v0Pro$20Optional; needed only if documenting frontend components
MintlifyHobby tierFreeSufficient for most teams; custom domain included
GitHubFree$0Webhooks included; no additional cost

Total monthly cost: $45–70 assuming you process 20 files per week with Claude and generate component visuals. Costs scale linearly with file count; teams pushing hundreds of files daily should budget higher.

You can reduce costs significantly by processing documentation generation monthly or quarterly rather than on every commit. Use branch-based filtering to only generate docs on main branch updates, not every feature branch push.

More Recipes