45 minlesson

Phase 1: Team Setup, Architecture & Integration Planning

Phase 1: Team Setup, Architecture & Integration Planning

Overview

Success in a team project requires clear architecture, well-defined boundaries, and effective communication. In this phase, you'll form your team, assign vertical slices, set up the shared codebase, and design integration points that allow independent development while ensuring seamless collaboration.

Learning Objectives

By the end of this phase, you will:

  • Understand vertical slice architecture for team collaboration
  • Have a complete monorepo setup with shared code
  • Know your team member responsibilities and deliverables
  • Have designed clear integration contracts
  • Established Git workflow and code review process

Requirements

1. Team Formation & Role Assignment

Team Size: 3 people

Role Assignments:

Person 1: Shipment Creation Engineer

  • Shipment intake and order creation
  • Carrier selection and routing
  • Address validation
  • Cost estimation
  • Patterns: Factory Method, Strategy, Chain of Responsibility, Builder

Person 2: Package Tracking Engineer

  • Real-time tracking interface
  • Status update system
  • Delivery confirmation
  • Exception handling
  • Patterns: State, Observer, Memento, Command

Person 3: Customer Portal Developer

  • Customer-facing order management
  • Multi-channel notifications
  • Delivery preferences
  • Reporting and analytics
  • Patterns: Observer, Template Method, Mediator, Facade

2. Project Setup

Monorepo Structure:

bash
1# Initialize Next.js project
2npx create-next-app@latest shipment-platform --typescript --tailwind --app
3cd shipment-platform
4
5# Additional dependencies
6npm install zod date-fns recharts
7npm install @tanstack/react-query
8npm install -D vitest @testing-library/react @testing-library/jest-dom

Required Directory Structure:

1shipment-platform/
2├── src/
3│ ├── app/ # Next.js App Router
4│ │ ├── (routes)/
5│ │ │ ├── shipments/ # Person 1's routes
6│ │ │ ├── tracking/ # Person 2's routes
7│ │ │ ├── portal/ # Person 3's routes
8│ │ │ └── layout.tsx
9│ │ └── api/
10│ │ ├── shipments/ # Person 1's API
11│ │ ├── tracking/ # Person 2's API
12│ │ └── notifications/ # Person 3's API
13│ ├── features/ # Feature modules (vertical slices)
14│ │ ├── shipment-creation/ # Person 1's feature
15│ │ │ ├── components/
16│ │ │ ├── services/
17│ │ │ ├── hooks/
18│ │ │ └── types.ts
19│ │ ├── package-tracking/ # Person 2's feature
20│ │ │ ├── components/
21│ │ │ ├── services/
22│ │ │ ├── hooks/
23│ │ │ └── types.ts
24│ │ └── customer-portal/ # Person 3's feature
25│ │ ├── components/
26│ │ ├── services/
27│ │ ├── hooks/
28│ │ └── types.ts
29│ ├── shared/ # Shared code (team collaboration)
30│ │ ├── types/ # Shared type definitions
31│ │ │ ├── domain.ts
32│ │ │ ├── api.ts
33│ │ │ └── events.ts
34│ │ ├── components/ # Shared UI components
35│ │ │ ├── ui/ # Base components
36│ │ │ └── layout/
37│ │ ├── lib/ # Shared utilities
38│ │ │ ├── storage.ts
39│ │ │ ├── formatters.ts
40│ │ │ └── validators.ts
41│ │ └── hooks/ # Shared custom hooks
42│ ├── services/ # Shared services
43│ │ └── event-bus.ts # For inter-feature communication
44│ └── config/
45│ └── constants.ts
46├── docs/
47│ ├── architecture.md
48│ ├── integration-contracts.md
49│ └── team-workflow.md
50└── package.json

3. Shared Type Definitions

Create src/shared/types/domain.ts:

typescript
1// Core domain types (shared by all team members)
2
3export interface Address {
4 id?: string;
5 name: string;
6 street1: string;
7 street2?: string;
8 city: string;
9 state: string;
10 postalCode: string;
11 country: string;
12 phone?: string;
13}
14
15export interface Package {
16 id: string;
17 dimensions: PackageDimensions;
18 weight: PackageWeight;
19 type: PackageType;
20 declaredValue?: number;
21}
22
23export interface PackageDimensions {
24 length: number;
25 width: number;
26 height: number;
27 unit: 'in' | 'cm';
28}
29
30export interface PackageWeight {
31 value: number;
32 unit: 'lbs' | 'kg';
33}
34
35export type PackageType = 'envelope' | 'box' | 'tube' | 'pallet';
36
37export type CarrierName = 'USPS' | 'FedEx' | 'UPS' | 'DHL';
38
39export type ServiceSpeed = 'overnight' | 'two-day' | 'standard' | 'economy';
40
41// Shipment entity (created by Person 1, used by Person 2 & 3)
42export interface Shipment {
43 id: string;
44 orderId: string;
45 package: Package;
46 origin: Address;
47 destination: Address;
48 carrier: CarrierName;
49 serviceLevel: string;
50 trackingNumber: string;
51 status: ShipmentStatus;
52 estimatedDelivery: Date;
53 actualDelivery?: Date;
54 cost: number;
55 createdAt: Date;
56 updatedAt: Date;
57 createdBy: string; // User ID
58}
59
60// Shipment status (managed by Person 2)
61export enum ShipmentStatus {
62 CREATED = 'created',
63 PICKED_UP = 'picked_up',
64 IN_TRANSIT = 'in_transit',
65 OUT_FOR_DELIVERY = 'out_for_delivery',
66 DELIVERED = 'delivered',
67 EXCEPTION = 'exception',
68 CANCELLED = 'cancelled',
69}
70
71// Tracking event (Person 2's domain)
72export interface TrackingEvent {
73 id: string;
74 shipmentId: string;
75 status: ShipmentStatus;
76 location: string;
77 timestamp: Date;
78 description: string;
79 metadata?: Record<string, unknown>;
80}
81
82// Notification (Person 3's domain)
83export interface Notification {
84 id: string;
85 userId: string;
86 shipmentId: string;
87 type: NotificationType;
88 channel: NotificationChannel;
89 subject: string;
90 message: string;
91 sentAt: Date;
92 readAt?: Date;
93}
94
95export enum NotificationType {
96 SHIPMENT_CREATED = 'shipment_created',
97 STATUS_UPDATE = 'status_update',
98 DELIVERY_CONFIRMATION = 'delivery_confirmation',
99 EXCEPTION_ALERT = 'exception_alert',
100}
101
102export enum NotificationChannel {
103 EMAIL = 'email',
104 SMS = 'sms',
105 PUSH = 'push',
106 IN_APP = 'in_app',
107}
108
109// Customer (Person 3's domain)
110export interface Customer {
111 id: string;
112 email: string;
113 name: string;
114 phone?: string;
115 preferences: CustomerPreferences;
116 createdAt: Date;
117}
118
119export interface CustomerPreferences {
120 notificationChannels: NotificationChannel[];
121 defaultOriginAddress?: Address;
122 savedAddresses: Address[];
123}

Create src/shared/types/events.ts:

typescript
1// Event types for inter-feature communication
2
3export enum EventType {
4 SHIPMENT_CREATED = 'shipment:created',
5 SHIPMENT_STATUS_CHANGED = 'shipment:status_changed',
6 TRACKING_EVENT_ADDED = 'tracking:event_added',
7 NOTIFICATION_SENT = 'notification:sent',
8}
9
10export interface DomainEvent<T = unknown> {
11 type: EventType;
12 payload: T;
13 timestamp: Date;
14 source: string; // Feature that emitted the event
15}
16
17// Specific event payloads
18export interface ShipmentCreatedPayload {
19 shipment: Shipment;
20}
21
22export interface ShipmentStatusChangedPayload {
23 shipmentId: string;
24 oldStatus: ShipmentStatus;
25 newStatus: ShipmentStatus;
26 timestamp: Date;
27}
28
29export interface TrackingEventAddedPayload {
30 shipmentId: string;
31 event: TrackingEvent;
32}

4. Integration Contracts

Document in docs/integration-contracts.md:

markdown
1# Integration Contracts Between Team Members
2
3## Person 1 → Person 2 Integration
4
5**Contract**: When a shipment is created, emit ShipmentCreated event
6
7**Person 1 Responsibility**:
8- Create shipment in database
9- Generate tracking number
10- Emit `SHIPMENT_CREATED` event via EventBus
11
12**Person 2 Expectation**:
13- Listen for `SHIPMENT_CREATED` event
14- Initialize tracking with first event (status: CREATED)
15- Create tracking timeline entry
16
17**Data Contract**:
18```typescript
19interface ShipmentCreatedEvent extends DomainEvent {
20 type: EventType.SHIPMENT_CREATED;
21 payload: {
22 shipment: Shipment;
23 };
24}

API Contract:

typescript
1// Person 1 provides
2POST /api/shipments
3Response: Shipment
4
5// Person 2 consumes
6GET /api/tracking/:trackingNumber
7Response: TrackingEvent[]

Person 2 → Person 3 Integration

Contract: When shipment status changes, emit StatusChanged event for notifications

Person 2 Responsibility:

  • Update shipment status
  • Create tracking event
  • Emit SHIPMENT_STATUS_CHANGED event

Person 3 Expectation:

  • Listen for SHIPMENT_STATUS_CHANGED event
  • Determine if notification should be sent (based on user preferences)
  • Send notification via appropriate channel(s)

Data Contract:

typescript
1interface ShipmentStatusChangedEvent extends DomainEvent {
2 type: EventType.SHIPMENT_STATUS_CHANGED;
3 payload: {
4 shipmentId: string;
5 oldStatus: ShipmentStatus;
6 newStatus: ShipmentStatus;
7 timestamp: Date;
8 };
9}

Person 3 → Person 1 Integration

Contract: Customer can reorder from portal using previous shipment data

Person 3 Responsibility:

  • Display shipment history
  • Provide "Reorder" button
  • Call Person 1's shipment creation API with prefilled data

Person 1 Expectation:

  • Accept shipment creation requests
  • Validate all data even if from reorder
  • Return created shipment

API Contract:

typescript
1// Person 3 calls
2POST /api/shipments
3Body: CreateShipmentRequest
4Response: Shipment
1
2### 5. Event Bus for Inter-Feature Communication
3
4**Create `src/services/event-bus.ts`:**
5
6```typescript
7import { DomainEvent, EventType } from '@/shared/types/events';
8
9type EventHandler<T = unknown> = (event: DomainEvent<T>) => void | Promise<void>;
10
11class EventBus {
12 private static instance: EventBus;
13 private handlers: Map<EventType, Set<EventHandler>>;
14
15 private constructor() {
16 this.handlers = new Map();
17 }
18
19 static getInstance(): EventBus {
20 if (!EventBus.instance) {
21 EventBus.instance = new EventBus();
22 }
23 return EventBus.instance;
24 }
25
26 subscribe<T>(eventType: EventType, handler: EventHandler<T>): () => void {
27 if (!this.handlers.has(eventType)) {
28 this.handlers.set(eventType, new Set());
29 }
30
31 this.handlers.get(eventType)!.add(handler as EventHandler);
32
33 // Return unsubscribe function
34 return () => {
35 this.handlers.get(eventType)?.delete(handler as EventHandler);
36 };
37 }
38
39 async publish<T>(event: DomainEvent<T>): Promise<void> {
40 const handlers = this.handlers.get(event.type);
41
42 if (!handlers || handlers.size === 0) {
43 console.warn(`No handlers registered for event: ${event.type}`);
44 return;
45 }
46
47 const promises = Array.from(handlers).map(handler => {
48 try {
49 return Promise.resolve(handler(event));
50 } catch (error) {
51 console.error(`Error in event handler for ${event.type}:`, error);
52 return Promise.resolve();
53 }
54 });
55
56 await Promise.allSettled(promises);
57 }
58}
59
60export const eventBus = EventBus.getInstance();

6. Git Workflow

Branching Strategy:

1main
2├── develop
3 ├── feature/person1-shipment-creation
4 ├── feature/person2-tracking-system
5 └── feature/person3-customer-portal

Workflow:

  1. Each person works on their feature branch
  2. Regular commits with meaningful messages
  3. Pull requests to develop branch
  4. Code review by at least one other team member
  5. Merge to develop after approval
  6. Integration testing on develop
  7. Periodic releases to main

Commit Message Convention:

1type(scope): description
2
3feat(shipment): add carrier selection logic
4fix(tracking): resolve status transition bug
5docs(readme): update setup instructions
6test(portal): add notification tests

7. Team Communication

Required Regular Meetings:

  1. Kickoff Meeting (1-2 hours)

    • Assign roles
    • Review architecture
    • Discuss integration points
    • Set timeline and milestones
  2. Daily Standups (15 minutes)

    • What did you complete yesterday?
    • What will you work on today?
    • Any blockers?
  3. Weekly Integration Sync (30 minutes)

    • Test integration points
    • Resolve conflicts
    • Align on next steps
  4. Code Review Sessions

    • Review each other's PRs
    • Share pattern implementations
    • Discuss improvements

Communication Channels:

  • Slack/Discord for async communication
  • GitHub for code reviews and discussions
  • Shared document for decisions and notes

Deliverables

By the end of Phase 1, your team must have:

  • Team formed with roles assigned
  • Monorepo set up with directory structure
  • Shared types defined in src/shared/types/
  • Event bus implemented for inter-feature communication
  • Integration contracts documented
  • Git repository initialized with branching strategy
  • Team workflow documented
  • Architecture diagram showing vertical slices and integration points
  • First team meeting completed with notes

Architecture Diagram Requirements

Create a diagram showing:

1┌─────────────────────────────────────────────────────────────┐
2│ User Interface │
3├─────────────┬─────────────────────┬─────────────────────────┤
4│ Person 1 │ Person 2 │ Person 3 │
5│ Shipment │ Tracking │ Portal │
6│ Creation │ System │ & Notifications │
7├─────────────┼─────────────────────┼─────────────────────────┤
8│ Components │ Components │ Components │
9│ Hooks │ Hooks │ Hooks │
10│ Services │ Services │ Services │
11├─────────────┴─────────────────────┴─────────────────────────┤
12│ Event Bus (Integration) │
13├──────────────────────────────────────────────────────────────┤
14│ Shared Types & Utilities │
15├──────────────────────────────────────────────────────────────┤
16│ Data Layer │
17│ (localStorage / Mock API) │
18└──────────────────────────────────────────────────────────────┘
19
20Events Flow:
21Person 1 → EventBus → Person 2 (ShipmentCreated)
22Person 2 → EventBus → Person 3 (StatusChanged)
23Person 3 → Person 1 API (Reorder)

Validation Checklist

Before moving to feature development:

  • All team members can run npm run dev successfully
  • Shared types compile without errors
  • Event bus can publish and subscribe to events
  • Git workflow is established and understood
  • Each team member knows their responsibilities
  • Integration contracts are clear and agreed upon
  • All team members have access to shared resources

Resources


Common Pitfalls to Avoid

  1. Tight coupling: Keep vertical slices independent, communicate via events
  2. Merge conflicts: Communicate frequently about overlapping changes
  3. Inconsistent types: Always use shared types, never duplicate
  4. Poor communication: Over-communicate rather than under-communicate
  5. Working in isolation: Integrate early and often

Estimated Time

  • Team formation and kickoff: 2 hours
  • Project setup: 2 hours
  • Shared types definition: 2 hours
  • Integration planning: 3 hours
  • Documentation: 2 hours
  • Total: 11 hours (distributed across team)

Next Steps

Each team member proceeds to their respective vertical slice:

  • Person 1 → Phase 2: Shipment Creation & Carrier Management
  • Person 2 → Phase 3: Package Tracking & Status Management
  • Person 3 → Phase 4: Customer Portal & Notifications

All members work in parallel on their features while maintaining integration contracts.