Skip to content

Modules (Frontend)

Overview

Frontend feature modules live in resources/js/modules/. Each module encapsulates a complete feature with its own components, store, services, API layer, and types — following the stores→services→api pattern.


Folder Structure

modules/landing/
├── setup/                     # Feature: Setup wizard
│   └── form/
│       ├── Index.svelte       # Entry point — minimal, pure composition
│       ├── api/               # API fetch functions
│       ├── parts/             # Sub-components (atomic design)
│       ├── services/          # Business logic
│       ├── stores/            # State management
│       │   └── entry/         # Store groups with barrel index.ts
│       ├── types/             # TypeScript interfaces
│       └── __tests__/         # Vitest tests
├── schools/                   # Feature: School profiles
├── recruitment/               # Feature: Career portal
├── articles/                  # Feature: News & articles
└── commons/                   # Shared UI patterns
    ├── dropdown/              # Reusable dropdowns
    ├── language-switch/       # Language switcher
    └── chatbot/               # Chatbot widget

The stores→services→api Pattern

Every data flow follows this strict chain:

Component (Svelte)
    ↓ subscribe() + call action
Store (state management)
    ↓ delegate business logic
Service (orchestration)
    ↓ HTTP calls
API (fetch)
    ↓ network
Backend (Laravel)

Layer Responsibilities

LayerResponsibilityExample
ComponentRender UI, call store actions, subscribe to stateIndex.svelte
StoreManage StateContainer<TData>, expose getters/actionssuper-user-form.stores.ts
ServiceOrchestrate API calls, transform dataotp.services.ts
APIPure HTTP fetch, typed responsesotp.api.ts

Rules

  • Never skip layers — component calls store, not service/API directly
  • Store calls service, not API directly
  • Service calls API, not fetch directly (SSE is the only exception)

Store Pattern

Every store uses StateContainer<TData> from @/types/state:

typescript
interface StateContainer<TData> {
    meta: StateMeta;       // loading, initialized, updatedAt, errorAt
    data: TData;           // domain data
    errors: StateErrors;   // validation errors
}

Store File Naming

<action>-<module>.stores.ts

Examples: fetch-bulletin.stores.ts, super-user-form.stores.ts, otp-form.stores.ts

Store Groups

Related stores are grouped in subdirectories with barrel index.ts:

stores/super-user-entry/
├── super-user-form.stores.ts
├── super-user-form-validation.stores.ts
└── index.ts          // re-exports all

Creating a New Module

bash
mkdir resources/js/modules/landing/{feature}/
mkdir resources/js/modules/landing/{feature}/api
mkdir resources/js/modules/landing/{feature}/parts
mkdir resources/js/modules/landing/{feature}/services
mkdir resources/js/modules/landing/{feature}/stores
mkdir resources/js/modules/landing/{feature}/types
mkdir resources/js/modules/landing/{feature}/__tests__

Then create:

  1. types/{module}.types.ts — Define data interfaces
  2. api/{module}.api.ts — API fetch functions
  3. services/{module}.service.ts — Business logic
  4. stores/{module}.stores.ts — State management (StateContainer)
  5. parts/*.svelte — Sub-components
  6. Index.svelte — Entry point

Key Files

FilePurpose
resources/js/lib/state.tsStateContainer<TData> type definition
resources/js/lib/i18n.svelte.tst() function for translations
resources/js/modules/All feature modules
resources/js/components/landing/Atomic design components