Getting Started
This guide walks you through setting up a Loom Loyalty Hub instance for your organization.
Prerequisites
- Node.js 20+
- pnpm 9+
- A Loom Loyalty API account
- A Cloudflare account (for deployment)
- A WorkOS account (for authentication)
Installation
1. Clone the Repository
git clone https://github.com/loom-loyalty/loom-loyalty.git
cd loom-loyalty
pnpm install
2. Configure Environment Variables
Create a .env file in apps/hub/:
# API Configuration
VITE_API_BASE_URL=https://api.loomloyalty.com
# WorkOS Authentication (optional for development)
VITE_WORKOS_CLIENT_ID=your_client_id
# Development Mode
VITE_USE_REAL_API=false # Use mock data for development
3. Start Development Server
pnpm --filter @loom-loyalty/hub dev
The Hub will be available at http://localhost:3001.
Project Structure
apps/hub/
├── src/
│ ├── routes/ # TanStack Router file-based routes
│ │ ├── index.tsx # Dashboard
│ │ ├── customers.tsx # Customer management
│ │ ├── settings.tsx # Settings page
│ │ └── programs/ # Programs and sub-entities
│ ├── providers/ # React context providers
│ │ ├── config-provider.tsx
│ │ ├── auth-provider.tsx
│ │ └── sdk-provider.tsx
│ ├── hooks/ # Custom React hooks
│ │ ├── use-entity-data.ts
│ │ └── use-entity-schema.ts
│ └── lib/ # Utilities and data layer
│ └── data/
│ └── entity-hooks.ts
├── worker/ # Cloudflare Worker entry point
│ └── index.ts # Static assets and /api/ai/* proxy
├── public/ # Static assets
└── wrangler.jsonc # Worker routes, assets, and AI_URL
Understanding the Data Flow
1. Configuration Loading
The client resolves the organization from the first hostname label, then fetches
its environment-scoped Hub configuration from the Platform API's /hub-configs
endpoint. The Worker does not read KV or serve /__config.js.
2. Provider Setup
The Hub wraps your application with providers:
// Simplified provider hierarchy
<ConfigProvider>
<AuthProvider>
<SDKProvider>
<BrandingProvider>
<QueryClientProvider>
<RouterProvider router={router} />
</QueryClientProvider>
</BrandingProvider>
</SDKProvider>
</AuthProvider>
</ConfigProvider>
3. Entity Data Hooks
Entity data is fetched using typed hooks:
import { useEntityList, useEntityRecord } from "@/hooks/use-entity-data";
// Fetch list of customers
const { data, isLoading } = useEntityList("customer", {
pagination: { page: 0, pageSize: 20 },
});
// Fetch single tier
const { data: tier } = useEntityRecord("tier", tierId);
Development Workflow
Using Mock Data
For development without a backend, the Hub provides mock data:
- Set
VITE_USE_REAL_API=falsein your.env - Mock data is returned from the entity hooks
- No authentication is required
Using Real API
To develop against the real API:
- Set
VITE_USE_REAL_API=true - Configure your API credentials
- Authentication will be required
Running Tests
# Unit tests
pnpm --filter @loom-loyalty/hub test
# E2E tests
pnpm --filter @loom-loyalty/hub test:e2e
# E2E tests with UI
pnpm --filter @loom-loyalty/hub test:e2e:ui