diagram-title-generator
v0.0.1
Published
Zero-dependency AI title generator for generic diagram data
Maintainers
Readme
📊 Diagram Title Generator
A lightweight, zero-dependency TypeScript library that generates intelligent titles for diagram data using AI (Gemini or OpenRouter APIs).

✨ Features
- 🪶 Zero Runtime Dependencies - Uses only native
fetchandPromise - 🌍 Universal Compatibility - Works in Node.js, Edge Runtime, and browsers
- 🤖 Dual Provider Support - Gemini and OpenRouter APIs
- 🧠 Intelligent Extraction - Semantic crawling with field prioritization
- 📦 Multiple Formats - CommonJS, ESM, and TypeScript declarations
- ⚡ Tiny Bundle - Minified builds under 3KB
⚠️ Privacy & Security Notice
Data Sovereignty
IMPORTANT: This package sends your diagram content to external AI services (Google Gemini or OpenRouter). By using this library, diagram data leaves your infrastructure.
Implications:
- ✅ Public/Non-Sensitive Data: Safe to use for public diagrams, demos, or non-confidential workflows
- ❌ Enterprise/Regulated Data: If your diagrams contain PII, trade secrets, or data subject to GDPR/HIPAA/other regulations, do NOT use this package without:
- Legal review of the AI provider's data processing agreements
- Implementing data anonymization/redaction before sending
- Ensuring compliance with your organization's data governance policies
For Regulated Environments: Consider running a self-hosted AI model or using this package only in isolated, non-production environments.
Browser Usage Security
WARNING: This package works in browsers via native fetch, but NEVER hardcode API keys in frontend code:
// ❌ NEVER DO THIS (exposes your API key to all users)
const title = await generateTitle(data, {
apiKey: 'sk-your-key-here' // Visible in browser DevTools!
});
// ✅ ALWAYS use a backend proxy
const response = await fetch('/api/generate-title', {
method: 'POST',
body: JSON.stringify({ diagramData })
});
const { title } = await response.json();The package will log a console warning if it detects API key usage in a browser environment.
📥 Installation
npm install diagram-title-generator🚀 Quick Start
Using Google Gemini API
import { generateTitle } from 'diagram-title-generator';
const diagramData = {
nodes: [
{ id: '1', text: 'User Login', type: 'Input' },
{ id: '2', text: 'Authenticate', type: 'Process' },
{ id: '3', text: 'Database', type: 'Storage' }
],
edges: []
};
const title = await generateTitle(diagramData, {
apiKey: process.env.GEMINI_API_KEY,
provider: 'google',
model: 'gemini-2.5-flash' // optional, this is the default
});
console.log(title); // e.g., "User Authentication Flow"Using OpenRouter API
import { generateTitle } from 'diagram-title-generator';
const title = await generateTitle(diagramData, {
apiKey: process.env.OPENROUTER_API_KEY,
provider: 'openrouter',
model: 'google/gemini-2.0-flash-lite-preview' // optional, this is the default
});🔑 API Key Setup
Getting a Gemini API Key
- Visit Google AI Studio
- Click "Get API Key"
- Copy your key and add to your project:
# .env file
GEMINI_API_KEY=your_api_key_hereGetting an OpenRouter API Key
- Visit OpenRouter
- Sign up and navigate to "Keys"
- Create a new API key
- Add to your project:
# .env file
OPENROUTER_API_KEY=your_api_key_here🧪 Local Testing
1. Clone and Install
git clone <your-repo-url>
cd diagram-title-generator
npm install2. Build the Package
npm run buildThis generates files in dist/:
index.js(CommonJS)index.mjs(ESM)index.d.ts(TypeScript types)
3. Create a Test File
Create local-test.js in the project root:
// local-test.js
require('dotenv').config(); // if using dotenv
const { generateTitle } = require('./dist/index.js');
const mockDiagram = {
nodes: [
{ text: 'Start', type: 'StartEvent' },
{ text: 'Process Order', type: 'Task' },
{ text: 'Payment Gateway', type: 'Service' },
{ text: 'End', type: 'EndEvent' }
]
};
async function test() {
try {
// Test with Gemini
const title = await generateTitle(mockDiagram, {
apiKey: process.env.GEMINI_API_KEY,
provider: 'google'
});
console.log('Generated Title:', title);
} catch (error) {
console.error('Error:', error.message);
}
}
test();4. Run the Test
# Set your API key inline (macOS/Linux)
GEMINI_API_KEY=your_key_here node local-test.js
# Or use dotenv
npm install dotenv
node local-test.js🧪 Testing
The package includes a comprehensive test suite with 97%+ code coverage.
Run Tests
# Run all unit tests
npm test
# Watch mode (re-runs on file changes)
npm run test:watch
# Generate coverage report
npm run test:coverage
# Interactive UI
npm run test:uiTest Structure
- Unit Tests (
extractor.test.ts) - 22 tests covering semantic extraction, circular references, depth limiting, and edge cases - Generator Tests (
generator.test.ts) - 22 tests with mocked API calls for both providers - Integration Tests (
integration.test.ts) - Optional real API tests (requires API keys)
Integration Tests (Optional)
To run tests with real API calls:
# 1. Copy environment template
cp .env.example .env
# 2. Add your API keys to .env
# GEMINI_API_KEY=your_real_key
# OPENROUTER_API_KEY=your_real_key
# 3. Run integration tests
npm run test:integrationNote: Integration tests are automatically skipped if API keys are not available.
🔧 Configuration Options
interface TitleOptions {
/** API Key for the selected provider (required) */
apiKey: string;
/** Provider to use (optional, defaults to 'google') */
provider?: 'google' | 'openrouter';
/** Model to use (optional) */
model?: string;
/** Custom base URL for proxy/self-hosted APIs (optional) */
baseUrl?: string;
/** If true, throws errors instead of returning fallback title (optional, defaults to false) */
throwOnError?: boolean;
}Error Handling
By default, the package returns "Untitled Diagram" if generation fails (network errors, invalid API keys, etc.). This ensures your application doesn't crash.
For stricter error handling, use throwOnError:
try {
const title = await generateTitle(diagramData, {
apiKey: process.env.GEMINI_API_KEY,
provider: 'google',
throwOnError: true // Throws on any error
});
console.log(title);
} catch (error) {
// Handle the error explicitly
console.error('Title generation failed:', error.message);
// Implement your own fallback logic
}Default Models
- Gemini:
gemini-2.5-flash - OpenRouter:
google/gemini-2.0-flash-lite-preview
Custom Models
// Use GPT-4 via OpenRouter
const title = await generateTitle(diagramData, {
apiKey: process.env.OPENROUTER_API_KEY,
provider: 'openrouter',
model: 'openai/gpt-4-turbo'
});
// Use a different Gemini model
const title = await generateTitle(diagramData, {
apiKey: process.env.GEMINI_API_KEY,
provider: 'google',
model: 'gemini-1.5-pro'
});📚 Usage in Existing Projects
React / Next.js
// components/DiagramTitleGenerator.tsx
import { generateTitle } from 'diagram-title-generator';
import { useState } from 'react';
export function DiagramTitleGenerator({ diagramData }) {
const [title, setTitle] = useState('');
async function handleGenerate() {
const result = await generateTitle(diagramData, {
apiKey: process.env.NEXT_PUBLIC_GEMINI_API_KEY,
provider: 'google'
});
setTitle(result);
}
return (
<div>
<button onClick={handleGenerate}>Generate Title</button>
<h2>{title}</h2>
</div>
);
}Node.js / Express API
// routes/diagram.ts
import { generateTitle } from 'diagram-title-generator';
app.post('/api/diagram/title', async (req, res) => {
try {
const { diagramData } = req.body;
const title = await generateTitle(diagramData, {
apiKey: process.env.GEMINI_API_KEY,
provider: 'google'
});
res.json({ title });
} catch (error) {
res.status(500).json({ error: error.message });
}
});Edge Runtime (Vercel, Cloudflare Workers)
// api/generate-title.ts
import { generateTitle } from 'diagram-title-generator';
export const config = { runtime: 'edge' };
export default async function handler(req: Request) {
const { diagramData } = await req.json();
const title = await generateTitle(diagramData, {
apiKey: process.env.OPENROUTER_API_KEY,
provider: 'openrouter'
});
return new Response(JSON.stringify({ title }), {
headers: { 'content-type': 'application/json' }
});
}🧩 Supported Diagram Structures
The library intelligently extracts context from any JSON structure. It works with:
Flowcharts
{
nodes: [{ text: 'Step 1', type: 'Process' }],
edges: []
}Mind Maps
{
central: 'Main Idea',
branches: [
{ label: 'Branch 1', children: [] }
]
}Entity Relationships
{
entities: [
{ name: 'User', type: 'Person' },
{ name: 'Order', type: 'Transaction' }
]
}Custom Formats
The extractor prioritizes these fields:
text,label,content,title,name,headertype(for semantic info like "Process", "Database")
⚠️ Important Notes
API Key Security
Never commit API keys to version control!
✅ Good Practices:
# .env (add to .gitignore)
GEMINI_API_KEY=your_key_here
# Use environment variables
const title = await generateTitle(data, {
apiKey: process.env.GEMINI_API_KEY
});❌ Bad Practice:
// NEVER do this
const title = await generateTitle(data, {
apiKey: 'hardcoded-key-here' // ❌ Security risk!
});Client-Side Usage
For browser usage, use a backend proxy to protect your API key:
// ❌ Don't expose API keys in client code
// ✅ Instead, call your own API endpoint
async function getTitle(diagramData) {
const response = await fetch('/api/generate-title', {
method: 'POST',
body: JSON.stringify({ diagramData })
});
return response.json();
}🛠️ Development
# Install dependencies
npm install
# Build the package
npm run build
# Watch mode for development
npm run dev
# Run basic test
npm test📄 License
MIT
🤝 Contributing
Contributions are welcome! Please open an issue or submit a pull request.
🔗 Resources
Built with ❤️ for developers who need smart diagram titles
