YouBothAgent▾
You — Business rules and flows you own. Read these yourself.
Both — Know the idea; your agent follows the details.
Agent — Conventions and references your agent follows. Look up as needed.
Introduction▾
Tutorials▾
Core Concepts▾
Architecture▾

Delivery Feature

The ice cream shop is so successful that delivery orders are flooding in! Now we need to manage delivery orders. A delivery driver can deliver multiple orders at once, which means we need to create a relationship between deliveries and orders. This is a classic one-to-many relationship - one Delivery contains many IcecreamOrders.
In this tutorial, you'll learn how to:
  • Define relationships between models with Light model references
  • Trigger side effects when related data is created
  • Build UI components for selecting and displaying related data

Create Delivery Module

First, let's create the Delivery module using the CLI. This module will connect multiple ice cream orders into a single delivery batch.
Terminal

Define Relationship

Now let's define the Delivery model with a relationship to IcecreamOrder. The key is using LightIcecreamOrder as the field type - the delivery stores each order's id, and reading a delivery hands the orders back as LightIcecreamOrder.
apps/koyo/lib/delivery/delivery.constant.ts
Let's understand the key relationship pattern:
field([LightIcecreamOrder], { minlength: 1 })
This defines a one-to-many relationship as an array of order references. The "Light" version carries only the fields a list shows (serveType, size, toppings, status), so a delivery loads its orders without their full documents.
Stored as ids
The delivery document keeps only the order ids, and the orders are loaded whenever a delivery is read. A delivery therefore always shows each order's current status, never a copy taken when it was created.
Add dictionary entries for the Delivery model:
apps/koyo/lib/delivery/delivery.dictionary.ts
Now let's implement the service layer with lifecycle hooks. When a delivery is created, all associated orders should be marked as finished:
apps/koyo/lib/delivery/delivery.service.ts
Key service patterns for related data:
service<srv.IcecreamOrderService>()
Injects the IcecreamOrderService so DeliveryService can interact with orders. This enables cross-model operations.
_postCreate
A lifecycle hook that runs after a delivery is created. It iterates through all linked orders and marks them as finished, which keeps cascading updates consistent.
_preUpdate
Prevents updates to deliveries by throwing an Err. Once a delivery is created, it becomes immutable - ensuring data integrity.
The generated slice reads "cru: None", so nobody can create a delivery yet. Open creation the way the practice tutorial did for orders. Updates stay closed, and _preUpdate refuses them on the server too:
apps/koyo/lib/delivery/delivery.signal.ts
Now let's create the Template component for selecting related orders. The Field.Children component is designed specifically for selecting related data:
apps/koyo/lib/delivery/Delivery.Template.tsx
Key features of Field.Children:
  • slice: Specifies which slice provides the selectable options. Here it's 'icecreamOrderInDelivery' - a slice filtered for delivery-eligible orders.
  • initArgs: Arguments passed to the slice, one entry per argument. [["served"]] sets statuses to ["served"], so only orders ready to go out are listed.
  • renderOption: Custom render function for each selectable option. Shows order ID for easy identification.
Add a new slice to IcecreamOrder specifically for the delivery selection UI. This filters orders by status and serve type:
apps/koyo/lib/icecreamOrder/icecreamOrder.signal.ts
Add arguments to support serveType filtering in the byStatuses query declaration in the document.
apps/koyo/lib/icecreamOrder/icecreamOrder.document.ts
Add dictionary entries for the new slice:
apps/koyo/lib/icecreamOrder/icecreamOrder.dictionary.ts
Now let's create the Unit component to display deliveries with their related orders:
apps/koyo/lib/delivery/Delivery.Unit.tsx
Notice how we iterate through delivery.icecreamOrders and render each one using the IcecreamOrder.Unit.Card component. The orders arrive loaded with the delivery, so the Unit runs no query of its own.
Delivery.View still renders the name field the CLI generated, which no longer exists. Render the orders there the same way:
apps/koyo/lib/delivery/Delivery.View.tsx
Create the Zone component with a modal for creating new deliveries:
apps/koyo/lib/delivery/Delivery.Zone.tsx
The submitOption.onSuccess callback updates the local state with the finished orders, keeping the UI in sync with the database changes.
Finally, let's integrate everything into the main page using Tab components to organize orders and deliveries:
apps/koyo/page/_index.tsx
Key features of this integrated page:
  • Tab: Organizes related content into switchable panels. Tab.Menu styles the active and inactive tabs itself, and activeClassName adds to the active one only.
  • fetch.init*() without await: Both slice queries leave at call time and each Tab.Panel gets its own promise, so the two tabs load in parallel and neither waits for the other.

Summary

  • Reference another model through its Light class to load only the fields you show
  • A relation stores ids, so every read shows the related data as it is now
  • Use lifecycle hooks for maintaining data consistency
  • Create dedicated slices for relationship selection UIs
All core tutorials are complete. Explore the Architecture section to see how everything works together.

Released under the MIT License

Connect your AI to these docs

MCPhttps://akanjs.com/mcp
Copyright © 2026 Akan.js All rights reserved.System managed bybassman