clean-architecture-ts
Clean Architecture for Remix/TypeScript Apps
As Remix apps grow, loader and action functions can become bloated "God Functions". This skill emphasizes separation of concerns.
1. The Layers
A. The Web Layer (Loaders/Actions)
Responsibility: Parsing requests, input validation (Zod), and returning Responses (JSON/Redirect). Rule: NO business logic here. Only orchestration.
// app/routes/app.products.update.ts
export const action = async ({ request }: ActionFunctionArgs) => {
const { shop } = await authenticate.admin(request);
const formData = await request.formData();
// 1. Validate Input
const input = validateProductUpdate(formData);
// 2. Call Service
const updatedProduct = await ProductService.updateProduct(shop, input);
// 3. Return Response
return json({ product: updatedProduct });
};
B. The Service Layer (Business Logic)
Responsibility: The "What". Rules, calculations, error handling, complex flows. Rule: Framework agnostic. Should not know about "Request" or "Response" objects.
// app/services/product.service.ts
export class ProductService {
static async updateProduct(shop: string, input: ProductUpdateInput) {
// Business Rule: Can't update archived products
const existing = await ProductRepository.findByShopAndId(shop, input.id);
if (existing.status === 'ARCHIVED') {
throw new BusinessError("Cannot update archived product");
}
// Business Logic
const result = await ProductRepository.save({
...existing,
...input,
updatedAt: new Date()
});
return result;
}
}
C. The Repository Layer (Data Access)
Responsibility: The "How". interaction with Database (Prisma), APIs (Shopify Admin), or File System. Rule: Only this layer touches the DB/API.
// app/repositories/product.repository.ts
export class ProductRepository {
static async findByShopAndId(shop: string, id: string) {
return prisma.product.findFirstOrThrow({
where: { shop, id: BigInt(id) }
});
}
}
2. Directory Structure
app/
routes/ # Web Layer
services/ # Business Logic
repositories/ # Data Access (DB/API)
models/ # Domain Types / Interfaces
utils/ # Pure functions (math, string manipulation)
3. Dependency Injection (Optional but Recommended)
For complex apps, use a container like tsyringe to manage dependencies, especially for testing (mocking Repositories).
// app/services/order.service.ts
@injectable()
export class OrderService {
constructor(
@inject(OrderRepository) private orderRepo: OrderRepository,
@inject(ShopifyClient) private shopify: ShopifyClient
) {}
}
4. Error Handling
Create custom Error classes to differentiate between "Bad Request" (User error) and "Server Error" (System error).
// app/errors/index.ts
export class BusinessError extends Error {
public code = 422;
}
export class NotFoundError extends Error {
public code = 404;
}
Refactor your loader/action to catch these errors and return appropriate HTTP status codes.
More from toilahuongg/shopify-agents-kit
shopify-polaris-icons
Guide for using Shopify Polaris Icons in Shopify Apps. Covers icon usage patterns, accessibility, tone variants, and common icon categories for commerce applications.
19email-template-design
Design and build professional HTML email templates with inline CSS for broad email client compatibility. Use this skill when the user asks to create, design, or build email templates, newsletters, transactional emails (order confirmations, receipts, shipping notifications, password resets), marketing emails, welcome series, onboarding emails, abandoned cart emails, drip campaigns, or any HTML email layout. Covers responsive design, dark mode support, and compatibility with Gmail, Outlook (desktop + web), Apple Mail, Yahoo, and mobile clients.
18shopify-extensions
Guide for building and managing Shopify Extensions (Admin, Checkout, Theme, Post-purchase, etc.) using the latest Shopify CLI and APIs.
14shopify-api
Comprehensive guide for Shopify APIs in Remix apps. Covers Admin GraphQL/REST, Storefront API, all resources (products, orders, customers, inventory, collections, discounts, fulfillments, metafields, files), bulk operations, webhooks, resource pickers, and TypeScript patterns. Use when querying/mutating Shopify data or building integrations.
14shopify-polaris-viz
Guide for creating data visualizations in Shopify Apps using the Polaris Viz library. Use this skill when building charts, graphs, dashboards, or any data visualization components that need to integrate with the Shopify Admin aesthetic. Covers BarChart, LineChart, DonutChart, SparkLineChart, and theming.
13code-investigator
Comprehensive code investigation and audit tool. Discovers all project features, then dispatches parallel subagents to analyze issues, risks, dead code, missing functionality, and redundancies. Produces a prioritized risk report. Use this skill when the user asks to "investigate code", "audit project", "find risks", "check code quality", "analyze codebase", "what's wrong with this code", "project health check", "code review entire project", "find dead code", "find redundant code", or any request for a thorough codebase analysis.
11