Sone

Examples & Use Cases

Real-world examples and common use cases for Sone

Examples & Use Cases

This page provides comprehensive examples of common use cases for Sone, from simple documents to complex layouts.

Business Documents

Invoice Template

import { Column, Row, Text, Span, Table, TableRow, TableCell, sone } from "sone";

function InvoiceTemplate(invoiceData) {
  const { company, client, items, invoiceNumber, date } = invoiceData;
  
  return Column(
    // Header
    Row(
      Column(
        Text(company.name).size(24).weight("bold"),
        Text(company.address).size(12).color("gray"),
        Text(`${company.city}, ${company.state} ${company.zip}`).size(12).color("gray"),
        Text(company.phone).size(12).color("gray")
      ).flex(1),
      
      Column(
        Text("INVOICE").size(32).weight("bold").color("#2563eb"),
        Text(`#${invoiceNumber}`).size(16).weight("500"),
        Text(date).size(14).color("gray")
      ).alignItems("flex-end")
    ).marginBottom(40),
    
    // Bill To
    Column(
      Text("Bill To:").size(14).weight("bold").marginBottom(10),
      Text(client.name).size(16).weight("500"),
      Text(client.address).size(14).color("gray"),
      Text(`${client.city}, ${client.state} ${client.zip}`).size(14).color("gray")
    ).marginBottom(30),
    
    // Items Table
    Table(
      // Header
      TableRow(
        TableCell(Text("Description").weight("bold").size(14)),
        TableCell(Text("Qty").weight("bold").size(14).align("center")),
        TableCell(Text("Rate").weight("bold").size(14).align("right")),
        TableCell(Text("Amount").weight("bold").size(14).align("right"))
      )
      .bg("#f8fafc")
      .borderBottomWidth(2)
      .borderColor("#e2e8f0"),
      
      // Items
      ...items.map(item =>
        TableRow(
          TableCell(Text(item.description).size(13)),
          TableCell(Text(item.quantity.toString()).size(13).align("center")),
          TableCell(Text(`$${item.rate.toFixed(2)}`).size(13).align("right")),
          TableCell(Text(`$${(item.quantity * item.rate).toFixed(2)}`).size(13).align("right"))
        )
        .padding(12, 0)
        .borderBottomWidth(1)
        .borderColor("#e2e8f0")
      )
    ).marginBottom(20),
    
    // Total
    Row(
      Column().flex(1),
      Column(
        Row(
          Text("Subtotal:").size(14).weight("500"),
          Text(`$${items.reduce((sum, item) => sum + (item.quantity * item.rate), 0).toFixed(2)}`)
            .size(14).marginLeft(40)
        ).marginBottom(8),
        
        Row(
          Text("Tax (10%):").size(14).weight("500"),
          Text(`$${(items.reduce((sum, item) => sum + (item.quantity * item.rate), 0) * 0.1).toFixed(2)}`)
            .size(14).marginLeft(40)
        ).marginBottom(8),
        
        Row(
          Text("Total:").size(16).weight("bold").color("#2563eb"),
          Text(`$${(items.reduce((sum, item) => sum + (item.quantity * item.rate), 0) * 1.1).toFixed(2)}`)
            .size(16).weight("bold").color("#2563eb").marginLeft(40)
        )
        .padding(12, 0)
        .borderTopWidth(2)
        .borderColor("#2563eb")
      ).width(200)
    )
  )
  .padding(40)
  .bg("white")
  .maxWidth(800);
}

// Usage
const invoice = await sone(InvoiceTemplate({
  company: {
    name: "Acme Corp",
    address: "123 Business St", 
    city: "Business City",
    state: "BC",
    zip: "12345",
    phone: "(555) 123-4567"
  },
  client: {
    name: "John Smith",
    address: "456 Client Ave",
    city: "Client City", 
    state: "CC",
    zip: "67890"
  },
  invoiceNumber: "INV-2024-001",
  date: "January 15, 2024",
  items: [
    { description: "Web Development", quantity: 40, rate: 100 },
    { description: "Design Services", quantity: 20, rate: 80 }
  ]
})).pdf();

Certificate Template

function CertificateTemplate(recipient, course, date, instructor) {
  return Column(
    // Decorative border
    Column(
      // Header
      Text("CERTIFICATE OF COMPLETION")
        .size(36)
        .weight("bold")
        .color("#1f2937")
        .align("center")
        .letterSpacing(4)
        .marginBottom(40),
      
      // Decorative line
      Row()
        .height(3)
        .width(300)
        .bg("linear-gradient(90deg, #f59e0b, #d97706)")
        .rounded(2)
        .margin("auto")
        .marginBottom(40),
      
      // Content
      Text("This is to certify that")
        .size(18)
        .color("#6b7280")
        .align("center")
        .marginBottom(20),
      
      Text(recipient)
        .size(42)
        .weight("bold")
        .color("#1f2937")
        .align("center")
        .marginBottom(30)
        .borderBottomWidth(2)
        .borderColor("#e5e7eb")
        .paddingBottom(10),
      
      Text("has successfully completed the course")
        .size(18)
        .color("#6b7280")
        .align("center")
        .marginBottom(20),
      
      Text(course)
        .size(28)
        .weight("600")
        .color("#059669")
        .align("center")
        .marginBottom(40),
      
      Text(`on ${date}`)
        .size(16)
        .color("#6b7280")
        .align("center")
        .marginBottom(60),
      
      // Signature section
      Row(
        Column(
          Row()
            .height(2)
            .width(200)
            .bg("#9ca3af")
            .marginBottom(8),
          Text(instructor)
            .size(16)
            .weight("500")
            .align("center"),
          Text("Instructor")
            .size(12)
            .color("#6b7280")
            .align("center")
        )
      ).justifyContent("center")
    )
    .padding(80)
    .bg("white")
  )
  .size(800, 600)
  .bg("linear-gradient(135deg, #fef3c7, #fde68a)")
  .shadow("0 20px 40px rgba(0,0,0,0.1)")
  .rounded(20)
  .borderWidth(8)
  .borderColor("#f59e0b")
  .justifyContent("center")
  .alignItems("center");
}

Marketing Materials

Social Media Post

function SocialMediaPost(content, author, image) {
  return Column(
    // Background image overlay
    Column(
      Column(
        Text(content.title)
          .size(32)
          .weight("bold")
          .color("white")
          .align("center")
          .dropShadow("2px 2px 8px rgba(0,0,0,0.8)")
          .marginBottom(15),
        
        Text(content.subtitle)
          .size(18)
          .color("white")
          .align("center")
          .dropShadow("1px 1px 4px rgba(0,0,0,0.8)")
          .opacity(0.9)
      )
      .padding(40)
      .bg("linear-gradient(135deg, rgba(99, 102, 241, 0.8), rgba(139, 92, 246, 0.8))")
      .rounded(20)
      .shadow("0 10px 20px rgba(0,0,0,0.3)")
    )
    .justifyContent("center")
    .alignItems("center")
    .size(600, 400)
    .bg(Photo(image))
    .rounded(15)
  )
  .shadow("0 20px 40px rgba(0,0,0,0.2)");
}

Business Card

function BusinessCard(person) {
  return Row(
    // Left side - Contact info
    Column(
      Text(person.name)
        .size(24)
        .weight("bold")
        .color("#1f2937")
        .marginBottom(5),
      
      Text(person.title)
        .size(14)
        .color("#6366f1")
        .weight("500")
        .marginBottom(20),
      
      Column(
        Text(person.email).size(12).color("#4b5563"),
        Text(person.phone).size(12).color("#4b5563"),
        Text(person.website).size(12).color("#4b5563")
      ).gap(5)
    )
    .flex(1)
    .padding(25),
    
    // Right side - Logo/Brand
    Column(
      Text(person.company)
        .size(20)
        .weight("bold")
        .color("#6366f1")
        .align("right")
    )
    .flex(1)
    .padding(25)
    .bg("linear-gradient(135deg, #f8fafc, #e2e8f0)")
    .justifyContent("center")
  )
  .size(350, 200)
  .bg("white")
  .rounded(12)
  .shadow("0 4px 12px rgba(0,0,0,0.15)")
  .borderWidth(1)
  .borderColor("#e5e7eb");
}

Data Visualization

Report Dashboard

function ReportDashboard(data) {
  return Column(
    // Header
    Row(
      Text("Monthly Report")
        .size(28)
        .weight("bold")
        .color("#1f2937"),
      
      Text(data.period)
        .size(16)
        .color("#6b7280")
    )
    .justifyContent("space-between")
    .alignItems("center")
    .marginBottom(30),
    
    // KPI Cards
    Row(
      ...data.kpis.map(kpi =>
        Column(
          Text(kpi.value)
            .size(32)
            .weight("bold")
            .color(kpi.trend > 0 ? "#059669" : kpi.trend < 0 ? "#dc2626" : "#1f2937")
            .align("center"),
          
          Text(kpi.label)
            .size(14)
            .color("#6b7280")
            .align("center")
            .marginTop(8),
          
          Text(`${kpi.trend > 0 ? '+' : ''}${kpi.trend}%`)
            .size(12)
            .weight("500")
            .color(kpi.trend > 0 ? "#059669" : kpi.trend < 0 ? "#dc2626" : "#6b7280")
            .align("center")
            .marginTop(4)
        )
        .flex(1)
        .padding(20)
        .bg("white")
        .rounded(8)
        .shadow("0 1px 3px rgba(0,0,0,0.1)")
        .margin(0, 10)
      )
    ).marginBottom(30),
    
    // Data Table
    Table(
      // Header
      TableRow(
        ...data.tableHeaders.map(header =>
          TableCell(Text(header).weight("bold").size(14))
            .padding(12)
            .bg("#f9fafb")
        )
      ),
      
      // Rows
      ...data.tableData.map((row, index) =>
        TableRow(
          ...row.map(cell =>
            TableCell(Text(cell.toString()).size(13))
              .padding(12)
          )
        )
        .bg(index % 2 === 0 ? "white" : "#f9fafb")
      )
    )
    .borderWidth(1)
    .borderColor("#d1d5db")
    .rounded(6)
  )
  .padding(40)
  .bg("#f3f4f6")
  .minHeight(800);
}

Performance Chart Placeholder

function ChartPlaceholder(title, data) {
  return Column(
    Text(title)
      .size(16)
      .weight("600")
      .color("#374151")
      .marginBottom(15),
    
    // Simulated bar chart
    Row(
      ...data.map((value, index) =>
        Column(
          Column()
            .width(30)
            .height(value * 2)  // Scale height
            .bg(`hsl(${200 + index * 30}, 70%, 50%)`)
            .rounded(4, 4, 0, 0),
          
          Text(value.toString())
            .size(10)
            .align("center")
            .marginTop(5)
        )
        .alignItems("center")
        .margin(0, 2)
      )
    )
    .alignItems("flex-end")
    .justifyContent("center")
    .height(200)
  )
  .padding(20)
  .bg("white")
  .rounded(8)
  .shadow("0 1px 3px rgba(0,0,0,0.1)");
}

Educational Content

Resume Template

function ResumeTemplate(resume) {
  return Column(
    // Header
    Column(
      Text(resume.name)
        .size(32)
        .weight("bold")
        .color("#1f2937")
        .align("center"),
      
      Text(resume.title)
        .size(18)
        .color("#6366f1")
        .align("center")
        .marginTop(8),
      
      Row(
        Text(resume.email).size(12),
        Text(resume.phone).size(12),
        Text(resume.location).size(12)
      )
      .gap(20)
      .justifyContent("center")
      .marginTop(15)
      .color("#6b7280")
    )
    .marginBottom(30)
    .borderBottomWidth(2)
    .borderColor("#e5e7eb")
    .paddingBottom(20),
    
    // Experience Section
    Column(
      Text("Experience")
        .size(20)
        .weight("bold")
        .color("#1f2937")
        .marginBottom(15),
      
      ...resume.experience.map(job =>
        Column(
          Row(
            Text(job.title).size(16).weight("600"),
            Text(job.period).size(14).color("#6b7280")
          )
          .justifyContent("space-between")
          .alignItems("center"),
          
          Text(job.company)
            .size(14)
            .color("#6366f1")
            .marginTop(2),
          
          Text(job.description)
            .size(12)
            .color("#4b5563")
            .lineHeight(1.5)
            .marginTop(8)
        )
        .marginBottom(20)
      )
    )
    .marginBottom(25),
    
    // Skills Section
    Column(
      Text("Skills")
        .size(20)
        .weight("bold")
        .color("#1f2937")
        .marginBottom(15),
      
      Row(
        ...resume.skills.map(skill =>
          Text(skill)
            .size(12)
            .color("#1f2937")
            .bg("#f3f4f6")
            .padding(6, 12)
            .rounded(20)
        )
      )
      .gap(10)
      .wrap("wrap")
    )
  )
  .padding(40)
  .bg("white")
  .maxWidth(600);
}

Course Materials

function CoursePage(lesson) {
  return Column(
    // Header
    Column(
      Text(lesson.title)
        .size(28)
        .weight("bold")
        .color("#1f2937")
        .marginBottom(10),
      
      Row(
        Text(`Lesson ${lesson.number}`).size(14).color("#6366f1"),
        Text(`Duration: ${lesson.duration}`).size(14).color("#6b7280")
      )
      .gap(20)
    )
    .marginBottom(30),
    
    // Objectives
    Column(
      Text("Learning Objectives")
        .size(18)
        .weight("600")
        .color("#1f2937")
        .marginBottom(15),
      
      ...lesson.objectives.map((objective, index) =>
        Row(
          Text(`${index + 1}.`).size(14).weight("500").width(30),
          Text(objective).size(14).flex(1)
        )
        .marginBottom(8)
        .color("#374151")
      )
    )
    .marginBottom(30),
    
    // Content
    Column(
      ...lesson.content.map(section =>
        Column(
          Text(section.heading)
            .size(16)
            .weight("600")
            .color("#1f2937")
            .marginBottom(10),
          
          Text(section.text)
            .size(14)
            .lineHeight(1.6)
            .color("#374151")
            .marginBottom(20)
        )
      )
    )
  )
  .padding(40)
  .bg("white")
  .maxWidth(700);
}

Creative Layouts

Magazine Layout

function MagazineArticle(article) {
  return Column(
    // Hero section
    Column(
      Text(article.title)
        .size(36)
        .weight("bold")
        .color("white")
        .align("center")
        .dropShadow("2px 2px 8px rgba(0,0,0,0.8)"),
      
      Text(article.subtitle)
        .size(18)
        .color("white")
        .align("center")
        .opacity(0.9)
        .marginTop(15)
    )
    .justifyContent("center")
    .alignItems("center")
    .size(800, 400)
    .bg(Photo(article.heroImage))
    .marginBottom(40),
    
    // Article content
    Column(
      Row(
        // Main content
        Column(
          Text(article.content)
            .size(16)
            .lineHeight(1.7)
            .color("#374151")
            .align("justify")
        )
        .flex(2)
        .marginRight(40),
        
        // Sidebar
        Column(
          Text("Related Articles")
            .size(18)
            .weight("bold")
            .marginBottom(20),
          
          ...article.related.map(related =>
            Column(
              Text(related.title)
                .size(14)
                .weight("600")
                .color("#1f2937")
                .marginBottom(5),
              
              Text(related.excerpt)
                .size(12)
                .color("#6b7280")
                .lineHeight(1.5)
            )
            .padding(15)
            .bg("#f9fafb")
            .rounded(8)
            .marginBottom(15)
          )
        )
        .flex(1)
      )
    )
    .padding(0, 40)
  )
  .bg("white");
}

Event Poster

function EventPoster(event) {
  return Column(
    // Background with gradient overlay
    Column(
      Text(event.name)
        .size(42)
        .weight("bold")
        .color("white")
        .align("center")
        .dropShadow("3px 3px 12px rgba(0,0,0,0.8)")
        .marginBottom(20),
      
      Text(event.tagline)
        .size(20)
        .color("white")
        .align("center")
        .style("italic")
        .opacity(0.9)
        .marginBottom(40),
      
      Column(
        Text(event.date)
          .size(24)
          .weight("600")
          .color("#fbbf24")
          .align("center"),
        
        Text(event.time)
          .size(18)
          .color("white")
          .align("center")
          .marginTop(8),
        
        Text(event.location)
          .size(16)
          .color("white")
          .align("center")
          .marginTop(8)
      )
      .padding(30)
      .bg("rgba(0,0,0,0.6)")
      .rounded(15)
      .marginBottom(30),
      
      Text("REGISTER NOW")
        .size(18)
        .weight("bold")
        .color("black")
        .bg("#fbbf24")
        .padding(15, 40)
        .rounded(25)
        .shadow("0 4px 12px rgba(251, 191, 36, 0.4)")
    )
    .justifyContent("center")
    .alignItems("center")
    .size(600, 800)
    .bg("linear-gradient(135deg, rgba(99, 102, 241, 0.8), rgba(139, 92, 246, 0.8))")
  )
  .shadow("0 20px 40px rgba(0,0,0,0.3)")
  .rounded(20);
}

Export Examples

Multi-page Document

async function generateReport(data) {
  // Page 1: Cover
  const coverPage = Column(
    Text("Annual Report 2024")
      .size(48)
      .weight("bold")
      .color("#1f2937")
      .align("center"),
    
    Text("Company Performance Overview")
      .size(24)
      .color("#6b7280")
      .align("center")
      .marginTop(20)
  )
  .justifyContent("center")
  .alignItems("center")
  .size(800, 600)
  .bg("white");
  
  // Page 2: Summary
  const summaryPage = ReportDashboard(data);
  
  // Export as PDF
  const coverPdf = await sone(coverPage).pdf();
  const summaryPdf = await sone(summaryPage).pdf();
  
  return { coverPdf, summaryPdf };
}

Social Media Variants

async function generateSocialVariants(content) {
  // Instagram Square
  const instagram = SocialMediaPost(content, null, content.image)
    .size(1080, 1080);
  
  // Twitter Card
  const twitter = SocialMediaPost(content, null, content.image)
    .size(1200, 628);
  
  // Facebook Cover
  const facebook = SocialMediaPost(content, null, content.image)
    .size(1200, 630);
  
  return {
    instagram: await sone(instagram).jpg(),
    twitter: await sone(twitter).jpg(),
    facebook: await sone(facebook).jpg()
  };
}

These examples demonstrate the versatility of Sone for creating professional documents, marketing materials, data visualizations, and creative layouts. Each example can be customized and extended based on specific needs.