After struggling with docs in Part 1, I finally touched some code.
This was the start of the actual domain modeling process: defining the core business entities of the app:
-
Tenant
: represents a customer account (company/org) -
User
: belongs to a tenant and interacts with the system -
Project
: something users can create and manage under their tenant
Each model is defined in its own file inside internal/domain/
, keeping things modular and easy to scale.
Why Start with Domain?
- Because the domain layer is the heart of the app.
- And, let's be honest. It makes me look like I know what I'm doing
Directory Layout
I’m keeping the structure… well, not exactly simple.
But trust me, I'm pretending I know what I'm doing
internal/
└── domain/
├── tenant/
├── user/
└── project/
Each entity gets its own package. It might look like overkill now, but it will pay off as things grow.
What's next
Domain Rules
To keep my domain layer consistent (and to future-proof my sanity), I started writing some generic domain rules in .mdc
files.
Here’s what I’ve got so far:
-
entity.mdc
, defines how entities should be structured (fields, IDs, invariants) -
generic-types.mdc
, documents reusable components likeIdentity
,Enumerated String
types. -
unit-test.mdc
, outlines rules for generating unit tests for domain entities
These arent just notes. They act as Cursor-aware prompts or codegen contracts.
Its a bit like meta-programming: I describe the rules, and Cursor helps generate code that follows them.
So yes, I am basically writing documentation for an AI to read X))
Entity
Once I had my entity.mdc
rule in place, I started defining specific entity contracts. Beginning with tenant.mdc
.
Here’s how it works: instead of jumping straight into code, I describe the entity and its behavior in Markdown, like this:
# Tenant
This rule describes the **tenant** entity and its behavior.
## Entity
### Tenant
- ID: Identity of Tenant – New Identity
- Name: string – constructor input
- Status: Enumerated string of "active", "inactive", default("active")
This isn't just documentation — Cursor uses it to generate consistent, valid Go code that follows my conventions.
It reads the structure, applies the meta-rules from entity.mdc
, and gives me a complete Go struct, constructor, and even basic validation.
So in a way, I am designing the system in plain text first, and letting AI turn it into working code.
And honestly? I amm starting to feel like it writes Go better than I do X)).
Links, if you're curious
Next Up
Now that the domain layer is in place, I'm going to focus on session management and authentication.
I'll be storing sessions in Redis (instead of using JWTs) so I can invalidate them easily — a pattern I've used and loved in past projects.
Top comments (2)
While others try to develop code in small stages one by one with short prompts 😆, here the prompt is applied completely to form a context of constraints or business in the .mdc file 😎 so that the AI cursor can understand and perform generation.
Glad you got the point! I believe "vibe coding" isn't just about writing prompts. It's about building a shared understanding with the AI. Over time, it's like working with a partner who learns and adapts to your habits.