orchestrated-discussions/.venv/lib/python3.12/site-packages/artifact_editor/templates.py

1729 lines
57 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Diagram templates for quick-start examples."""
# Templates organized by format, then by category
PLANTUML_TEMPLATES = {
'class': {
'Basic Class Diagram': {
'description': 'Simple class with attributes and methods',
'code': '''@startuml
title Basic Class Diagram
class User {
+id: int
+name: String
+email: String
--
+login()
+logout()
}
class Order {
+id: int
+date: Date
+total: float
--
+addItem(item)
+removeItem(item)
+calculateTotal(): float
}
User "1" --> "*" Order : places
@enduml'''
},
'Inheritance Example': {
'description': 'Class hierarchy with inheritance and interfaces',
'code': '''@startuml
title Inheritance and Interfaces
interface Drawable {
+draw()
+resize(scale)
}
abstract class Shape {
#x: int
#y: int
+move(dx, dy)
{abstract} +area(): float
}
class Circle {
-radius: float
+area(): float
+draw()
}
class Rectangle {
-width: float
-height: float
+area(): float
+draw()
}
Drawable <|.. Shape
Shape <|-- Circle
Shape <|-- Rectangle
@enduml'''
},
},
'sequence': {
'Basic Sequence': {
'description': 'Simple request-response flow',
'code': '''@startuml
title Basic API Request Flow
actor User
participant "Web App" as App
participant "API Server" as API
database "Database" as DB
User -> App: Click Login
activate App
App -> API: POST /auth/login
activate API
API -> DB: SELECT user
activate DB
DB --> API: user data
deactivate DB
API --> App: JWT token
deactivate API
App --> User: Show dashboard
deactivate App
@enduml'''
},
'Authentication Flow': {
'description': 'OAuth2 authentication sequence',
'code': '''@startuml
title OAuth2 Authentication Flow
actor User
participant "Client App" as Client
participant "Auth Server" as Auth
participant "Resource Server" as Resource
User -> Client: Login request
Client -> Auth: Authorization request
Auth -> User: Login page
User -> Auth: Credentials
Auth -> Auth: Validate credentials
alt successful login
Auth --> Client: Authorization code
Client -> Auth: Exchange code for token
Auth --> Client: Access token + Refresh token
Client -> Resource: API request + Access token
Resource --> Client: Protected resource
Client --> User: Display data
else invalid credentials
Auth --> Client: Error
Client --> User: Show error
end
@enduml'''
},
},
'component': {
'System Architecture': {
'description': 'High-level system components',
'code': '''@startuml
title System Architecture
package "Frontend" {
[Web Application] as Web
[Mobile App] as Mobile
}
package "Backend Services" {
[API Gateway] as Gateway
[User Service] as UserSvc
[Order Service] as OrderSvc
}
package "Data Layer" {
database "PostgreSQL" as PG
database "Redis Cache" as Redis
}
Web --> Gateway
Mobile --> Gateway
Gateway --> UserSvc
Gateway --> OrderSvc
UserSvc --> PG
OrderSvc --> PG
Gateway --> Redis
@enduml'''
},
},
'state': {
'Order State Machine': {
'description': 'Order lifecycle states',
'code': '''@startuml
title Order State Machine
[*] --> Draft : create order
Draft --> Pending : submit
Draft --> Cancelled : cancel
Pending --> Confirmed : payment received
Pending --> Cancelled : payment failed
Confirmed --> Processing : begin fulfillment
Processing --> Shipped : dispatch
Shipped --> Delivered : delivery confirmed
Delivered --> [*]
Cancelled --> [*]
@enduml'''
},
},
'activity': {
'Checkout Process': {
'description': 'E-commerce checkout flow',
'code': '''@startuml
title Checkout Process
start
:View Cart;
if (Cart empty?) then (yes)
:Show empty cart message;
stop
endif
:Enter Shipping Address;
:Select Shipping Method;
:Enter Payment Details;
:Validate Payment;
if (Payment valid?) then (yes)
:Process Payment;
:Create Order;
:Send Confirmation Email;
:Show Success Page;
else (no)
:Show Payment Error;
endif
stop
@enduml'''
},
},
'mindmap': {
'Project Planning': {
'description': 'Project breakdown structure',
'code': '''@startmindmap
title Project Planning
* Project Launch
** Planning
*** Define scope
*** Set milestones
*** Allocate resources
** Development
*** Backend
**** API endpoints
**** Database layer
*** Frontend
**** Components
**** Styling
** Testing
*** Unit tests
*** Integration tests
** Deployment
*** CI/CD setup
*** Production release
@endmindmap'''
},
},
}
MERMAID_TEMPLATES = {
'flowchart': {
'Basic Flowchart': {
'description': 'Simple decision flowchart',
'code': '''flowchart TD
A[Start] --> B{Is it working?}
B -->|Yes| C[Great!]
B -->|No| D[Debug]
D --> B
C --> E[End]'''
},
'Process Flow': {
'description': 'Business process with multiple paths',
'code': '''flowchart LR
subgraph Input
A[User Request] --> B[Validate]
end
subgraph Processing
B --> C{Valid?}
C -->|Yes| D[Process]
C -->|No| E[Return Error]
D --> F[Store Result]
end
subgraph Output
F --> G[Send Response]
E --> G
end'''
},
'Top-Down Flow': {
'description': 'Vertical flowchart with conditions',
'code': '''flowchart TB
Start([Start]) --> Input[/Get Input/]
Input --> Validate{Valid Input?}
Validate -->|Yes| Process[Process Data]
Validate -->|No| Error[Show Error]
Error --> Input
Process --> Save[(Save to DB)]
Save --> Output[/Display Result/]
Output --> End([End])'''
},
},
'sequence': {
'Basic Sequence': {
'description': 'Simple API request flow',
'code': '''sequenceDiagram
actor User
participant App as Web App
participant API as API Server
participant DB as Database
User->>App: Click Login
activate App
App->>API: POST /auth/login
activate API
API->>DB: Query user
DB-->>API: User data
API-->>App: JWT Token
deactivate API
App-->>User: Show Dashboard
deactivate App'''
},
'Async Messaging': {
'description': 'Asynchronous message flow with loops',
'code': '''sequenceDiagram
participant Client
participant Server
participant Queue
participant Worker
Client->>+Server: Submit Job
Server->>Queue: Enqueue Job
Server-->>-Client: Job ID
loop Process Queue
Worker->>Queue: Poll for jobs
Queue-->>Worker: Job data
Worker->>Worker: Process
Worker->>Queue: Mark complete
end
Client->>Server: Check Status
Server-->>Client: Job Complete'''
},
},
'class': {
'Basic Class Diagram': {
'description': 'Classes with relationships',
'code': '''classDiagram
class Animal {
+String name
+int age
+makeSound()
}
class Dog {
+String breed
+bark()
+fetch()
}
class Cat {
+bool indoor
+meow()
+scratch()
}
Animal <|-- Dog
Animal <|-- Cat'''
},
'E-commerce Model': {
'description': 'Domain model with associations',
'code': '''classDiagram
class Customer {
+String id
+String name
+String email
+placeOrder()
}
class Order {
+String id
+Date date
+String status
+calculateTotal()
}
class Product {
+String id
+String name
+float price
}
class OrderItem {
+int quantity
+float unitPrice
}
Customer "1" --> "*" Order : places
Order "1" *-- "*" OrderItem : contains
OrderItem "*" --> "1" Product : references'''
},
},
'state': {
'Order States': {
'description': 'Order lifecycle state machine',
'code': '''stateDiagram-v2
[*] --> Draft
Draft --> Pending: submit
Draft --> Cancelled: cancel
Pending --> Confirmed: payment
Pending --> Cancelled: timeout
Confirmed --> Shipped: dispatch
Shipped --> Delivered: arrive
Delivered --> [*]
Cancelled --> [*]'''
},
'Traffic Light': {
'description': 'Simple state transitions',
'code': '''stateDiagram-v2
[*] --> Red
Red --> Green: timer
Green --> Yellow: timer
Yellow --> Red: timer
state Red {
[*] --> Waiting
Waiting --> Pedestrian: button
Pedestrian --> Waiting: timer
}'''
},
},
'er': {
'Blog Database': {
'description': 'Blog entity relationships',
'code': '''erDiagram
USER ||--o{ POST : writes
USER ||--o{ COMMENT : writes
POST ||--o{ COMMENT : has
POST }o--o{ TAG : has
USER {
uuid id PK
string username
string email
string password_hash
}
POST {
uuid id PK
uuid author_id FK
string title
text content
datetime published_at
}
COMMENT {
uuid id PK
uuid post_id FK
uuid user_id FK
text content
}
TAG {
uuid id PK
string name
}'''
},
},
'pie': {
'Simple Pie Chart': {
'description': 'Distribution pie chart',
'code': '''pie title Project Time Distribution
"Development" : 45
"Testing" : 25
"Documentation" : 15
"Meetings" : 15'''
},
},
'gantt': {
'Project Timeline': {
'description': 'Project schedule with dependencies',
'code': '''gantt
title Project Timeline
dateFormat YYYY-MM-DD
section Planning
Requirements :a1, 2024-01-01, 7d
Design :a2, after a1, 14d
section Development
Backend API :b1, after a2, 21d
Frontend UI :b2, after a2, 21d
Integration :b3, after b1, 7d
section Testing
QA Testing :c1, after b3, 14d
Bug Fixes :c2, after c1, 7d
section Deployment
Release :d1, after c2, 3d'''
},
},
}
OPENSCAD_TEMPLATES = {
'primitives': {
'Basic Shapes': {
'description': 'Cube, sphere, and cylinder primitives',
'code': '''// Basic 3D Primitives
$fn = 32; // Smoothness
// Cube
translate([-30, 0, 0])
cube([15, 15, 15], center=true);
// Sphere
sphere(r=10);
// Cylinder
translate([30, 0, 0])
cylinder(h=20, r=8, center=true);'''
},
'2D Shapes': {
'description': 'Circle, square, and polygon',
'code': '''// 2D Shapes (for extrusion)
$fn = 32;
// Circle
translate([-30, 0, 0])
circle(r=10);
// Square
square([15, 15], center=true);
// Polygon
translate([30, 0, 0])
polygon(points=[
[0, 15],
[-13, -7.5],
[13, -7.5]
]);'''
},
},
'operations': {
'Boolean Operations': {
'description': 'Union, difference, and intersection',
'code': '''// Boolean Operations Demo
$fn = 32;
// Difference: cube with spherical hole
translate([-35, 0, 0])
difference() {
cube([20, 20, 20], center=true);
sphere(r=12);
}
// Union: combined shapes
union() {
cube([15, 15, 15], center=true);
sphere(r=10);
}
// Intersection: overlapping volume
translate([35, 0, 0])
intersection() {
cube([20, 20, 20], center=true);
sphere(r=14);
}'''
},
'Extrusions': {
'description': 'Linear and rotational extrusion',
'code': '''// Extrusion Examples
$fn = 32;
// Linear extrude a shape
translate([-25, 0, 0])
linear_extrude(height=20, twist=45)
square([10, 10], center=true);
// Rotate extrude (lathe)
translate([25, 0, 0])
rotate_extrude()
translate([10, 0, 0])
circle(r=5);'''
},
},
'transforms': {
'Transformations': {
'description': 'Translate, rotate, and scale',
'code': '''// Transformation Examples
$fn = 32;
// Original
color("red")
cube([10, 10, 10], center=true);
// Translated
color("green")
translate([20, 0, 0])
cube([10, 10, 10], center=true);
// Rotated
color("blue")
translate([40, 0, 0])
rotate([45, 0, 45])
cube([10, 10, 10], center=true);
// Scaled
color("yellow")
translate([60, 0, 0])
scale([1.5, 0.5, 1])
cube([10, 10, 10], center=true);'''
},
'Mirror and Hull': {
'description': 'Mirror and convex hull operations',
'code': '''// Mirror and Hull Examples
$fn = 32;
// Mirror operation
translate([-30, 0, 0]) {
sphere(r=5);
mirror([1, 0, 0])
translate([15, 0, 0])
sphere(r=5);
}
// Hull: convex wrapper around shapes
translate([20, 0, 0])
hull() {
sphere(r=5);
translate([20, 0, 0])
sphere(r=5);
translate([10, 15, 0])
sphere(r=5);
}'''
},
},
'modules': {
'Custom Module': {
'description': 'Reusable parametric module',
'code': '''// Parametric Module Example
$fn = 32;
// Define a rounded box module
module rounded_box(size, radius) {
hull() {
for (x = [-1, 1])
for (y = [-1, 1])
for (z = [-1, 1])
translate([
x * (size[0]/2 - radius),
y * (size[1]/2 - radius),
z * (size[2]/2 - radius)
])
sphere(r=radius);
}
}
// Use the module
rounded_box([30, 20, 15], 3);
translate([40, 0, 0])
rounded_box([20, 20, 20], 5);'''
},
'Gear Module': {
'description': 'Simple parametric gear',
'code': '''// Simple Gear Module
$fn = 64;
module gear(teeth, tooth_size, thickness, hole_r) {
difference() {
union() {
// Base cylinder
cylinder(h=thickness, r=teeth*tooth_size/6.28, center=true);
// Teeth
for (i = [0:teeth-1]) {
rotate([0, 0, i * 360/teeth])
translate([teeth*tooth_size/6.28, 0, 0])
cylinder(h=thickness, r=tooth_size/2, center=true);
}
}
// Center hole
cylinder(h=thickness+1, r=hole_r, center=true);
}
}
// Create a gear
gear(teeth=12, tooth_size=5, thickness=5, hole_r=3);'''
},
},
'mechanical': {
'Enclosure Box': {
'description': 'Box with lid for electronics',
'code': '''// Electronics Enclosure
$fn = 32;
box_size = [60, 40, 25];
wall = 2;
lid_height = 8;
// Bottom part
module box_bottom() {
difference() {
cube(box_size, center=true);
translate([0, 0, wall])
cube([
box_size[0] - wall*2,
box_size[1] - wall*2,
box_size[2]
], center=true);
}
}
// Lid
module box_lid() {
translate([0, 0, box_size[2]/2 + lid_height/2 + 2])
difference() {
cube([box_size[0], box_size[1], lid_height], center=true);
translate([0, 0, -wall])
cube([
box_size[0] - wall*4,
box_size[1] - wall*4,
lid_height
], center=true);
}
}
box_bottom();
box_lid();'''
},
'Bracket': {
'description': 'L-shaped mounting bracket',
'code': '''// Mounting Bracket
$fn = 32;
thickness = 3;
width = 20;
leg1 = 30;
leg2 = 25;
hole_d = 5;
hole_margin = 8;
module bracket() {
difference() {
union() {
// Vertical leg
cube([width, thickness, leg1]);
// Horizontal leg
cube([width, leg2, thickness]);
// Fillet/gusset
translate([0, thickness, thickness])
rotate([0, 90, 0])
linear_extrude(width)
polygon([[0,0], [8,0], [0,8]]);
}
// Mounting holes
translate([width/2, -1, leg1 - hole_margin])
rotate([-90, 0, 0])
cylinder(h=thickness+2, d=hole_d);
translate([width/2, leg2 - hole_margin, -1])
cylinder(h=thickness+2, d=hole_d);
}
}
bracket();'''
},
},
}
CODE_TEMPLATES = {
'python': {
'Hello World': {
'description': 'Simple Python hello world',
'language': 'python',
'code': '''def hello_world():
"""A simple example function."""
print("Hello, World!")
if __name__ == "__main__":
hello_world()'''
},
'Class Example': {
'description': 'Python class with methods',
'language': 'python',
'code': '''class Rectangle:
"""A simple rectangle class."""
def __init__(self, width: float, height: float):
self.width = width
self.height = height
@property
def area(self) -> float:
"""Calculate the area of the rectangle."""
return self.width * self.height
@property
def perimeter(self) -> float:
"""Calculate the perimeter of the rectangle."""
return 2 * (self.width + self.height)
def __repr__(self) -> str:
return f"Rectangle({self.width}, {self.height})"
# Example usage
rect = Rectangle(10, 5)
print(f"Area: {rect.area}")
print(f"Perimeter: {rect.perimeter}")'''
},
'FastAPI Endpoint': {
'description': 'FastAPI route handler example',
'language': 'python',
'code': '''from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List, Optional
app = FastAPI()
class Item(BaseModel):
id: int
name: str
description: Optional[str] = None
price: float
items_db: List[Item] = []
@app.get("/items", response_model=List[Item])
async def get_items():
"""Get all items."""
return items_db
@app.get("/items/{item_id}", response_model=Item)
async def get_item(item_id: int):
"""Get a specific item by ID."""
for item in items_db:
if item.id == item_id:
return item
raise HTTPException(status_code=404, detail="Item not found")
@app.post("/items", response_model=Item)
async def create_item(item: Item):
"""Create a new item."""
items_db.append(item)
return item'''
},
},
'javascript': {
'Hello World': {
'description': 'Simple JavaScript hello world',
'language': 'javascript',
'code': '''// Hello World in JavaScript
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet("World"));'''
},
'Async/Await Example': {
'description': 'Async function with fetch',
'language': 'javascript',
'code': '''// Async/Await API fetch example
async function fetchUserData(userId) {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const userData = await response.json();
return userData;
} catch (error) {
console.error("Failed to fetch user data:", error);
throw error;
}
}
// Usage
async function main() {
const user = await fetchUserData(123);
console.log("User:", user);
}
main();'''
},
'React Component': {
'description': 'React functional component with hooks',
'language': 'jsx',
'code': '''import React, { useState, useEffect } from 'react';
function Counter({ initialValue = 0 }) {
const [count, setCount] = useState(initialValue);
useEffect(() => {
document.title = `Count: ${count}`;
}, [count]);
const increment = () => setCount(c => c + 1);
const decrement = () => setCount(c => c - 1);
const reset = () => setCount(initialValue);
return (
<div className="counter">
<h2>Count: {count}</h2>
<div className="buttons">
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
<button onClick={increment}>+</button>
</div>
</div>
);
}
export default Counter;'''
},
},
'rust': {
'Hello World': {
'description': 'Simple Rust hello world',
'language': 'rust',
'code': '''fn main() {
println!("Hello, World!");
}'''
},
'Struct Example': {
'description': 'Rust struct with implementation',
'language': 'rust',
'code': '''use std::fmt;
#[derive(Debug)]
struct Rectangle {
width: f64,
height: f64,
}
impl Rectangle {
fn new(width: f64, height: f64) -> Self {
Rectangle { width, height }
}
fn area(&self) -> f64 {
self.width * self.height
}
fn perimeter(&self) -> f64 {
2.0 * (self.width + self.height)
}
fn is_square(&self) -> bool {
(self.width - self.height).abs() < f64::EPSILON
}
}
impl fmt::Display for Rectangle {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Rectangle({}x{})", self.width, self.height)
}
}
fn main() {
let rect = Rectangle::new(10.0, 5.0);
println!("{}", rect);
println!("Area: {}", rect.area());
println!("Perimeter: {}", rect.perimeter());
println!("Is square: {}", rect.is_square());
}'''
},
},
'go': {
'Hello World': {
'description': 'Simple Go hello world',
'language': 'go',
'code': '''package main
import "fmt"
func main() {
fmt.Println("Hello, World!")
}'''
},
'HTTP Server': {
'description': 'Simple Go HTTP server',
'language': 'go',
'code': '''package main
import (
"encoding/json"
"log"
"net/http"
)
type Response struct {
Message string `json:"message"`
Status int `json:"status"`
}
func helloHandler(w http.ResponseWriter, r *http.Request) {
response := Response{
Message: "Hello, World!",
Status: 200,
}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
func main() {
http.HandleFunc("/", helloHandler)
log.Println("Server starting on :8080...")
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
}'''
},
},
'sql': {
'Create Table': {
'description': 'SQL table creation with constraints',
'language': 'sql',
'code': '''-- Create users table
CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create orders table with foreign key
CREATE TABLE orders (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
total_amount DECIMAL(10, 2) NOT NULL,
status VARCHAR(20) DEFAULT 'pending',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Create index for faster lookups
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE INDEX idx_orders_status ON orders(status);'''
},
'Common Queries': {
'description': 'Common SQL query patterns',
'language': 'sql',
'code': '''-- Select with join
SELECT
u.username,
u.email,
COUNT(o.id) as order_count,
COALESCE(SUM(o.total_amount), 0) as total_spent
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
GROUP BY u.id, u.username, u.email
ORDER BY total_spent DESC;
-- Subquery example
SELECT * FROM users
WHERE id IN (
SELECT DISTINCT user_id
FROM orders
WHERE total_amount > 100
);
-- Window function
SELECT
username,
total_amount,
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) as order_rank
FROM users u
JOIN orders o ON u.id = o.user_id;'''
},
},
'bash': {
'Script Template': {
'description': 'Bash script with common patterns',
'language': 'bash',
'code': '''#!/bin/bash
# Script description
# Usage: ./script.sh [options]
set -euo pipefail # Exit on error, undefined vars, pipe failures
# Constants
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly LOG_FILE="/tmp/script.log"
# Functions
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
die() {
log "ERROR: $*"
exit 1
}
usage() {
cat <<EOF
Usage: $(basename "$0") [OPTIONS]
Options:
-h, --help Show this help message
-v, --verbose Enable verbose output
-f, --file Input file path
EOF
exit 0
}
# Parse arguments
VERBOSE=false
INPUT_FILE=""
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help) usage ;;
-v|--verbose) VERBOSE=true; shift ;;
-f|--file) INPUT_FILE="$2"; shift 2 ;;
*) die "Unknown option: $1" ;;
esac
done
# Main logic
main() {
log "Starting script..."
if [[ -n "$INPUT_FILE" ]]; then
log "Processing file: $INPUT_FILE"
fi
log "Done!"
}
main "$@"'''
},
},
'html': {
'Basic Page': {
'description': 'HTML5 page template',
'language': 'html',
'code': '''<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Page</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
color: #333;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 2rem;
}
header {
background: #2c3e50;
color: white;
padding: 1rem 0;
}
</style>
</head>
<body>
<header>
<div class="container">
<h1>Welcome</h1>
</div>
</header>
<main class="container">
<h2>Hello, World!</h2>
<p>This is a basic HTML5 template.</p>
</main>
<script>
console.log('Page loaded!');
</script>
</body>
</html>'''
},
},
}
# SVG Templates for wireframes and diagrams
SVG_TEMPLATES = {
'wireframes': {
'Login Page': {
'description': 'Simple login form wireframe',
'code': '''<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 500" width="400" height="500">
<rect width="100%" height="100%" fill="#f9fafb"/>
<!-- Card container -->
<rect x="50" y="80" width="300" height="340" rx="8" fill="#ffffff" stroke="#e5e7eb"/>
<!-- Logo placeholder -->
<circle cx="200" cy="130" r="30" fill="#e5e7eb"/>
<text x="200" y="135" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#9ca3af">Logo</text>
<!-- Title -->
<text x="200" y="190" text-anchor="middle" font-family="sans-serif" font-size="20" font-weight="bold" fill="#111827">Welcome Back</text>
<!-- Email input -->
<text x="70" y="230" font-family="sans-serif" font-size="12" fill="#374151">Email</text>
<rect x="70" y="240" width="260" height="40" rx="4" fill="#ffffff" stroke="#d1d5db"/>
<text x="82" y="265" font-family="sans-serif" font-size="14" fill="#9ca3af">you@example.com</text>
<!-- Password input -->
<text x="70" y="300" font-family="sans-serif" font-size="12" fill="#374151">Password</text>
<rect x="70" y="310" width="260" height="40" rx="4" fill="#ffffff" stroke="#d1d5db"/>
<text x="82" y="335" font-family="sans-serif" font-size="14" fill="#9ca3af">••••••••</text>
<!-- Sign in button -->
<rect x="70" y="370" width="260" height="40" rx="4" fill="#3b82f6"/>
<text x="200" y="395" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#ffffff">Sign In</text>
<!-- Forgot password link -->
<text x="200" y="435" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#3b82f6">Forgot password?</text>
</svg>'''
},
'Dashboard Layout': {
'description': 'Dashboard with sidebar and cards',
'code': '''<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600" width="800" height="600">
<rect width="100%" height="100%" fill="#f3f4f6"/>
<!-- Sidebar -->
<rect x="0" y="0" width="200" height="600" fill="#1f2937"/>
<text x="20" y="40" font-family="sans-serif" font-size="20" font-weight="bold" fill="#ffffff">Dashboard</text>
<!-- Sidebar menu items -->
<rect x="0" y="70" width="200" height="40" fill="#374151"/>
<text x="20" y="95" font-family="sans-serif" font-size="14" fill="#ffffff">Overview</text>
<text x="20" y="135" font-family="sans-serif" font-size="14" fill="#9ca3af">Analytics</text>
<text x="20" y="175" font-family="sans-serif" font-size="14" fill="#9ca3af">Reports</text>
<text x="20" y="215" font-family="sans-serif" font-size="14" fill="#9ca3af">Settings</text>
<!-- Top header -->
<rect x="200" y="0" width="600" height="60" fill="#ffffff" stroke="#e5e7eb"/>
<text x="220" y="38" font-family="sans-serif" font-size="18" fill="#111827">Welcome back, User</text>
<!-- Search box -->
<rect x="500" y="15" width="180" height="30" rx="4" fill="#f3f4f6" stroke="#d1d5db"/>
<text x="515" y="35" font-family="sans-serif" font-size="12" fill="#9ca3af">Search...</text>
<!-- Avatar -->
<circle cx="760" cy="30" r="18" fill="#e5e7eb"/>
<!-- Stats cards -->
<rect x="220" y="80" width="170" height="100" rx="8" fill="#ffffff" stroke="#e5e7eb"/>
<text x="240" y="115" font-family="sans-serif" font-size="12" fill="#6b7280">Total Users</text>
<text x="240" y="150" font-family="sans-serif" font-size="28" font-weight="bold" fill="#111827">12,345</text>
<rect x="410" y="80" width="170" height="100" rx="8" fill="#ffffff" stroke="#e5e7eb"/>
<text x="430" y="115" font-family="sans-serif" font-size="12" fill="#6b7280">Revenue</text>
<text x="430" y="150" font-family="sans-serif" font-size="28" font-weight="bold" fill="#111827">$54,321</text>
<rect x="600" y="80" width="170" height="100" rx="8" fill="#ffffff" stroke="#e5e7eb"/>
<text x="620" y="115" font-family="sans-serif" font-size="12" fill="#6b7280">Orders</text>
<text x="620" y="150" font-family="sans-serif" font-size="28" font-weight="bold" fill="#111827">1,234</text>
<!-- Main content area -->
<rect x="220" y="200" width="550" height="280" rx="8" fill="#ffffff" stroke="#e5e7eb"/>
<text x="240" y="230" font-family="sans-serif" font-size="16" font-weight="bold" fill="#111827">Recent Activity</text>
<!-- Chart placeholder -->
<rect x="240" y="250" width="510" height="200" rx="4" fill="#f9fafb" stroke="#e5e7eb" stroke-dasharray="4,4"/>
<text x="495" y="355" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#9ca3af">Chart Placeholder</text>
</svg>'''
},
'Mobile App Screen': {
'description': 'Mobile app layout wireframe',
'code': '''<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 375 812" width="375" height="812">
<!-- Phone frame -->
<rect width="100%" height="100%" fill="#ffffff" rx="40"/>
<!-- Status bar -->
<rect x="0" y="0" width="375" height="44" fill="#f9fafb"/>
<text x="187" y="28" text-anchor="middle" font-family="sans-serif" font-size="14" font-weight="bold" fill="#111827">9:41</text>
<!-- Header -->
<rect x="0" y="44" width="375" height="56" fill="#ffffff" stroke="#e5e7eb"/>
<text x="20" y="78" font-family="sans-serif" font-size="24" fill="#3b82f6">←</text>
<text x="187" y="80" text-anchor="middle" font-family="sans-serif" font-size="17" font-weight="bold" fill="#111827">Profile</text>
<!-- Profile section -->
<circle cx="187" cy="170" r="50" fill="#e5e7eb"/>
<text x="187" y="175" text-anchor="middle" font-family="sans-serif" font-size="16" fill="#9ca3af">Photo</text>
<text x="187" y="245" text-anchor="middle" font-family="sans-serif" font-size="22" font-weight="bold" fill="#111827">John Doe</text>
<text x="187" y="270" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#6b7280">john@example.com</text>
<!-- Menu items -->
<g transform="translate(0, 300)">
<rect x="20" y="0" width="335" height="56" fill="#ffffff"/>
<line x1="20" y1="56" x2="355" y2="56" stroke="#e5e7eb"/>
<text x="40" y="35" font-family="sans-serif" font-size="16" fill="#111827">Edit Profile</text>
<text x="335" y="35" font-family="sans-serif" font-size="20" fill="#9ca3af"></text>
<rect x="20" y="56" width="335" height="56" fill="#ffffff"/>
<line x1="20" y1="112" x2="355" y2="112" stroke="#e5e7eb"/>
<text x="40" y="91" font-family="sans-serif" font-size="16" fill="#111827">Notifications</text>
<text x="335" y="91" font-family="sans-serif" font-size="20" fill="#9ca3af"></text>
<rect x="20" y="112" width="335" height="56" fill="#ffffff"/>
<line x1="20" y1="168" x2="355" y2="168" stroke="#e5e7eb"/>
<text x="40" y="147" font-family="sans-serif" font-size="16" fill="#111827">Privacy</text>
<text x="335" y="147" font-family="sans-serif" font-size="20" fill="#9ca3af"></text>
<rect x="20" y="168" width="335" height="56" fill="#ffffff"/>
<text x="40" y="203" font-family="sans-serif" font-size="16" fill="#111827">Help & Support</text>
<text x="335" y="203" font-family="sans-serif" font-size="20" fill="#9ca3af"></text>
</g>
<!-- Logout button -->
<rect x="40" y="580" width="295" height="48" rx="8" fill="none" stroke="#ef4444"/>
<text x="187" y="610" text-anchor="middle" font-family="sans-serif" font-size="16" fill="#ef4444">Log Out</text>
<!-- Tab bar -->
<rect x="0" y="730" width="375" height="82" fill="#ffffff" stroke="#e5e7eb"/>
<text x="62" y="770" text-anchor="middle" font-family="sans-serif" font-size="10" fill="#9ca3af">Home</text>
<text x="145" y="770" text-anchor="middle" font-family="sans-serif" font-size="10" fill="#9ca3af">Search</text>
<text x="230" y="770" text-anchor="middle" font-family="sans-serif" font-size="10" fill="#3b82f6">Profile</text>
<text x="313" y="770" text-anchor="middle" font-family="sans-serif" font-size="10" fill="#9ca3af">Settings</text>
</svg>'''
},
},
'diagrams': {
'Simple Flowchart': {
'description': 'Basic flowchart with shapes and arrows',
'code': '''<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 400" width="600" height="400">
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#374151"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#ffffff"/>
<!-- Start (oval) -->
<ellipse cx="300" cy="40" rx="60" ry="25" fill="#10b981" stroke="#059669" stroke-width="2"/>
<text x="300" y="46" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#ffffff">Start</text>
<!-- Arrow down -->
<line x1="300" y1="65" x2="300" y2="100" stroke="#374151" stroke-width="2" marker-end="url(#arrowhead)"/>
<!-- Process box -->
<rect x="220" y="110" width="160" height="50" rx="4" fill="#3b82f6" stroke="#2563eb" stroke-width="2"/>
<text x="300" y="140" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#ffffff">Process Data</text>
<!-- Arrow down -->
<line x1="300" y1="160" x2="300" y2="195" stroke="#374151" stroke-width="2" marker-end="url(#arrowhead)"/>
<!-- Decision diamond -->
<polygon points="300,200 380,250 300,300 220,250" fill="#fbbf24" stroke="#d97706" stroke-width="2"/>
<text x="300" y="255" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#111827">Valid?</text>
<!-- Yes path -->
<line x1="380" y1="250" x2="450" y2="250" stroke="#374151" stroke-width="2" marker-end="url(#arrowhead)"/>
<text x="410" y="240" font-family="sans-serif" font-size="12" fill="#374151">Yes</text>
<rect x="460" y="225" width="100" height="50" rx="4" fill="#10b981" stroke="#059669" stroke-width="2"/>
<text x="510" y="255" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#ffffff">Save</text>
<!-- No path -->
<line x1="220" y1="250" x2="150" y2="250" stroke="#374151" stroke-width="2" marker-end="url(#arrowhead)"/>
<text x="180" y="240" font-family="sans-serif" font-size="12" fill="#374151">No</text>
<rect x="40" y="225" width="100" height="50" rx="4" fill="#ef4444" stroke="#dc2626" stroke-width="2"/>
<text x="90" y="255" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#ffffff">Error</text>
<!-- End -->
<line x1="300" y1="300" x2="300" y2="340" stroke="#374151" stroke-width="2" marker-end="url(#arrowhead)"/>
<ellipse cx="300" cy="365" rx="60" ry="25" fill="#6b7280" stroke="#4b5563" stroke-width="2"/>
<text x="300" y="371" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#ffffff">End</text>
</svg>'''
},
'System Architecture': {
'description': 'Simple system architecture diagram',
'code': '''<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 500" width="800" height="500">
<defs>
<marker id="arrow" markerWidth="10" markerHeight="7" refX="9" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#6b7280"/>
</marker>
</defs>
<rect width="100%" height="100%" fill="#f9fafb"/>
<!-- Title -->
<text x="400" y="30" text-anchor="middle" font-family="sans-serif" font-size="18" font-weight="bold" fill="#111827">System Architecture</text>
<!-- Client layer -->
<rect x="50" y="60" width="700" height="80" rx="8" fill="none" stroke="#d1d5db" stroke-dasharray="5,5"/>
<text x="70" y="85" font-family="sans-serif" font-size="12" fill="#6b7280">Client Layer</text>
<rect x="100" y="90" width="120" height="40" rx="4" fill="#dbeafe" stroke="#3b82f6"/>
<text x="160" y="115" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#1e40af">Web App</text>
<rect x="250" y="90" width="120" height="40" rx="4" fill="#dbeafe" stroke="#3b82f6"/>
<text x="310" y="115" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#1e40af">Mobile App</text>
<rect x="400" y="90" width="120" height="40" rx="4" fill="#dbeafe" stroke="#3b82f6"/>
<text x="460" y="115" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#1e40af">Desktop App</text>
<!-- Arrows to API Gateway -->
<line x1="160" y1="130" x2="400" y2="190" stroke="#6b7280" stroke-width="1.5" marker-end="url(#arrow)"/>
<line x1="310" y1="130" x2="400" y2="190" stroke="#6b7280" stroke-width="1.5" marker-end="url(#arrow)"/>
<line x1="460" y1="130" x2="400" y2="190" stroke="#6b7280" stroke-width="1.5" marker-end="url(#arrow)"/>
<!-- API Gateway -->
<rect x="300" y="190" width="200" height="50" rx="4" fill="#fef3c7" stroke="#f59e0b"/>
<text x="400" y="220" text-anchor="middle" font-family="sans-serif" font-size="14" fill="#92400e">API Gateway</text>
<!-- Arrow to services -->
<line x1="400" y1="240" x2="400" y2="280" stroke="#6b7280" stroke-width="1.5" marker-end="url(#arrow)"/>
<!-- Services layer -->
<rect x="50" y="280" width="700" height="100" rx="8" fill="none" stroke="#d1d5db" stroke-dasharray="5,5"/>
<text x="70" y="305" font-family="sans-serif" font-size="12" fill="#6b7280">Microservices</text>
<rect x="80" y="320" width="130" height="45" rx="4" fill="#d1fae5" stroke="#10b981"/>
<text x="145" y="348" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#065f46">Auth Service</text>
<rect x="235" y="320" width="130" height="45" rx="4" fill="#d1fae5" stroke="#10b981"/>
<text x="300" y="348" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#065f46">User Service</text>
<rect x="390" y="320" width="130" height="45" rx="4" fill="#d1fae5" stroke="#10b981"/>
<text x="455" y="348" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#065f46">Order Service</text>
<rect x="545" y="320" width="130" height="45" rx="4" fill="#d1fae5" stroke="#10b981"/>
<text x="610" y="348" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#065f46">Payment Service</text>
<!-- Data layer -->
<rect x="50" y="410" width="700" height="70" rx="8" fill="none" stroke="#d1d5db" stroke-dasharray="5,5"/>
<text x="70" y="435" font-family="sans-serif" font-size="12" fill="#6b7280">Data Layer</text>
<!-- Databases -->
<ellipse cx="200" cy="455" rx="60" ry="20" fill="#fce7f3" stroke="#ec4899"/>
<text x="200" y="460" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#9d174d">PostgreSQL</text>
<ellipse cx="400" cy="455" rx="60" ry="20" fill="#fce7f3" stroke="#ec4899"/>
<text x="400" y="460" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#9d174d">Redis Cache</text>
<ellipse cx="600" cy="455" rx="60" ry="20" fill="#fce7f3" stroke="#ec4899"/>
<text x="600" y="460" text-anchor="middle" font-family="sans-serif" font-size="11" fill="#9d174d">MongoDB</text>
<!-- Arrows from services to databases -->
<line x1="145" y1="365" x2="190" y2="435" stroke="#6b7280" stroke-width="1" marker-end="url(#arrow)"/>
<line x1="300" y1="365" x2="395" y2="435" stroke="#6b7280" stroke-width="1" marker-end="url(#arrow)"/>
<line x1="610" y1="365" x2="600" y2="435" stroke="#6b7280" stroke-width="1" marker-end="url(#arrow)"/>
</svg>'''
},
},
'basic': {
'Shapes Gallery': {
'description': 'Common SVG shapes reference',
'code': '''<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 400" width="600" height="400">
<rect width="100%" height="100%" fill="#f9fafb"/>
<text x="300" y="30" text-anchor="middle" font-family="sans-serif" font-size="18" font-weight="bold" fill="#111827">SVG Shapes Reference</text>
<!-- Rectangle -->
<rect x="50" y="60" width="120" height="80" rx="8" fill="#3b82f6" stroke="#1d4ed8" stroke-width="2"/>
<text x="110" y="170" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#374151">Rectangle</text>
<!-- Circle -->
<circle cx="280" cy="100" r="45" fill="#10b981" stroke="#059669" stroke-width="2"/>
<text x="280" y="170" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#374151">Circle</text>
<!-- Ellipse -->
<ellipse cx="450" cy="100" rx="70" ry="40" fill="#f59e0b" stroke="#d97706" stroke-width="2"/>
<text x="450" y="170" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#374151">Ellipse</text>
<!-- Line -->
<line x1="50" y1="220" x2="170" y2="280" stroke="#6366f1" stroke-width="3"/>
<text x="110" y="310" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#374151">Line</text>
<!-- Polygon (triangle) -->
<polygon points="280,200 330,280 230,280" fill="#ec4899" stroke="#be185d" stroke-width="2"/>
<text x="280" y="310" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#374151">Polygon</text>
<!-- Path (curve) -->
<path d="M 380 280 Q 450 180 520 280" fill="none" stroke="#8b5cf6" stroke-width="3"/>
<text x="450" y="310" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#374151">Path (Curve)</text>
<!-- Text -->
<text x="110" y="370" text-anchor="middle" font-family="sans-serif" font-size="24" font-weight="bold" fill="#111827">Text</text>
<text x="110" y="390" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#374151">Text Element</text>
<!-- Polyline -->
<polyline points="230,330 260,380 290,340 320,370" fill="none" stroke="#14b8a6" stroke-width="3"/>
<text x="280" y="390" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#374151">Polyline</text>
<!-- Group with transform -->
<g transform="translate(450, 350)">
<rect x="-30" y="-20" width="60" height="40" fill="#f43f5e"/>
<circle cx="0" cy="0" r="15" fill="#fef2f2"/>
</g>
<text x="450" y="390" text-anchor="middle" font-family="sans-serif" font-size="12" fill="#374151">Group</text>
</svg>'''
},
},
}
# Excalidraw Templates (JSON format)
EXCALIDRAW_TEMPLATES = {
'diagrams': {
'Simple Flowchart': {
'description': 'Hand-drawn flowchart with shapes and arrows',
'code': '''{
"type": "excalidraw",
"version": 2,
"elements": [
{"type": "rectangle", "id": "start", "x": 200, "y": 20, "width": 120, "height": 50, "strokeColor": "#087f5b", "backgroundColor": "#c3fae8", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "start-txt", "x": 230, "y": 35, "width": 60, "height": 25, "text": "Start", "fontSize": 20, "strokeColor": "#087f5b"},
{"type": "arrow", "id": "a1", "x": 260, "y": 70, "width": 0, "height": 40, "points": [[0, 0], [0, 40]], "strokeColor": "#495057"},
{"type": "rectangle", "id": "proc1", "x": 180, "y": 120, "width": 160, "height": 60, "strokeColor": "#1864ab", "backgroundColor": "#d0ebff", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "proc1-txt", "x": 200, "y": 140, "width": 120, "height": 25, "text": "Process", "fontSize": 20, "strokeColor": "#1864ab"},
{"type": "arrow", "id": "a2", "x": 260, "y": 180, "width": 0, "height": 40, "points": [[0, 0], [0, 40]], "strokeColor": "#495057"},
{"type": "diamond", "id": "decision", "x": 185, "y": 230, "width": 150, "height": 100, "strokeColor": "#e67700", "backgroundColor": "#fff3bf", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "dec-txt", "x": 225, "y": 270, "width": 70, "height": 25, "text": "Valid?", "fontSize": 18, "strokeColor": "#e67700"},
{"type": "arrow", "id": "a3-yes", "x": 335, "y": 280, "width": 80, "height": 0, "points": [[0, 0], [80, 0]], "strokeColor": "#2b8a3e"},
{"type": "text", "id": "yes-lbl", "x": 355, "y": 260, "width": 40, "height": 20, "text": "Yes", "fontSize": 14, "strokeColor": "#2b8a3e"},
{"type": "rectangle", "id": "success", "x": 420, "y": 255, "width": 100, "height": 50, "strokeColor": "#2b8a3e", "backgroundColor": "#d3f9d8", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "succ-txt", "x": 445, "y": 270, "width": 50, "height": 25, "text": "Done", "fontSize": 18, "strokeColor": "#2b8a3e"},
{"type": "arrow", "id": "a3-no", "x": 185, "y": 280, "width": -80, "height": 0, "points": [[0, 0], [-80, 0]], "strokeColor": "#c92a2a"},
{"type": "text", "id": "no-lbl", "x": 130, "y": 260, "width": 40, "height": 20, "text": "No", "fontSize": 14, "strokeColor": "#c92a2a"},
{"type": "rectangle", "id": "error", "x": 0, "y": 255, "width": 100, "height": 50, "strokeColor": "#c92a2a", "backgroundColor": "#ffe3e3", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "err-txt", "x": 25, "y": 270, "width": 50, "height": 25, "text": "Error", "fontSize": 18, "strokeColor": "#c92a2a"}
],
"appState": {"viewBackgroundColor": "#ffffff"}
}'''
},
'Mind Map': {
'description': 'Simple mind map with central topic',
'code': '''{
"type": "excalidraw",
"version": 2,
"elements": [
{"type": "ellipse", "id": "center", "x": 300, "y": 200, "width": 160, "height": 80, "strokeColor": "#1864ab", "backgroundColor": "#d0ebff", "fillStyle": "solid", "roughness": 1, "strokeWidth": 2},
{"type": "text", "id": "center-txt", "x": 335, "y": 230, "width": 90, "height": 30, "text": "Main Topic", "fontSize": 20, "strokeColor": "#1864ab"},
{"type": "line", "id": "l1", "x": 380, "y": 200, "width": 100, "height": -80, "points": [[0, 0], [100, -80]], "strokeColor": "#495057"},
{"type": "rectangle", "id": "t1", "x": 480, "y": 80, "width": 120, "height": 50, "strokeColor": "#087f5b", "backgroundColor": "#c3fae8", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "t1-txt", "x": 505, "y": 95, "width": 70, "height": 25, "text": "Topic 1", "fontSize": 16, "strokeColor": "#087f5b"},
{"type": "line", "id": "l2", "x": 460, "y": 240, "width": 80, "height": 0, "points": [[0, 0], [80, 0]], "strokeColor": "#495057"},
{"type": "rectangle", "id": "t2", "x": 540, "y": 215, "width": 120, "height": 50, "strokeColor": "#e67700", "backgroundColor": "#fff3bf", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "t2-txt", "x": 565, "y": 230, "width": 70, "height": 25, "text": "Topic 2", "fontSize": 16, "strokeColor": "#e67700"},
{"type": "line", "id": "l3", "x": 380, "y": 280, "width": 100, "height": 80, "points": [[0, 0], [100, 80]], "strokeColor": "#495057"},
{"type": "rectangle", "id": "t3", "x": 480, "y": 350, "width": 120, "height": 50, "strokeColor": "#862e9c", "backgroundColor": "#f3d9fa", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "t3-txt", "x": 505, "y": 365, "width": 70, "height": 25, "text": "Topic 3", "fontSize": 16, "strokeColor": "#862e9c"},
{"type": "line", "id": "l4", "x": 300, "y": 240, "width": -80, "height": 60, "points": [[0, 0], [-80, 60]], "strokeColor": "#495057"},
{"type": "rectangle", "id": "t4", "x": 100, "y": 290, "width": 120, "height": 50, "strokeColor": "#c92a2a", "backgroundColor": "#ffe3e3", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "t4-txt", "x": 125, "y": 305, "width": 70, "height": 25, "text": "Topic 4", "fontSize": 16, "strokeColor": "#c92a2a"}
],
"appState": {"viewBackgroundColor": "#ffffff"}
}'''
},
},
'wireframes': {
'Login Sketch': {
'description': 'Hand-drawn login form sketch',
'code': '''{
"type": "excalidraw",
"version": 2,
"elements": [
{"type": "rectangle", "id": "card", "x": 100, "y": 50, "width": 280, "height": 350, "strokeColor": "#495057", "backgroundColor": "#f8f9fa", "fillStyle": "solid", "roughness": 1, "strokeWidth": 2},
{"type": "ellipse", "id": "logo", "x": 200, "y": 80, "width": 80, "height": 80, "strokeColor": "#1864ab", "backgroundColor": "#d0ebff", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "logo-txt", "x": 220, "y": 110, "width": 40, "height": 25, "text": "Logo", "fontSize": 14, "strokeColor": "#1864ab"},
{"type": "text", "id": "title", "x": 175, "y": 180, "width": 130, "height": 30, "text": "Welcome Back", "fontSize": 20, "strokeColor": "#212529"},
{"type": "rectangle", "id": "email", "x": 130, "y": 220, "width": 220, "height": 40, "strokeColor": "#adb5bd", "backgroundColor": "#ffffff", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "email-txt", "x": 145, "y": 233, "width": 50, "height": 20, "text": "Email...", "fontSize": 14, "strokeColor": "#adb5bd"},
{"type": "rectangle", "id": "pass", "x": 130, "y": 275, "width": 220, "height": 40, "strokeColor": "#adb5bd", "backgroundColor": "#ffffff", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "pass-txt", "x": 145, "y": 288, "width": 70, "height": 20, "text": "Password...", "fontSize": 14, "strokeColor": "#adb5bd"},
{"type": "rectangle", "id": "btn", "x": 130, "y": 335, "width": 220, "height": 45, "strokeColor": "#1864ab", "backgroundColor": "#339af0", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "btn-txt", "x": 200, "y": 350, "width": 80, "height": 20, "text": "Sign In", "fontSize": 16, "strokeColor": "#ffffff"}
],
"appState": {"viewBackgroundColor": "#ffffff"}
}'''
},
'Mobile Screen': {
'description': 'Hand-drawn mobile app screen',
'code': '''{
"type": "excalidraw",
"version": 2,
"elements": [
{"type": "rectangle", "id": "phone", "x": 100, "y": 20, "width": 240, "height": 480, "strokeColor": "#212529", "backgroundColor": "#f8f9fa", "fillStyle": "solid", "roughness": 1, "strokeWidth": 3},
{"type": "rectangle", "id": "statusbar", "x": 100, "y": 20, "width": 240, "height": 30, "strokeColor": "#212529", "backgroundColor": "#e9ecef", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "time", "x": 195, "y": 30, "width": 50, "height": 20, "text": "9:41", "fontSize": 14, "strokeColor": "#212529"},
{"type": "rectangle", "id": "header", "x": 100, "y": 50, "width": 240, "height": 50, "strokeColor": "#1864ab", "backgroundColor": "#339af0", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "header-txt", "x": 180, "y": 68, "width": 80, "height": 20, "text": "My App", "fontSize": 18, "strokeColor": "#ffffff"},
{"type": "rectangle", "id": "card1", "x": 115, "y": 115, "width": 210, "height": 80, "strokeColor": "#adb5bd", "backgroundColor": "#ffffff", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "card1-txt", "x": 130, "y": 140, "width": 100, "height": 20, "text": "Item 1", "fontSize": 16, "strokeColor": "#212529"},
{"type": "rectangle", "id": "card2", "x": 115, "y": 210, "width": 210, "height": 80, "strokeColor": "#adb5bd", "backgroundColor": "#ffffff", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "card2-txt", "x": 130, "y": 235, "width": 100, "height": 20, "text": "Item 2", "fontSize": 16, "strokeColor": "#212529"},
{"type": "rectangle", "id": "card3", "x": 115, "y": 305, "width": 210, "height": 80, "strokeColor": "#adb5bd", "backgroundColor": "#ffffff", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "card3-txt", "x": 130, "y": 330, "width": 100, "height": 20, "text": "Item 3", "fontSize": 16, "strokeColor": "#212529"},
{"type": "rectangle", "id": "tabbar", "x": 100, "y": 450, "width": 240, "height": 50, "strokeColor": "#212529", "backgroundColor": "#ffffff", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "tab1", "x": 130, "y": 468, "width": 40, "height": 15, "text": "Home", "fontSize": 12, "strokeColor": "#1864ab"},
{"type": "text", "id": "tab2", "x": 200, "y": 468, "width": 40, "height": 15, "text": "Search", "fontSize": 12, "strokeColor": "#868e96"},
{"type": "text", "id": "tab3", "x": 275, "y": 468, "width": 40, "height": 15, "text": "Profile", "fontSize": 12, "strokeColor": "#868e96"}
],
"appState": {"viewBackgroundColor": "#ffffff"}
}'''
},
},
'basic': {
'Shapes Demo': {
'description': 'Basic shapes in Excalidraw style',
'code': '''{
"type": "excalidraw",
"version": 2,
"elements": [
{"type": "rectangle", "id": "rect", "x": 50, "y": 50, "width": 120, "height": 80, "strokeColor": "#1864ab", "backgroundColor": "#d0ebff", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "rect-lbl", "x": 75, "y": 150, "width": 70, "height": 20, "text": "Rectangle", "fontSize": 12, "strokeColor": "#495057"},
{"type": "ellipse", "id": "ellipse", "x": 220, "y": 50, "width": 100, "height": 80, "strokeColor": "#087f5b", "backgroundColor": "#c3fae8", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "ell-lbl", "x": 245, "y": 150, "width": 50, "height": 20, "text": "Ellipse", "fontSize": 12, "strokeColor": "#495057"},
{"type": "diamond", "id": "diamond", "x": 370, "y": 40, "width": 100, "height": 100, "strokeColor": "#e67700", "backgroundColor": "#fff3bf", "fillStyle": "solid", "roughness": 1},
{"type": "text", "id": "dia-lbl", "x": 390, "y": 150, "width": 60, "height": 20, "text": "Diamond", "fontSize": 12, "strokeColor": "#495057"},
{"type": "line", "id": "line", "x": 50, "y": 200, "width": 100, "height": 60, "points": [[0, 0], [100, 60]], "strokeColor": "#862e9c", "strokeWidth": 2, "roughness": 1},
{"type": "text", "id": "line-lbl", "x": 75, "y": 280, "width": 50, "height": 20, "text": "Line", "fontSize": 12, "strokeColor": "#495057"},
{"type": "arrow", "id": "arrow", "x": 220, "y": 200, "width": 100, "height": 60, "points": [[0, 0], [100, 60]], "strokeColor": "#c92a2a", "strokeWidth": 2, "roughness": 1},
{"type": "text", "id": "arr-lbl", "x": 250, "y": 280, "width": 50, "height": 20, "text": "Arrow", "fontSize": 12, "strokeColor": "#495057"},
{"type": "text", "id": "text-demo", "x": 370, "y": 220, "width": 100, "height": 40, "text": "Text\\nElement", "fontSize": 20, "strokeColor": "#212529"},
{"type": "text", "id": "txt-lbl", "x": 395, "y": 280, "width": 50, "height": 20, "text": "Text", "fontSize": 12, "strokeColor": "#495057"}
],
"appState": {"viewBackgroundColor": "#ffffff"}
}'''
},
},
}
# Combined templates dict for backwards compatibility
TEMPLATES = PLANTUML_TEMPLATES
def get_template_categories(format_type: str = 'plantuml') -> list:
"""Get list of template categories for a format."""
templates = get_templates_for_format(format_type)
return list(templates.keys())
def get_templates_for_format(format_type: str) -> dict:
"""Get all templates for a format type."""
format_map = {
'plantuml': PLANTUML_TEMPLATES,
'mermaid': MERMAID_TEMPLATES,
'openscad': OPENSCAD_TEMPLATES,
'code': CODE_TEMPLATES,
'svg': SVG_TEMPLATES,
'excalidraw': EXCALIDRAW_TEMPLATES,
}
return format_map.get(format_type, PLANTUML_TEMPLATES)
def get_templates_for_category(category: str, format_type: str = 'plantuml') -> dict:
"""Get all templates for a diagram type category."""
templates = get_templates_for_format(format_type)
return templates.get(category, {})
def get_template(category: str, name: str, format_type: str = 'plantuml') -> dict:
"""Get a specific template by category and name."""
templates = get_templates_for_format(format_type)
return templates.get(category, {}).get(name, {})
def get_all_templates(format_type: str = 'plantuml') -> list:
"""Get all templates as a flat list with category info."""
result = []
templates = get_templates_for_format(format_type)
for category, category_templates in templates.items():
for name, template in category_templates.items():
result.append({
'category': category,
'name': name,
'description': template.get('description', ''),
'code': template.get('code', ''),
})
return result