Skip to content

Slicing Vocabulary & Rules

GLIMPSE uses a precise vocabulary to describe how code is organised within layers. Understanding these terms is necessary to place any new file correctly.

Vocabulary

Port
A delivery mechanism, named after the domain concept rather than the
technology.
Examples: cli, web, db, payment_api, email
The first axis for links and gates, known before any code exists.
Adapter
The specific technology implementing a port.
Examples: postgres, sqlite, argparse, stripe, sendgrid
One port can have multiple adapters — usually coexisting, not
interchangeable. payment_api/stripe and payment_api/paypal are both wired
and both live; which one handles a given payment is a business decision made
in a mill, through the protocols it holds. Genuine substitution
(db/postgres vs db/sqlite) is the rarer case: one adapter wired per
deployment, chosen in inits.
One technology can serve multiple ports. A full-stack framework shipping both an ORM and a request layer appears as db/{framework} and web/{framework} — two separate adapters that share nothing but a name.
Kind
The type of thing a links module holds, below the adapter.
Examples: models and repositories for a db adapter; transport,
types, signer for an API client.
Kinds are per-adapter. The db shape is not a universal template.
Noun
A fat data cow — the model cluster everything else hangs off.
Examples: invoices, customers, proposals, users
The primary slicing axis for pacts, mills, and specs.
Which nouns exist depends on what the system is for, not on the words in
the domain. An invoice tracker slices by invoices; a subscription service
slices by billing, and an invoice is a detail inside it.
Plurality is not prescribed; it follows the noun. events are many, a
panel is one.
Nouns are GLIMPSE's own axis, not a DDD import. If another axis fits a project better, slice by that instead; the layer rules don't change.
Verb
An activity cut inside a noun.
Examples: issue, refund, enroll, schedule
A verb module holds the records and logic of actions, not first-class data.
Verbs nest inside nouns: invoices might cut into issue and refund.
No catch-all verbs. manage, organize, and misc name no activity — if you cannot name a real one, the file is not too big yet.
Page
What the user touches — the slicing axis for gates, below port and adapter.
Gates take whatever grouping the interface already has: a command or command
group for a CLI, a page group and page — or a page and its subpages — for the
web, a view for a TUI, a tool for MCP.
Gates mirror the shape of the interface; mills mirror the domain. The two need not line up, and forcing them to is how a sitemap ends up in mills.
Entity
A persistence-level concept: the unit that a DTO and a repository wrap.
Narrower than a noun — one noun spans many entities.
Conceptual, not a file-layout axis. links slices by kind, so one models.py holds many entities' models. There is no links/db/{adapter}/{entity}.py.

Hierarchy

noun
└── verb
    └── entity

Boundary vs core

Place the code before slicing it. Code that crosses a boundary is a contract and goes to pacts; code that enforces business rules is core and goes to mills. DTOs are the case that trips people — see boundary vs core.

Slicing rules by layer

pacts, mills, specs — by noun, then verb

These start as single modules and become packages when they earn it. See Growing rules.

pacts.py                     # start here
pacts/{noun}.py              # flat while the noun is small
pacts/{noun}/{verb}.py       # cut by verb when the noun grows fat
mills/{noun}.py
mills/{noun}/{verb}.py
specs/{noun}.py

Each pacts module holds all boundary contracts for that noun or verb cut — DTOs, write TypedDicts, repository protocols, errors. Split by domain concern, never by technical kind. Contracts that belong to no noun follow the axis of the layer they serve — pacts/{port}.py for port machinery (TransactionProtocol), a module mirroring the inits registry for wiring contracts (pacts/services.pyServicesProtocol and the service protocols it names). See the placement algorithm.

pacts and mills share the noun/verb axis, but they are free to promote independently — mills/ may be a package while pacts.py is still one file. Each layer splits when its own size or friction says so.

inits — however is convenient

There is no axis to get right: inits is thin by construction and stays thin. Start as a single module; when one file stops being comfortable, split it the obvious way — a module per registry class, plus one that binds them.

inits.py                 # start here
inits/repositories.py    # promoted
inits/services.py
inits/middleware.py

Nothing rides on those names; pick what reads best. See inits.

Packages from day one: the port is known before you write any code.

links/{port}/{adapter}.py                 # the whole adapter is one module
links/{port}/{adapter}/{kind}.py          # once the kinds separate
links/{port}/{adapter}/{kind}/{module}.py # when a kind crosses ~1000 lines
links/{port}/{adapter}/__init__.py        # facade — re-exports the public surface

Examples:

links/db/sqlite.py
links/db/postgres/models.py
links/db/postgres/repositories.py
links/payment_api/stripe.py
links/email/sendgrid.py

gates — port / adapter / page

Packages from day one, for the same reason. Below the adapter, gates follows the shape of the interface itself — whatever grouping that interface already has.

gates/{port}/{adapter}.py                      # flat while there is one page
gates/{port}/{adapter}/{page}.py
gates/{port}/{adapter}/{page_group}/{page}.py  # whichever grouping
gates/{port}/{adapter}/{page}/{subpage}.py     # the interface already has

Examples:

gates/cli/argparse.py
gates/cli/argparse/export.py             # a CLI's pages are its commands
gates/cli/argparse/report/monthly.py     # ...grouped as the CLI groups them
gates/web/flask/dashboard.py
gates/web/flask/checkout/payment.py      # page group / page
gates/web/flask/proposal/comments.py     # page / subpage

The axis is the interface, never the domain: plenty of pages belong to no single noun, and forcing one on them drags business vocabulary into the interface. A gate's job is to mirror what the user sees.