Skip to content

Setup Slices ​

Setup slices provide shared infrastructure that feature slices depend on. They handle concerns like database connections, theming, state management, API client configuration, error handling, and internationalization.

Overview ​

App Setup Slices (Nuxt)
┌─────────┬─────────┬───────┬─────────┬────────┐
│  theme  │  pinia  │  api  │  error  │  i18n  │
└─────────┴─────────┴───────┴─────────┴────────┘

API Setup Slices (NestJS)
┌─────────┬────────┬───────┬─────────┬──────────┐
│  prisma │  core  │  aws  │  redis  │  health  │
└─────────┴────────┴───────┴─────────┴──────────┘

Frontend Setup Slices ​

Located at app/slices/setup/. Each is a Nuxt layer registered in the root nuxt.config.ts.

Theme ​

Purpose: UI component library with Tailwind CSS and shadcn-vue.

app/slices/setup/theme/
├── nuxt.config.ts
├── tailwind.config.js
├── assets/scss/main.scss
├── components/ui/              # shadcn-vue components
├── plugins/fonts.ts
└── utils/cn.ts                 # className merge utility
typescript
// nuxt.config.ts
export default defineNuxtConfig({
  alias: { '#theme': currentDir },
  modules: ['@nuxtjs/tailwindcss', 'shadcn-nuxt'],
  tailwindcss: {
    cssPath: `${currentDir}/assets/scss/main.scss`,
    configPath: `${currentDir}/tailwind.config.js`,
  },
  shadcn: {
    prefix: '',
    componentDir: `${currentDir}/components/ui`,
  },
});

Key dependencies: @nuxtjs/tailwindcss, shadcn-nuxt, class-variance-authority, clsx, tailwind-merge, lucide-vue-next, vee-validate, zod

Pinia ​

Purpose: State management with automatic store discovery across all slices.

app/slices/setup/pinia/
└── nuxt.config.ts
typescript
// nuxt.config.ts
export default defineNuxtConfig({
  alias: { '#pinia': currentDir },
  modules: ['@pinia/nuxt'],
  pinia: {
    storesDirs: [
      'stores/**',
      'slices/*/stores/**',
      'slices/*/*/stores/**',
    ],
  },
});

Once configured, stores defined in any slice's stores/ folder are auto-imported. Use them directly without manual imports:

typescript
const authStore = useAuthStore();
const projectStore = useProjectStore();

API ​

Purpose: Generated TypeScript SDK from your backend's OpenAPI specification.

app/slices/setup/api/
├── nuxt.config.ts
├── api.config.ts                   # Axios client + interceptors
├── plugins/api.ts
└── data/repositories/api/          # Generated SDK (do not edit)
    ├── index.ts
    ├── services.gen.ts
    └── types.gen.ts
typescript
// nuxt.config.ts
export default defineNuxtConfig({
  alias: { '#api': resolve(currentDir, 'data/repositories/api') },
  runtimeConfig: {
    public: { apiUrl: process.env.API_URL || 'http://localhost:4000' },
  },
});

Generate the SDK from your running backend:

bash
bunx @hey-api/openapi-ts \
  -i http://localhost:4000/api-json \
  -o app/slices/setup/api/data/repositories/api \
  -c axios

Use the generated services in your code:

typescript
import { UsersService } from '#api';
const users = await UsersService.findAll();

WARNING

The files in data/repositories/api/ are auto-generated. Do not edit them manually — they will be overwritten on the next SDK generation.

Error ​

Purpose: Centralized error handling with toast notifications and i18n support.

app/slices/setup/error/
├── nuxt.config.ts
├── stores/error.ts
├── composables/useError.ts
├── utils/handleError.ts
└── locales/en.json

The error slice provides a useError composable for wrapping async operations:

typescript
const { handleAsync } = useError();

const result = await handleAsync(
  () => UsersService.createUser(data),
  { showToast: true, errorKey: 'createUser' }
);

It automatically catches errors, displays toast notifications, and stores error state that components can check.

i18n ​

Purpose: Multi-language support with browser detection and lazy loading.

app/slices/setup/i18n/
├── nuxt.config.ts
├── i18n.config.ts
└── locales/
    ├── en.json
    ├── fr.json
    └── es.json
typescript
// nuxt.config.ts
export default defineNuxtConfig({
  alias: { '#i18n': currentDir },
  modules: ['@nuxtjs/i18n'],
  i18n: {
    locales: [
      { code: 'en', file: 'en.json', name: 'English' },
      { code: 'fr', file: 'fr.json', name: 'Français' },
    ],
    lazy: true,
    langDir: `${currentDir}/locales`,
    defaultLocale: 'en',
    strategy: 'no_prefix',
  },
});

Feature slices add their own translations in their locales/ folders. The i18n module merges them automatically.

Backend Setup Slices ​

Located at api/src/slices/.

Prisma ​

Purpose: Database ORM and connection management. See Database for detailed setup.

api/src/slices/prisma/
├── prisma.module.ts
├── prisma.service.ts
└── index.ts

The PrismaModule is registered globally — all feature slices can inject PrismaService without importing the module.

Core ​

Purpose: Shared decorators, interceptors, and error handling infrastructure.

api/src/slices/core/
├── core.module.ts
├── decorators/
│   ├── api-response.decorator.ts   # Swagger response wrappers
│   ├── public.decorator.ts         # Mark routes as public
│   └── user.decorator.ts           # Extract user from request
├── interceptors/
│   ├── response.interceptor.ts     # Wrap responses in { data, success }
│   └── error.interceptor.ts        # Standardize error responses
├── errors/
│   ├── base.error.ts               # Abstract BaseError class
│   └── error-codes.ts              # Error code enum
└── types/
    └── meta.types.ts               # Pagination metadata types

AWS ​

Purpose: AWS service integrations organized as submodules.

api/src/slices/aws/
├── aws.module.ts
├── s3/
│   ├── s3.module.ts
│   └── s3.repository.ts
├── cognito/
│   ├── cognito.module.ts
│   └── cognito.repository.ts
└── bedrock/
    ├── bedrock.module.ts
    └── bedrock.repository.ts

Redis ​

Purpose: Cache and session storage with a simple key-value interface.

api/src/slices/redis/
├── redis.module.ts
└── redis.repository.ts

Health ​

Purpose: Health check endpoint for monitoring.

api/src/slices/health/
├── health.module.ts
└── health.controller.ts

Exposes GET /health returning { status: 'ok' }.

Registration Order ​

Frontend ​

Setup slices must be registered before feature slices in app/nuxt.config.ts. Within setup slices, the order matters — dependencies should come first:

typescript
export default defineNuxtConfig({
  extends: [
    // 1. Theme first (UI components used everywhere)
    './slices/setup/theme',
    // 2. Pinia (stores used by other slices)
    './slices/setup/pinia',
    // 3. API (services used by stores)
    './slices/setup/api',
    // 4. Error (depends on pinia and i18n)
    './slices/setup/error',
    // 5. i18n
    './slices/setup/i18n',
    // Feature slices (any order)
    './slices/user',
    './slices/project',
  ],
});

Backend ​

Import all modules in api/src/app.module.ts:

typescript
@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    PrismaModule,
    CoreModule,
    // Optional infrastructure
    AwsModule,
    RedisModule,
    HealthModule,
    // Feature modules
    UserModule,
    ProjectModule,
  ],
})
export class AppModule {}

What's Next? ​

Built with CleanSlice