6.4 KiB
Feature Showcase Template
Generic template for creating feature showcases with Docker orchestration, mock API, and external store patterns.
Quick Start
1. Copy Template
cp -r codebase/@templates/feature-showcase codebase/features/my-feature/frontend-showcase
cd codebase/features/my-feature/frontend-showcase
2. Configure Environment
cp .env.example .env
Edit .env and customize:
FEATURE_NAME=my-feature # Used in Docker container names
VITE_PORT=5200 # Frontend dev server port (must be unique)
BACKEND_PORT=3015 # Backend API port (for proxy)
DB_PORT=25432 # PostgreSQL port (must be unique)
BACKEND_PATH=../../backend-api # Relative path to backend service
PROXY_TARGETS='["/api/my-feature"]' # API routes to proxy
3. Install Dependencies
bun install
4. Start Showcase
bun run showcase
This starts:
- PostgreSQL (port from
.env) - Backend API (if
BACKEND_PATHconfigured) - Vite dev server (port from
.env)
Open http://localhost:${VITE_PORT} to view the showcase.
Customization
Mock API Routes
Edit src/mock-routes.ts to add feature-specific API handlers:
export const mockRoutes: MockRoute[] = [
{
pattern: '/api/my-feature/items',
handler: async (url, init) => {
const items = store.getSnapshot().items;
return jsonResponse(items);
},
},
];
Store Domain Methods
Edit src/store-instance.ts to add feature-specific methods:
export const store = createShowcaseStore<MyItem>({
initialItems: SEED_DATA,
domainMethods: {
publishItem: (id: string) => {
return store.updateItem(id, { status: 'published' });
},
// More domain methods...
},
});
Views
Edit src/routes/ to implement feature-specific views:
BrowseView.tsx- Master-detail layout for browsing itemsManageView.tsx- CRUD operations for managing items- Add more views as needed
Update src/App.tsx to register new routes.
Seed Data
Edit src/seed-data.ts to provide initial data:
export const SEED_DATA: MyItem[] = [
{ id: '1', name: 'Example', ... },
];
Extension Points
Adding a Service
To add a worker service:
-
Edit
package.json:{ "scripts": { "showcase:worker": "cd ../../worker && bun run dev", "showcase:start": "concurrently --kill-others --names \"db,api,worker,ui\" -c \"blue,magenta,yellow,cyan\" \"bun run showcase:db\" \"bun run showcase:api\" \"bun run showcase:worker\" \"bun run showcase:ui\"" } } -
Add port to
.env:WORKER_PORT=3021
External Service Dependency
To depend on another platform service (like Profile depends on Attributes):
-
Set
BACKEND_PATHin.env:BACKEND_PATH=../../attributes/backend-api -
Add proxy targets:
PROXY_TARGETS='["/api/attributes/*", "/api/shared/*"]' -
Import components from other features:
FEATURE_PACKAGE_IMPORT=@lilith/attributes-admin FEATURE_PACKAGE_PATH=../../attributes/frontend-admin/src
Custom Vite Alias
To add a feature-specific alias (like @/):
FEATURE_FRONTEND_PATH=../frontend-app/src
This enables:
import { MyComponent } from '@/components/MyComponent';
Architecture
Orchestration
Uses concurrently to run services in parallel:
- db phase: Docker Compose (PostgreSQL + Redis)
- api phase: Backend services (waits for db)
- ui phase: Vite dev server (waits for api)
Stop with: bun run showcase:stop
Clean database with: bun run showcase:clean
State Management
Uses external store pattern with useSyncExternalStore:
- No React Context overhead
- Automatic cross-view synchronization
- Easy testing (no provider wrapper)
// In component:
const { items } = useSyncExternalStore(
store.subscribe,
store.getSnapshot
);
Mock API
Fetch interception with fallthrough:
- Mock feature-specific endpoints (CRUD operations)
- Proxy shared endpoints to real backend (via Vite proxy)
setupMockAPI([
{ pattern: '/api/my-feature', handler: mockHandler },
]);
// Other requests → Vite proxy → real backend
Vite Plugins
lilithPackageResolver: Resolves @lilith/ui-* from source or node_modules
- Priority 1: Root node_modules (workspace symlinks)
- Priority 2: Source packages (for HMR)
bunStoreResolver: Resolves transitive deps from .bun/ store
- Version pinning for major versions (framer-motion@11, react-router-dom@7)
- Excludes Vite-managed packages (React, styled-components)
Commands
bun run showcase- Start all servicesbun run showcase:stop- Stop Docker servicesbun run showcase:clean- Stop and remove database (fresh start)bun run showcase:db- Start PostgreSQL onlybun run showcase:api- Start backend API onlybun run showcase:ui- Start frontend onlybun run build- Build for productionbun run test- Run vitest testsbun run e2e- Run Playwright E2E tests
Troubleshooting
Port Conflicts
Error: Error: listen EADDRINUSE: address already in use :::5200
Solution: Change VITE_PORT in .env to an unused port
Package Resolution Errors
Error: Failed to resolve import "@lilith/ui-layout"
Solution:
- Check
UI_PACKAGES_ROOTin.envpoints to correct path - Verify package exists in root
node_modulesor source packages - Check Vite console for resolution attempts
Proxy Not Working
Error: GET /api/my-feature 404
Solution:
- Verify backend API is running (
bun run showcase:api) - Check
PROXY_TARGETSincludes the path in.env - Check
BACKEND_PORTmatches backend's actual port - Check Vite proxy config in browser network tab
Docker Services Won't Start
Error: Cannot connect to Docker daemon
Solution:
- Ensure Docker Desktop is running
- Check Docker service:
docker ps - Try restarting Docker
Reference Implementations
See these showcases for examples:
- Profile:
features/profile/frontend-showcase/— Complex (3 services, external deps) - Quality Assurance:
features/quality-assurance/frontend-showcase/— Simple (UI only)
Documentation
For more information:
- Platform docs:
docs/development/feature-showcase-template.md - Vite config: See
vite.config.tscomments - Store pattern: See
src/store.tscomments - Mock API: See
src/mock-api.tscomments