Skip to content

Part 8: Design Stubs

Design stubs describe a pattern’s design before the implementation exists. They document the API contract, design decisions, and target path — making the “not yet built” parts of your system visible.

8.1 Create src/stubs/notification-service.stub.ts

Section titled “8.1 Create src/stubs/notification-service.stub.ts”
/** @libar-docs */
/**
* @libar-docs-pattern NotificationService
* @libar-docs-status roadmap
* @libar-docs-infra
* @libar-docs-arch-role service
* @libar-docs-arch-context identity
* @libar-docs-arch-layer infrastructure
* @libar-docs-target src/sample-sources/notification-service.ts
* @libar-docs-since design-session-1
* @libar-docs-uses AuthHandler
* @libar-docs-phase 2
* @libar-docs-release vNEXT
* @libar-docs-brief Notification service for auth lifecycle events
* @libar-docs-usecase "Send welcome email after user registration"
* @libar-docs-usecase "Send login alert for new device"
* @libar-docs-quarter Q2-2026
* @libar-docs-extract-shapes NotificationConfig, NotificationResult
*
* ## NotificationService - Auth Event Notifications
*
* Sends notifications (email, SMS) when authentication lifecycle
* events occur. Stub — target implementation does not exist yet.
*
* ### Design Decisions
*
* AD-1: Use event-driven notifications (not inline calls)
* AD-2: Support multiple channels via strategy pattern
*
* ### When to Use
*
* - When sending post-registration welcome emails
* - When alerting users about new device logins
*/
/** @libar-docs-shape reference-sample */
export interface NotificationConfig {
channel: "email" | "sms";
template: string;
recipientId: string;
}
/** @libar-docs-shape reference-sample */
export interface NotificationResult {
sent: boolean;
channel: string;
timestamp: Date;
}
TagExamplePurpose
@libar-docs-targetsrc/sample-sources/notification-service.tsPath where the real implementation will live. The resolver checks if this file exists.
@libar-docs-sincedesign-session-1Identifies which design session created the stub.
Terminal window
npm run process:stubs
{
"success": true,
"data": [
{
"pattern": "NotificationConfig",
"stubs": [
{
"stubName": "NotificationConfig",
"stubFile": "src/stubs/notification-service.stub.ts",
"targetPath": "",
"targetExists": false
}
],
"resolvedCount": 0,
"unresolvedCount": 1
},
{
"pattern": "NotificationResult",
"stubs": [
{
"stubName": "NotificationResult",
"stubFile": "src/stubs/notification-service.stub.ts",
"targetPath": "",
"targetExists": false
}
],
"resolvedCount": 0,
"unresolvedCount": 1
},
{
"pattern": "NotificationService",
"stubs": [
{
"stubName": "NotificationService",
"stubFile": "src/stubs/notification-service.stub.ts",
"targetPath": "src/sample-sources/notification-service.ts",
"since": "design-session-1",
"targetExists": false
}
],
"resolvedCount": 0,
"unresolvedCount": 1
}
]
}

What just happened: The stubs query returns 3 entries, not just 1. The shape patterns (NotificationConfig and NotificationResult) from the stub file are also tracked as separate stub entries. Only NotificationService has a targetPath and since field — the shapes have empty target paths because they lack their own @libar-docs-target tags. When you create the real file at src/sample-sources/notification-service.ts, the resolver will mark NotificationService as resolved.

  • src/stubs/notification-service.stub.ts exists with @libar-docs-target and @libar-docs-since
  • npm run process:stubs shows 3 stub entries with targetExists: false
  • npm run process:sources shows 1 stub file
  • Stubs document API contracts before implementation exists
  • @libar-docs-target tracks where the real file will live
  • @libar-docs-since records which design session created the stub
  • The stubs query shows resolution status — unresolved stubs are visible work items
  • Shape patterns defined in stub files also appear as separate stub entries