.do
Develop

Build

Build your Business-as-Code and Services-as-Software using semantic patterns and platform primitives

Build your Business-as-Code and Services-as-Software using the .do platform's semantic patterns, primitives, and development tools.

Overview

The Build phase is where designs become reality. Using Business-as-Code patterns and the .do SDK, you'll implement your business logic as executable, maintainable, and scalable code.

This phase emphasizes:

  • Semantic Implementation: Code that reflects business meaning
  • Type Safety: Catch errors at compile time with TypeScript
  • Event-Driven Architecture: Loosely coupled, reactive systems
  • Services-as-Software: Composable, AI-deliverable services
  • Rapid Development: High-level primitives accelerate implementation

Core Primitives

Entities: Define What Exists

Create and manage business entities:

// Import semantic types from schema.org.ai ontology package
import { Organization, Person, Product } from 'schema.org.ai'

// Create entities
const company = await db.create($.Organization, {
  name: 'Acme Corp',
  legalName: 'Acme Corporation LLC',
  taxID: '12-3456789',
  foundingDate: '2024-01-01',
})

const customer = await db.create($.Person, {
  givenName: 'Alice',
  familyName: 'Smith',
  email: '[email protected]',
  telephone: '+1-555-0100',
})

const product = await db.create($.Product, {
  name: 'Pro Plan',
  description: 'Full-featured professional plan',
  price: { amount: 99, currency: 'USD' },
  category: 'Subscription',
})

// Update entities
await db.update($.Person, customer.id, {
  membershipStatus: 'premium',
  membershipStartDate: new Date(),
})

// Query entities
const premiumCustomers = await db.list($.Person, {
  where: { membershipStatus: 'premium' },
  orderBy: { membershipStartDate: 'desc' },
})

Events: Define What Happens

Respond to business events:

// User lifecycle events
on($.User.signup, async (user, $) => {
  // Create customer record
  const customer = await db.create($.Customer, {
    userId: user.id,
    email: user.email,
    status: 'trial',
  })

  // Send welcome email
  await send($.Email.welcome, {
    to: user.email,
    name: user.givenName,
  })

  // Start onboarding workflow
  await send($.Onboarding.start, { userId: user.id })

  // Track event
  await send($.Analytics.track, {
    event: 'user_signed_up',
    userId: user.id,
  })
})

// Order processing events
on($.Order.created, async (order, $) => {
  // Reserve inventory
  await send($.Inventory.reserve, {
    orderId: order.id,
    items: order.items,
  })

  // Process payment
  const payment = await send($.Payment.process, {
    orderId: order.id,
    amount: order.total,
    customer: order.customerId,
  })

  if (payment.status === 'succeeded') {
    await send($.Order.confirmed, order)
  } else {
    await send($.Order.failed, { order, reason: payment.error })
  }
})

// Multiple event triggers
on([$.User.verified, $.User.completed_onboarding], async (user) => {
  // Both events must have occurred
  await send($.Email.activation_complete, user)
})

Workflows: Define How to Respond

Build complex business processes:

// Subscription workflow
on($.Subscription.created, async (subscription, $) => {
  // Set up billing
  const billing = await $.Billing.setup({
    subscription,
    frequency: 'monthly',
    nextBillDate: addMonths(new Date(), 1),
  })

  // Provision resources
  await send($.Resources.provision, {
    subscriptionId: subscription.id,
    tier: subscription.tier,
  })

  // Schedule first invoice
  await $.Schedule.create({
    trigger: billing.nextBillDate,
    action: $.Invoice.generate,
    data: { subscriptionId: subscription.id },
  })
})

// Automated customer support
on($.Customer.submits.SupportRequest, async (request, $) => {
  // Classify request with AI
  const classification = await $.ai.classify(request.message, {
    categories: ['billing', 'technical', 'feature-request', 'bug'],
  })

  // Route based on classification
  if (classification.category === 'billing') {
    await send($.Team.billing.assign, request)
  } else if (classification.confidence >= 0.7) {
    // AI handles high-confidence requests (>=0.7 confidence threshold)
    const response = await $.ai.respond(request.message, {
      context: await getCustomerContext(request.customerId),
    })

    await send($.SupportRequest.respond, {
      requestId: request.id,
      message: response,
      source: 'ai',
    })
  } else {
    // Route to human support
    await send($.Team.support.assign, request)
  }
})

// Multi-step approval workflow
on($.Expense.submitted, async (expense, $) => {
  // Step 1: Manager approval
  if (expense.amount < 1000) {
    const managerApproval = await $.Approval.request({
      type: 'expense',
      approver: expense.submitter.manager,
      item: expense,
    })

    if (managerApproval.approved) {
      await send($.Expense.approved, expense)
    }
  } else {
    // Step 2: Finance approval for large expenses
    const financeApproval = await $.Approval.request({
      type: 'expense',
      approver: 'finance-team',
      item: expense,
    })

    if (financeApproval.approved) {
      await send($.Expense.approved, expense)
    }
  }
})

Actions: Define Operations

Create reusable business operations:

// Define actions
const actions = {
  // Create customer action
  createCustomer: $.action(async ({ email, name }: { email: string; name: string }, $) => {
    const customer = await db.create($.Customer, {
      email,
      name,
      createdAt: new Date(),
    })

    await send($.Email.welcome, { to: email, name })

    return customer
  }),

  // Process refund action
  processRefund: $.action(async ({ orderId, reason }: { orderId: string; reason: string }, $) => {
    const order = await db.get($.Order, orderId)

    // Refund payment
    const refund = await $.Stripe.refund({
      paymentIntent: order.paymentIntentId,
      amount: order.total,
    })

    // Update order
    await db.update($.Order, orderId, {
      status: 'refunded',
      refundReason: reason,
      refundedAt: new Date(),
    })

    // Notify customer
    await send($.Email.refund_confirmation, {
      to: order.customer.email,
      amount: order.total,
    })

    return refund
  }),

  // Calculate metrics action
  calculateMetrics: $.action(async ({ period }: { period: string }, $) => {
    const [revenue, customers, churn] = await Promise.all([
      calculateRevenue(period),
      countNewCustomers(period),
      calculateChurn(period),
    ])

    return { revenue, customers, churn, period }
  }),
}

// Use actions
const customer = await actions.createCustomer({
  email: '[email protected]',
  name: 'Bob Jones',
})

const refund = await actions.processRefund({
  orderId: 'ord_123',
  reason: 'customer-request',
})

Services: Define Composable Units

Build Services-as-Software:

// Define service
export const AnalyticsService = $.service({
  name: 'Analytics',
  description: 'Business analytics and reporting',

  // Service methods
  methods: {
    // Track event
    track: async ({ event, userId, properties }) => {
      await db.create($.Event, {
        name: event,
        userId,
        properties,
        timestamp: new Date(),
      })
    },

    // Generate report
    report: async ({ metric, period }) => {
      const data = await fetchMetricData(metric, period)
      const analysis = await $.ai.analyze(data, {
        insights: true,
        trends: true,
        recommendations: true,
      })

      return {
        metric,
        period,
        data,
        analysis,
      }
    },

    // Real-time dashboard
    dashboard: async ({ userId }) => {
      const metrics = await calculateRealTimeMetrics(userId)
      return metrics
    },
  },

  // Service events
  events: {
    'metric.threshold_exceeded': {
      emit: async ({ metric, threshold, value }) => {
        await send($.Alert.send, {
          type: 'metric-alert',
          metric,
          message: `${metric} (${value}) exceeded threshold (${threshold})`,
        })
      },
    },
  },
})

// Use service
await AnalyticsService.track({
  event: 'purchase_completed',
  userId: user.id,
  properties: { amount: 99, plan: 'pro' },
})

const report = await AnalyticsService.report({
  metric: 'mrr',
  period: 'last-30-days',
})

Development Patterns

Pattern 1: CRUD Operations

Standard create-read-update-delete:

// Create
const product = await db.create($.Product, {
  name: 'Widget Pro',
  price: 99,
  category: 'Hardware',
})

// Read
const widget = await db.get($.Product, product.id)
const allProducts = await db.list($.Product, {
  where: { category: 'Hardware' },
})

// Update
await db.update($.Product, product.id, {
  price: 89,
  salePrice: 79,
})

// Delete
await db.delete($.Product, product.id)

// Soft delete (preferred)
await db.update($.Product, product.id, {
  status: 'archived',
  archivedAt: new Date(),
})

Pattern 2: Event-Driven State Machines

Model complex state transitions:

// Define state machine
const OrderStateMachine = $.stateMachine({
  initial: 'pending',
  states: {
    pending: {
      on: {
        payment_received: 'processing',
        cancelled: 'cancelled',
      },
    },
    processing: {
      on: {
        shipped: 'shipped',
        failed: 'failed',
      },
    },
    shipped: {
      on: {
        delivered: 'delivered',
        returned: 'returned',
      },
    },
    delivered: { type: 'final' },
    cancelled: { type: 'final' },
    failed: { type: 'final' },
    returned: { type: 'final' },
  },
})

// Use state machine
on($.Order.created, async (order) => {
  await OrderStateMachine.initialize(order)
})

on($.Payment.received, async ({ orderId }) => {
  await OrderStateMachine.transition(orderId, 'payment_received')
})

on($.Shipment.dispatched, async ({ orderId }) => {
  await OrderStateMachine.transition(orderId, 'shipped')
})

Pattern 3: Saga Pattern

Coordinate distributed transactions:

// Define saga
const CheckoutSaga = $.saga({
  name: 'Checkout',
  steps: [
    {
      name: 'validate-cart',
      do: async ({ cart }) => {
        return await $.Cart.validate(cart)
      },
      undo: async () => {
        /* nothing to undo */
      },
    },
    {
      name: 'reserve-inventory',
      do: async ({ cart }) => {
        return await $.Inventory.reserve(cart.items)
      },
      undo: async ({ reservation }) => {
        await $.Inventory.release(reservation.id)
      },
    },
    {
      name: 'process-payment',
      do: async ({ cart, customer }) => {
        return await $.Payment.charge({
          amount: cart.total,
          customer: customer.id,
        })
      },
      undo: async ({ payment }) => {
        await $.Payment.refund(payment.id)
      },
    },
    {
      name: 'create-order',
      do: async ({ cart, payment }) => {
        return await db.create($.Order, {
          items: cart.items,
          total: cart.total,
          paymentId: payment.id,
        })
      },
      undo: async ({ order }) => {
        await db.delete($.Order, order.id)
      },
    },
  ],
})

// Execute saga
on($.Checkout.initiated, async ({ cart, customer }) => {
  const result = await CheckoutSaga.execute({ cart, customer })

  if (result.success) {
    await send($.Order.created, result.data.order)
  } else {
    await send($.Checkout.failed, { error: result.error })
  }
})

Pattern 4: Repository Pattern

Encapsulate data access:

// Define repository
const CustomerRepository = {
  // Create customer
  create: async (data) => {
    return await db.create($.Customer, {
      ...data,
      createdAt: new Date(),
      status: 'active',
    })
  },

  // Find by email
  findByEmail: async (email) => {
    return await db.findOne($.Customer, {
      where: { email },
    })
  },

  // Get active customers
  getActive: async () => {
    return await db.list($.Customer, {
      where: { status: 'active' },
    })
  },

  // Update subscription
  updateSubscription: async (customerId, tier) => {
    return await db.update($.Customer, customerId, {
      subscriptionTier: tier,
      subscriptionUpdatedAt: new Date(),
    })
  },

  // Calculate lifetime value
  calculateLTV: async (customerId) => {
    const orders = await db.list($.Order, {
      where: { customerId },
    })

    return orders.reduce((sum, order) => sum + order.total, 0)
  },
}

// Use repository
const customer = await CustomerRepository.create({
  email: '[email protected]',
  name: 'Charlie Brown',
})

const ltv = await CustomerRepository.calculateLTV(customer.id)

AI Integration

AI-Powered Features

Build intelligent features:

// Content generation
on($.User.requests.Content, async ({ prompt, userId }) => {
  const content = await $.ai.generate({
    prompt,
    model: 'gpt-5',
    context: await getUserContext(userId),
  })

  await db.create($.Content, {
    userId,
    prompt,
    generated: content,
    createdAt: new Date(),
  })

  await send($.Content.generated, { userId, content })
})

// Semantic search
on($.User.searches, async ({ query, userId }) => {
  // Generate embedding
  const embedding = await $.ai.embed(query)

  // Vector search
  const results = await db.vectorSearch($.Product, {
    embedding,
    limit: 10,
    threshold: 0.7,
  })

  // Rerank with AI
  const reranked = await $.ai.rerank(query, results)

  await send($.Search.results, { userId, results: reranked })
})

// Classification
on($.Customer.submits.Feedback, async (feedback) => {
  const classification = await $.ai.classify(feedback.message, {
    categories: ['positive', 'negative', 'neutral'],
    tags: ['feature-request', 'bug', 'praise', 'complaint'],
  })

  await db.update($.Feedback, feedback.id, {
    sentiment: classification.category,
    tags: classification.tags,
  })

  if (classification.category === 'negative') {
    await send($.Team.support.urgent, feedback)
  }
})

Testing

Unit Tests

Test individual components:

import { describe, it, expect } from 'vitest'

describe('CustomerRepository', () => {
  it('creates customer with defaults', async () => {
    const customer = await CustomerRepository.create({
      email: '[email protected]',
      name: 'Test User',
    })

    expect(customer.status).toBe('active')
    expect(customer.createdAt).toBeDefined()
  })

  it('calculates lifetime value', async () => {
    const customer = await CustomerRepository.create({
      email: '[email protected]',
      name: 'Test User',
    })

    await db.create($.Order, {
      customerId: customer.id,
      total: 100,
    })

    const ltv = await CustomerRepository.calculateLTV(customer.id)
    expect(ltv).toBe(100)
  })
})

Integration Tests

Test workflows end-to-end:

describe('Checkout Saga', () => {
  it('completes successful checkout', async () => {
    const cart = await createTestCart()
    const customer = await createTestCustomer()

    const result = await CheckoutSaga.execute({ cart, customer })

    expect(result.success).toBe(true)
    expect(result.data.order).toBeDefined()

    // Verify side effects
    const order = await db.get($.Order, result.data.order.id)
    expect(order.status).toBe('pending')

    const inventory = await $.Inventory.check(cart.items[0].id)
    expect(inventory.reserved).toBe(cart.items[0].quantity)
  })

  it('rolls back on payment failure', async () => {
    const cart = await createTestCart()
    const customer = await createInvalidPaymentCustomer()

    const result = await CheckoutSaga.execute({ cart, customer })

    expect(result.success).toBe(false)

    // Verify rollback
    const inventory = await $.Inventory.check(cart.items[0].id)
    expect(inventory.reserved).toBe(0)
  })
})

Best Practices

Do's

  1. Use semantic types - Leverage Schema.org and domain vocabularies
  2. Event-driven design - Loosely couple components with events
  3. Type safety - Use TypeScript for compile-time safety
  4. Test everything - Write comprehensive tests
  5. Idempotency - Make operations safe to retry
  6. Error handling - Handle failures gracefully
  7. Documentation - Document business logic clearly

Don'ts

  1. Don't skip types - Avoid any types
  2. Don't tightly couple - Use events instead of direct calls
  3. Don't ignore errors - Handle all failure cases
  4. Don't skip tests - Untested code breaks in production
  5. Don't hardcode - Use configuration and environment variables
  6. Don't block - Use async/await for I/O operations

CLI Tools

# Generate boilerplate
do generate service --name Analytics
do generate entity --type Product
do generate workflow --trigger "Order.created"

# Run development server
do dev

# Run tests
do test
do test:watch
do test:coverage

# Type checking
do typecheck
do typecheck:watch

# Build for production
do build

Next Steps


Build Tip: Write business logic that reads like business language. If developers can't understand your code, neither will AI.