# Deep Technical Integration Notes — Book Print Obsidian Plugin

This document serves as the authoritative technical reference for Electron PDF rendering, Lulu Print API v2 integration, cover geometry calculations, and Stripe checkout workflows.

---

# 1. Local Electron PDF Rendering (`webContents.printToPDF`)

## Core Challenge
Obsidian desktop plugins execute inside Electron. Standard browser print dialogs enforce system default paper sizes (Letter/A4). To produce an exact **6 × 9 inches** (152.4 × 228.6 mm) trade book interior locally:

## Print Options Specification
```typescript
interface PrintToPDFOptions {
  pageSize: {
    width: number;  // Microns: 6 inches * 25,400 = 152,400
    height: number; // Microns: 9 inches * 25,400 = 228,600
  };
  marginsType: 0; // 0 = None (forces CSS @page margins to take precedence)
  printBackground: true;
  preferCSSPageSize: true;
}
```

## CSS Paged Media `@page` Rules
```css
@media print {
  @page {
    size: 6in 9in;
    margin-top: 0.75in;
    margin-bottom: 0.75in;
    margin-inside: 0.85in;  /* Gutter margin */
    margin-outside: 0.65in;
  }

  /* Support for left/right mirrored pages in print engines */
  @page :left {
    margin-left: 0.65in;
    margin-right: 0.85in;
  }
  @page :right {
    margin-left: 0.85in;
    margin-right: 0.65in;
  }

  body {
    font-family: "Libre Caslon Text", serif;
    font-size: 12pt;
    line-height: 1.35;
    color: #000;
    background: transparent;
  }

  /* Forced Page Break marker /// */
  .book-page-break {
    break-before: page;
    page-break-before: always;
  }

  /* Heading 1 starts on a new page by default */
  h1 {
    break-before: page;
    page-break-before: always;
    font-size: 24pt;
    font-weight: bold;
    margin-top: 2in;
  }
}
```

---

# 2. Lulu Print API v2 Integration

## Auth & Sandbox Base URLs
- **Sandbox Base URL**: `https://api.sandbox.lulu.com`
- **Production Base URL**: `https://api.lulu.com`
- **Token Request**: `POST /oauth/token` (`grant_type=client_credentials`)

## Key API Endpoints
1. **Shipping & Manufacturing Quote**: `POST /print-job-cost-calculations/`
   ```json
   {
     "line_items": [
       {
         "page_count": 120,
         "pod_package_id": "0600X0900BWSTDPB060UW444MXX",
         "quantity": 1
       }
     ],
     "shipping_address": {
       "city": "White Salmon",
       "country": "US",
       "postcode": "98672",
       "state": "WA",
       "street1": "123 Example Road"
     }
   }
   ```
2. **File Validation**: `POST /print-jobs/validate/`
   - Validates interior PDF and full-wrap cover PDF accessibility, page count, and dimensions.
3. **Submit Order**: `POST /print-jobs/`
   - Accepts external signed S3/R2 URLs for interior and cover PDFs.

## Common `pod_package_id` Specifications (6 × 9 Trade Book)
- **Paperback**: 6 × 9 in, Black & White interior, 60# White paper, Perfect Bound, Gloss Cover.
- **Hardcover**: 6 × 9 in, Black & White interior, 60# White paper, Hardcover Casewrap, Matte Cover.

---

# 3. Dynamic Cover Geometry & Spine Calculation

## Cover Layout Diagram
```text
┌──────────────┬──────────────┬──────────────┬──────────────┬──────────────┐
│ Bleed        │ Back Cover   │    Spine     │ Front Cover  │ Bleed        │
│ (0.125")     │ (6.0")       │  (Calculated)│ (6.0")       │ (0.125")     │
└──────────────┴──────────────┴──────────────┴──────────────┴──────────────┘
```

## Formulas
1. **Spine Width Calculation**:
   - `Spine Width (in) = Page Count * Page Thickness`
   - Example (Standard 60# White Paper ~ 0.00225 in/page):
     For 200 pages: `200 * 0.00225 = 0.45 inches`.
2. **Paperback Full-Wrap Dimensions**:
   - `Total Width = 0.125" (bleed) + 6.0" (back) + Spine Width + 6.0" (front) + 0.125" (bleed)`
   - `Total Height = 0.125" (bleed) + 9.0" (height) + 0.125" (bleed) = 9.25 inches`
3. **Hardcover Casewrap Dimensions**:
   - Hardcover requires extra wrap margins (~0.625" wrap around board edges on all 4 sides) plus hinge fold allowances (~0.3125").
   - Always verify against Lulu API Cover Dimension Endpoint: `GET /cover-dimensions/`.

---

# 4. Stripe Payment & Webhook Architecture

```text
OBSIDIAN PLUGIN                  BACKEND API                   STRIPE / LULUS
      │                               │                             │
      │ ─── 1. Request Checkout ────> │                             │
      │                               │ ─── 2. Create Session ────> │
      │ <── 3. Return Checkout URL ── │                             │
      │                               │                             │
      │ [User Completes Payment]      │                             │
      │                               │ <── 4. Webhook (checkout.session.completed)
      │                               │                             │
      │                               │ ─── 5. Submit Order ──────> │ (Lulu API)
```

## Security & Idempotency Rules
1. Never process Lulu orders based on client-side status signals.
2. Webhooks MUST verify the `Stripe-Signature` header using the webhook secret.
3. Every order submission is tagged with an `idempotencyKey` matching the `checkoutSessionId` to guarantee that Lulu never receives duplicate orders.
