confect/ directory (see Project Structure). Beyond those, organize your API as colocated *.spec.ts/*.impl.ts pairs, one pair per group. The group’s name is the file’s path within confect/ (its stem for top-level groups, the dot-joined directory path for nested groups).
Spec and impl files
Name each group’s spec and impl with.spec.ts and .impl.ts suffixes. Each file must default-export its GroupSpec or GroupImpl; additional named exports on .spec.ts (for example error classes) are fine.
A complete pair looks like this. The impl default-imports its sibling spec, passes it to FunctionImpl.make and GroupImpl.make, and finalizes the resulting layer with GroupImpl.finalize:
confect/notes.spec.ts
confect/notes.impl.ts
confect codegen after adding or changing specs and impls.
A file’s path within
confect/ determines the public Convex API path it
produces—confect/notes_and_random/notes.spec.ts becomes
internal.notes_and_random.notes.list. Renaming a file or directory renames
the API path, so treat these paths as part of your API’s contract.Native Convex functions
When a group wraps native Convex functions (for use with components or other libraries), place the plain function definitions in a file named after the group—without a suffix. This puts all three files for a group side by side:Middleware
Middleware is declared and implemented as a*.spec.ts/*.impl.ts pair too, but it belongs to no single group, so it lives in the reserved confect/middleware/ directory—one pair per middleware, each named after the middleware in PascalCase. Confect does not scan that directory for groups, so nothing is emitted into convex/ for it.
Node actions
Node action groups follow the same.spec.ts/.impl.ts naming and nesting conventions as any other group. A group is Node-runtime when its spec is built with GroupSpec.makeNode() (rather than GroupSpec.make()); its impl is otherwise identical to a non-node impl, passing the database schema from _generated/schema. Confect emits Convex’s "use node" directive into the generated module based on the spec.
Nested groups
When a group contains subgroups, place each subgroup’s.spec.ts/.impl.ts pair inside a subdirectory named after the parent group. The parent group itself does not need a spec or impl file—it is composed from its subgroups by their paths.
Full example
Putting it all together, a project using all of these conventions might look like this:confect
_generated
convexSchema.ts
refs.ts
schema.ts
services.ts
spec.ts
registeredFunctions
env.ts
notes_and_random
notes.ts
random.ts
workpool.ts
email.ts
tables
notes.ts
users.ts
id.ts
notes_and_random
notes.spec.ts
notes.impl.ts
random.spec.ts
random.impl.ts
middleware
RequireUser.spec.ts
RequireUser.impl.ts
tables
notes.ts
users.ts
email.spec.ts
email.impl.ts
env.spec.ts
env.impl.ts
http.ts
workpool.ts
workpool.spec.ts
workpool.impl.ts