qr-api

REST API integration for qr-code-generator. TypeScript request helpers, batch pipeline patterns, and server-side code examples for embedding QR generation into other applications.

7 stars

Best use case

qr-api is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

REST API integration for qr-code-generator. TypeScript request helpers, batch pipeline patterns, and server-side code examples for embedding QR generation into other applications.

Teams using qr-api should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/qr-api/SKILL.md --create-dirs "https://raw.githubusercontent.com/heldernoid/agentic-build-templates/main/projects/automation-productivity/qr-code-generator/skills/qr-api/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/qr-api/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How qr-api Compares

Feature / Agentqr-apiStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

REST API integration for qr-code-generator. TypeScript request helpers, batch pipeline patterns, and server-side code examples for embedding QR generation into other applications.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# qr-api Skill

## When to use

Use this skill when you need to call the qr-code-generator API from another service, script, or CI pipeline. This skill covers the TypeScript client, Node.js usage, and piping output.

## Prerequisites

qr-code-generator server running. The `QR_API_URL` environment variable should point to it (e.g., `http://localhost:3000`).

## TypeScript API client

```typescript
// lib/qr-client.ts
import { z } from 'zod';

const QR_API = process.env.QR_API_URL ?? 'http://localhost:3000';

export type QRType = 'url' | 'text' | 'wifi' | 'vcard';
export type ErrorCorrection = 'L' | 'M' | 'Q' | 'H';
export type QRFormat = 'svg' | 'png';

export interface QRStyle {
  fgColor?: string;
  bgColor?: string;
  errorCorrection?: ErrorCorrection;
  margin?: number;
  width?: number;
}

export interface QRRequest {
  type: QRType;
  data: Record<string, string | boolean | number>;
  style?: QRStyle;
  logo?: string | null;
  format?: QRFormat;
}

export interface QRResponse {
  svg: string;
  dataUrl: string;
  size: number;
}

export async function generateQR(req: QRRequest): Promise<QRResponse> {
  const res = await fetch(`${QR_API}/api/generate`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(req),
  });
  if (!res.ok) {
    const body = await res.text();
    throw new Error(`QR generation failed ${res.status}: ${body}`);
  }
  return res.json() as Promise<QRResponse>;
}
```

## URL QR code
```typescript
import { generateQR } from './lib/qr-client.ts';
import { writeFile } from 'node:fs/promises';

const result = await generateQR({
  type: 'url',
  data: { url: 'https://example.com' },
  style: { width: 512, errorCorrection: 'M' },
  format: 'svg',
});

await writeFile('qrcode.svg', result.svg, 'utf8');
```

## WiFi QR code
```typescript
const result = await generateQR({
  type: 'wifi',
  data: {
    ssid: 'OfficeNetwork',
    password: 'supersecret',
    security: 'WPA',
    hidden: false,
  },
  format: 'svg',
});
```

## vCard QR code
```typescript
const result = await generateQR({
  type: 'vcard',
  data: {
    firstName: 'Jane',
    lastName: 'Smith',
    org: 'Acme Corp',
    title: 'Product Manager',
    phone: '+1-555-0100',
    email: 'jane@acme.com',
    url: 'https://acme.com',
  },
  style: { errorCorrection: 'Q' },
  format: 'svg',
});
```

## PNG output to buffer
```typescript
import { generateQR } from './lib/qr-client.ts';
import { writeFile } from 'node:fs/promises';

const result = await generateQR({
  type: 'url',
  data: { url: 'https://example.com' },
  style: { width: 1024 },
  format: 'png',
});

// result.dataUrl is "data:image/png;base64,..."
const base64 = result.dataUrl.split(',')[1];
const buffer = Buffer.from(base64, 'base64');
await writeFile('qrcode.png', buffer);
```

## Bulk generation from JSON
```typescript
import FormData from 'form-data';
import { createReadStream } from 'node:fs';
import { writeFile } from 'node:fs/promises';

const QR_API = process.env.QR_API_URL ?? 'http://localhost:3000';

async function bulkFromJSON(codes: Array<{ data: string; filename: string; fgColor?: string }>) {
  const res = await fetch(`${QR_API}/api/bulk`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ codes, format: 'svg' }),
  });
  if (!res.ok) throw new Error(`Bulk failed: ${res.status}`);
  const buffer = Buffer.from(await res.arrayBuffer());
  await writeFile('qrcodes.zip', buffer);
}
```

## Bulk generation from CSV file
```typescript
import { readFile, writeFile } from 'node:fs/promises';

async function bulkFromCSV(csvPath: string) {
  const csvBuffer = await readFile(csvPath);
  const form = new FormData();
  form.append('csv', csvBuffer, { filename: 'codes.csv', contentType: 'text/csv' });

  const res = await fetch(`${QR_API}/api/bulk`, {
    method: 'POST',
    headers: form.getHeaders(),
    body: form.getBuffer(),
  });
  if (!res.ok) throw new Error(`Bulk failed: ${res.status}`);
  await writeFile('qrcodes.zip', Buffer.from(await res.arrayBuffer()));
}
```

## Express middleware: generate QR on the fly
```typescript
import { Router } from 'express';
import { generateQR } from './lib/qr-client.ts';

const router = Router();

// GET /qr?url=https://example.com&format=svg
router.get('/qr', async (req, res) => {
  const url = String(req.query.url ?? '');
  const format = req.query.format === 'png' ? 'png' : 'svg';

  if (!url.startsWith('http')) {
    return res.status(400).json({ error: 'Invalid url parameter' });
  }

  const result = await generateQR({ type: 'url', data: { url }, format });

  if (format === 'png') {
    const base64 = result.dataUrl.split(',')[1];
    res.setHeader('Content-Type', 'image/png');
    return res.send(Buffer.from(base64, 'base64'));
  }

  res.setHeader('Content-Type', 'image/svg+xml');
  res.send(result.svg);
});

export { router };
```

## CI pipeline: generate QR codes for releases

```bash
#!/usr/bin/env bash
# generate-release-qr.sh
set -euo pipefail

VERSION="${1:-latest}"
BASE_URL="https://releases.example.com/$VERSION"
QR_API="${QR_API_URL:-http://localhost:3000}"

for PLATFORM in linux macos windows; do
  URL="$BASE_URL/download/$PLATFORM"
  FILENAME="release-${VERSION}-${PLATFORM}"

  curl -s -X POST "$QR_API/api/generate" \
    -H 'Content-Type: application/json' \
    -d "{\"type\":\"url\",\"data\":{\"url\":\"$URL\"},\"style\":{\"width\":512},\"format\":\"svg\"}" \
    | jq -r '.svg' > "dist/qr/${FILENAME}.svg"

  echo "Generated $FILENAME.svg"
done
```

## Environment variables

| Variable | Default | Description |
|---|---|---|
| QR_API_URL | http://localhost:3000 | Base URL for the qr-code-generator server |

## Error handling

```typescript
import { generateQR } from './lib/qr-client.ts';

async function safeGenerate(url: string) {
  try {
    const result = await generateQR({
      type: 'url',
      data: { url },
      format: 'svg',
    });
    return result.svg;
  } catch (err) {
    if (err instanceof Error && err.message.includes('400')) {
      console.error('Invalid request:', err.message);
    } else if (err instanceof Error && err.message.includes('429')) {
      console.error('Rate limited. Retry after 60 seconds.');
    } else {
      throw err;
    }
    return null;
  }
}
```

## Rate limits

The server enforces `RATE_LIMIT_RPM` requests per minute per IP (default 60). For bulk jobs, the single `/api/bulk` call counts as one request regardless of how many codes are generated.

Related Skills

Skill: Uptime Monitoring

7
from heldernoid/agentic-build-templates

## Overview

Skill: Status Page

7
from heldernoid/agentic-build-templates

## Overview

Skill: unit-conversion

7
from heldernoid/agentic-build-templates

## Overview

Skill: recipe-scaler

7
from heldernoid/agentic-build-templates

## Overview

reading-list

7
from heldernoid/agentic-build-templates

Operate the reading-list API to save, manage, tag, search, and export articles.

email-digest

7
from heldernoid/agentic-build-templates

Configure, test, and troubleshoot the reading-list daily email digest delivered via nodemailer.

websocket-realtime

7
from heldernoid/agentic-build-templates

Use the WebSocket connection in poll-builder to receive live vote updates. Use when you need to stream real-time poll results, monitor a poll for new votes, or build a live dashboard. Triggers include "live results", "real-time updates", "stream votes", "watch poll", or "WebSocket".

poll-builder

7
from heldernoid/agentic-build-templates

Self-hosted poll creation tool with real-time results. Use when you need to create a poll, check vote counts, close a poll, export results, or get the shareable link for a poll. Triggers include "create poll", "vote", "poll results", "survey", "collect votes", "share poll", or any task involving polling or voting.

Skill: personal-finance

7
from heldernoid/agentic-build-templates

## Overview

Skill: csv-import

7
from heldernoid/agentic-build-templates

## Overview

Skill: Syntax Highlighting

7
from heldernoid/agentic-build-templates

## Purpose

Skill: Pastebin Core

7
from heldernoid/agentic-build-templates

## Purpose