Your First State (Entity)
We are building the concert app — users follow artists, artists announce shows, and a query returns upcoming shows for followed artists. Every getting-started tutorial walks through one layer of this same application.
State defines the entity types — one snapshot per (stream, entity_id). Everything else references these types.
Set up the project
Scaffold the app with the CLI — do this once before the layer tutorials (or before the Quickstart):
causet initWhen prompted:
| Prompt | Choose |
|---|---|
| Project name | concert-app (or any name) |
| Template | Concert app — follow artists, announce shows, query upcoming shows |
cd concert-appThe template creates app.causet, starter files for every DSL layer, and a README. The tutorials below explain what each file does — you can follow along in the project you just created.
# app.causet (created by the template)
dsl_version: 1
app: concert_app
includes:
states: [./states/**/*.state.causet]
events: [./events/**/*.events.causet]
actions: [./actions/**/*.actions.causet]
projections: [./projections/**/*.projections.causet]
queries: [./queries/**/*.queries.causet]
relationships: [./relationships/**/*.relationships.causet]Prerequisites: Install Causet — CLI installed and authenticated against Causet Cloud.
What you define
| Field | Purpose |
|---|---|
entity_key | Which payload field identifies an instance (e.g. user_id) |
fields | Typed columns on the entity snapshot |
default | Initial value when the entity is first created |
Streams are derived from the state name — user becomes user_stream at runtime.
Open the state files the template created under states/:
User entity
# states/user.state.causet
state:
user:
entity_key: user_id
fields:
- name: username
type: string
default: ""
- name: following_count
type: int
default: 0Artist entity
# states/artist.state.causet
state:
artist:
entity_key: artist_id
fields:
- name: name
type: string
default: ""
- name: follower_count
type: int
default: 0Each instance is addressed as (stream, entity_id) — e.g. user user-1 on user_stream, artist artist-pearl-jam on artist_stream.
How state is used at runtime
- An intent targets
(stream, entity_id)— the runtime loads the current snapshot. - Core rules mutate fields (
set,add, …). - The committed snapshot is stored in PostgreSQL.
- Events emitted during the intent reference the entity via
entity_expr.
Entity snapshots are the write side. Projections are separate read models.
Verify entity state
After deploying and running intents:
causet inspect entity user-1 \
--fork main \
--stream user_streamConcert app so far
After causet init → Concert app, your project includes:
concert-app/
app.causet
states/
user.state.causet
artist.state.causet
… (events, actions, projections, queries, relationships — covered in later tutorials)This tutorial focuses on states/.
Common mistakes
Wrong entity_key. Must match the field callers use as the entity ID in intents.
Modeling read tables as state. Use projections for list views and joins — not entity snapshots.
Next steps
- Your First Event —
ARTIST_FOLLOWEDandSHOW_ANNOUNCED - Complete Concert App — all layers assembled (jump ahead)
- State & Memory — snapshots and replay