Files
motia/bitbylaw/.cursor/architecture/architecture.mdc
2025-10-19 14:57:07 +00:00

97 lines
3.4 KiB
Plaintext

---
description: How to structure your Motia project
globs:
alwaysApply: true
---
# Architecture Guide
## Overview
This guide covers the architecture of a Motia project.
## File Structure
All step files should be underneath the `steps/` folder.
Underneath the `steps/` folder, create subfolders for Flows. Flows are used to group steps together.
## Step Naming Conventions
### Typescript
- Use kebab-case for filenames: `resource-processing.step.ts`
- Include `.step` before language extension
### Python
- Use snake_case for filenames: `data_processor_step.py`
- Include `_step` before language extension
### Global
- Match handler names to config names
- Use descriptive, action-oriented names
## Code Style Guidelines
- **JavaScript**: Use modern ES6+ features, async/await, proper error handling
- **TypeScript**: Make sure you use the correct Handlers type that is auto generated on the `types.d.ts` file.
## Defining Middlewares
Middleware is a powerful feature in Motia to help adding common validation, error
handling and other common logic to your steps.
- Make sure to add all the middlewares in a single folder, called `middlewares/`.
- Create a comprehensive file name for the middleware, like `auth.middleware.ts`.
- Follow SOLID principles with separation of concerns in middlewares, create a middleware for each responsibility.
- Use core middleware to handle ZodError gracefully (see [Error Handling Guide](./error-handling.mdc))
- Rate limiting and CORS are not needed to be handled in middleware since they're an infrastructure concern.
## Domain Driven Design
Make sure you follow Domain Driven Design principles in your project.
- Create `/src/services` folder to store your services, this is where it holds business logic.
- Create `/src/repositories` folder to store your repositories, this is where it holds data access logic.
- Create `/src/utils` folder to store your utility functions.
- Models and DTOs are not quite necessary, we can rely on zod to create the models and DTOs from the steps.
- Controller layer is the Steps, it should have mostly logic around validation and calling services.
- Avoid having Service methods with just a call to the Repository, it should have some logic around it, if it doesn't have, then Steps can have access to repositories directly.
### Services
Defining services can be done in the following way:
- Create a folder underneath `/src/services/` folder, like `/src/services/auth/`.
- Create a file inside the folder called `index.ts`.
- Inside `index.ts`, export a constant with the name of the service, with the methods as properties.
- Methods should be defined as separate files, use export named functions.
- Use the service in the Steps.
#### Example
```typescript
/**
* Business logic for authentication defined in a separate file in the same folder.
*/
import { login } from './login'
/**
* Constant with the name of the service, with the methods as properties.
*/
export const authService = {
login
}
```
## Logging and observability
- Make sure to use the Logger from Motia (from context object) to log messages.
- Make sure to have visibility of what is going on in a request
- Before throwing errors, make sure to log the issue, identify if issue is a validation blocker, then log with `logger.warn`, if it's something that is not supposed to happen, then log with `logger.error`.
- Make sure to add context to the logs to help identify any potential issues.