Structure and organize Encore.ts services and applications. Use when creating new services, deciding on service boundaries, organizing code, or planning application architecture. Keywords: service, microservice, monolith, structure, architecture, organize, module, encore.service.ts.
Organizes Encore.ts services and applications with proper structure and boundaries.
/plugin marketplace add encoredev/skills/plugin install encoredev-encore-skills-plugins-encore-skills@encoredev/skillsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Every Encore service needs an encore.service.ts file:
// encore.service.ts
import { Service } from "encore.dev/service";
export default new Service("my-service");
my-service/
├── encore.service.ts # Service definition (required)
├── api.ts # API endpoints
└── db.ts # Database (if needed)
Best for new projects - start simple, split later if needed:
my-app/
├── package.json
├── encore.app
├── encore.service.ts
├── api.ts
├── db.ts
└── migrations/
└── 001_initial.up.sql
For distributed systems with clear domain boundaries:
my-app/
├── encore.app
├── package.json
├── user/
│ ├── encore.service.ts
│ ├── api.ts
│ └── db.ts
├── order/
│ ├── encore.service.ts
│ ├── api.ts
│ └── db.ts
└── notification/
├── encore.service.ts
└── api.ts
Group related services into systems:
my-app/
├── encore.app
├── commerce/
│ ├── order/
│ │ └── encore.service.ts
│ ├── cart/
│ │ └── encore.service.ts
│ └── payment/
│ └── encore.service.ts
├── identity/
│ ├── user/
│ │ └── encore.service.ts
│ └── auth/
│ └── encore.service.ts
└── comms/
├── email/
│ └── encore.service.ts
└── push/
└── encore.service.ts
Import other services from ~encore/clients:
import { user } from "~encore/clients";
export const getOrderWithUser = api(
{ method: "GET", path: "/orders/:id", expose: true },
async ({ id }): Promise<OrderWithUser> => {
const order = await getOrder(id);
const orderUser = await user.get({ id: order.userId });
return { ...order, user: orderUser };
}
);
Split when you have:
| Signal | Action |
|---|---|
| Different scaling needs | Split (e.g., auth vs analytics) |
| Different deployment cycles | Split |
| Clear domain boundaries | Split |
| Shared database tables | Keep together |
| Tightly coupled logic | Keep together |
| Just organizing code | Use folders, not services |
import { Service } from "encore.dev/service";
import { middleware } from "encore.dev/api";
const loggingMiddleware = middleware(
{ target: { all: true } },
async (req, next) => {
console.log(`Request: ${req.requestMeta?.path}`);
return next(req);
}
);
export default new Service("my-service", {
middlewares: [loggingMiddleware],
});
~encore/clients for cross-service calls (never direct imports)