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
- Use semantic types - Leverage Schema.org and domain vocabularies
- Event-driven design - Loosely couple components with events
- Type safety - Use TypeScript for compile-time safety
- Test everything - Write comprehensive tests
- Idempotency - Make operations safe to retry
- Error handling - Handle failures gracefully
- Documentation - Document business logic clearly
Don'ts
- Don't skip types - Avoid
anytypes - Don't tightly couple - Use events instead of direct calls
- Don't ignore errors - Handle all failure cases
- Don't skip tests - Untested code breaks in production
- Don't hardcode - Use configuration and environment variables
- 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 buildNext Steps
- Test → - Test your Business-as-Code
- Deploy → - Deploy to production
- Services → - Build Services-as-Software
Build Tip: Write business logic that reads like business language. If developers can't understand your code, neither will AI.