projection

Creates read-side projections as schema-driven free records for TypeScript and Go backends.

4|Updated Jul 30, 2026
One-click install
npx skills add https://github.com/gabriellst/codm --skill projection-gabriellst
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: projection
Source: https://github.com/gabriellst/codm/tree/main/.claude/skills/projection
Command: npx skills add https://github.com/gabriellst/codm --skill projection-gabriellst

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve? When building CQRS systems, read models often diverge from write models, requiring denormalized views, aggregations, and cross-context joins. This Skill guides the creation of read-side projections — free record classes with no base class and no invariants — that materialize domain views for specific UI and query needs, paired with projectors that drive them from events. ## Core Features & Use Cases - Language dispatch hub: Routes to TypeScript or Go playbooks based on file extension, with per-language registries of patterns and bad practices. - Canonical flow enforcement: Codifies the find → applyEvent → save flow, with method-overloaded create/applyEvent in TypeScript and ApplyX methods in Go. - Modeling decision framework: Helps decide whether a projection is needed, where it lives (domain context vs ui BFF), which archetype applies, and the level of denormalization. - Use Case: When adding a chat sidebar that needs unread counts and last-message timestamps, use this Skill to scaffold a fully denormalized projection plus its repository with canonical findByKey/save/insertIfNew methods and justified atomic ops. ## Quick Start Ask the AI to create a projection for a specific context and name, for example by running the CLI scaffolder with bun cli projection channel Message and then filling in the event union and applyEvent overloads.

Frequently Asked Questions about projection

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I create a read-side projection in a CQRS TypeScript backend?

Define a flat Zod schema, infer a Props type, export an event union, and write a plain class with overloaded static create(event) and applyEvent(event) methods that switch on event.name. Pair it with a repository exposing findByKey, save, and insertIfNew.

When should I add a projection instead of a Drizzle query?

Add a projection only when the read shape is an expensive denormalization or aggregation, a cross-service consumer needs mirrored fields, or derived columns like counters and ranks are updated by events from many aggregates. Otherwise write a query use case against existing aggregate tables.

Where do cross-context projections live in this architecture?

Cross-context projections that span multiple bounded contexts live in the ui BFF context under ui/projections/. Domain contexts must not subscribe to events from other domain contexts; that coupling belongs only in the BFF.

When are atomic repository operations justified over find-applyEvent-save?

Atomic ops are edge cases justified by five named triggers: hot-row contention, bulk updates across N rows, monotonic constraints, conditional updates needing SQL atomicity, and cache-mirror bulk upserts. Each atomic method must carry a comment naming its trigger.

Why must applyEvent use switch(event.name) even for a single event?

The switch on event.name with a default never case is the mandatory canonical dispatch shape, enforced by detector PS-04. It provides exhaustiveness checking and makes adding a second event a new case rather than a restructure.

Can a projection extend BaseEntity or AggregateRoot?

No. Projections are free records with no base class, no invariants, no validation, and no domain events. Extending BaseEntity drags write-side baggage like identity and event-raising into a read model, which is flagged as a critical bad practice.