Project Structure
Folder Tree
dtx-portal/
├── apps/
│ └── portal/ # Main React 19 application
│ ├── src/
│ │ ├── components/ # Feature & shared components
│ │ │ ├── access-management/ # User/role/group management
│ │ │ ├── approval-workflow/ # Workflow designer & task inbox
│ │ │ ├── cache-management/ # Redis/Dragonfly cache UI
│ │ │ ├── kafka-management/ # Kafka topic management
│ │ │ ├── observability-dashboard/ # Metrics, health, alerts
│ │ │ ├── pipelines/ # Pipeline list/management
│ │ │ ├── schema-registry/ # Schema CRUD, versioning
│ │ │ ├── synthetic-data/ # SDG generators, universes, pools
│ │ │ └── shared/ # Cross-feature reusable components
│ │ │ ├── designer/ # XYFlow pipeline/connector designer
│ │ │ ├── form-renderer/ # Dynamic JSON-schema forms
│ │ │ ├── header/ # Top navigation + search
│ │ │ ├── layout/ # Main app layout wrapper
│ │ │ ├── operator-config/ # Multi-stage operator config
│ │ │ └── sidebar/ # Sidebar navigation
│ │ ├── config/ # env.ts, sql-operator-rules.ts
│ │ ├── constants/ # navigation.ts
│ │ ├── hooks/ # 13 custom React hooks
│ │ ├── lib/ # fetchWithAuth, apiResponse, uuid
│ │ ├── pages/ # Route page components
│ │ ├── providers/ # AuthProvider (Keycloak)
│ │ ├── router/ # React Router v7 config
│ │ ├── services/ # API client services
│ │ ├── stores/ # Zustand state stores
│ │ ├── styles/ # Tailwind CSS (theme, typography)
│ │ ├── test/ # Test setup
│ │ └── types/ # TypeScript type definitions (14 files)
│ ├── public/assets/images/ # Static assets (operator SVGs, logo)
│ ├── .env.local / .env.dev / .env.test / .env.production
│ ├── vite.config.ts
│ └── vitest.config.ts
├── packages/
│ ├── ui/ # @dtx/ui — Shared component library
│ │ └── src/
│ │ ├── components/
│ │ │ ├── base/ # Buttons, inputs, badges, cards
│ │ │ ├── application/ # Tables, modals, tabs, charts
│ │ │ ├── foundations/ # Icons, logos, rating
│ │ │ └── shared-assets/ # QR codes, illustrations
│ │ ├── hooks/ # UI hooks (resize, clipboard)
│ │ ├── icons/ # @untitledui/icons re-exports
│ │ └── utils/ # cx(), toast utils
│ └── utils/ # @dtx/utils — Shared utilities
│ └── src/index.ts # cx(), formatBytes(), debounce()
├── scripts/ # SQL & migration scripts
├── Dockerfile # Multi-stage build (Node + Nginx)
├── nginx.conf # Reverse proxy config
├── deploy-dev.sh / deploy-test.sh # Deployment scripts
├── pnpm-workspace.yaml # Workspace + dependency catalog
└── package.json
Organization Pattern
The project uses a hybrid folder strategy:
Feature Folder Example: Synthetic Data
components/synthetic-data/
├── CreateGeneratorWizard.tsx # Main wizard
├── GeneratorsListPage.tsx # List view
├── StatusBadge.tsx # Status indicator
├── steps/ # Wizard steps
│ ├── BasicInfoStep.tsx
│ ├── SchemaConfigStep.tsx
│ ├── DestinationConfigStep.tsx
│ ├── GenerationConfigStep.tsx
│ └── ReviewStep.tsx
├── destination-forms/ # Per-destination forms
│ ├── KafkaDestinationForm.tsx
│ ├── PostgresDestinationForm.tsx
│ └── ...
├── detail-tabs/ # Detail view tabs
│ ├── OverviewTab.tsx
│ ├── StatisticsTab.tsx
│ └── LiveMetricsPanel.tsx
├── field-mapping/ # Field mapping UI
└── common/ # Feature-local shared
├── ThroughputChart.tsx
└── MetricsCard.tsx
Naming Conventions
| Entity | Convention | Example |
|---|---|---|
| Components | PascalCase | CreateGeneratorWizard.tsx |
| Pages | PascalCase + Page suffix | UsersPage.tsx |
| Hooks | camelCase + use prefix | useSyntheticData.ts |
| Services | camelCase + .service.ts | pipeline.service.ts |
| API files | camelCase + Api suffix | kafkaApi.ts |
| Types | camelCase + .types.ts | synthetic-data.types.ts |
| Stores | camelCase + use + Store | usePipelineStore.ts |
| CSS files | kebab-case | theme.css |
| Folders | kebab-case | schema-registry/ |
Import Aliases
| Alias | Resolves To | Example |
|---|---|---|
@/ | apps/portal/src/ | import { usePipelineStore } from '@/stores/usePipelineStore' |
@dtx/ui | packages/ui/src | import { Button, Badge } from '@dtx/ui' |
@dtx/utils | packages/utils/src | import { cx } from '@dtx/utils' |
Configured in both vite.config.ts (for bundling) and tsconfig.json (for IDE support).
Build Configuration
Vite (apps/portal/vite.config.ts)
- Plugins:
@vitejs/plugin-react,@tailwindcss/vite - Dev proxy:
/apitolocalhost:8080,/sdg-apito SDG service - Code splitting:
| Chunk | Contents |
|---|---|
react-vendor | react, react-dom, react-router-dom |
query-vendor | @tanstack/react-query |
monaco | Monaco Editor |
d3 | D3.js |
react-flow | @xyflow/react |
TypeScript (apps/portal/tsconfig.json)
- Target: ES2020
- Strict mode: Enabled (
strict,noUnusedLocals,noUnusedParameters,noUncheckedIndexedAccess) - Module: ESNext with bundler resolution
- JSX: react-jsx
Environment Configuration
All variables use the VITE_ prefix and are accessed via import.meta.env. A centralized env.ts config object provides typed access.
| Category | Variables |
|---|---|
| App | VITE_APP_NAME, VITE_APP_VERSION, VITE_APP_DESCRIPTION |
| API | VITE_API_BASE_URL, VITE_API_TIMEOUT |
| Auth | VITE_AUTH_ENABLED, VITE_KEYCLOAK_URL, VITE_KEYCLOAK_REALM, VITE_KEYCLOAK_CLIENT_ID |
| Features | VITE_FEATURE_OBSERVABILITY, VITE_FEATURE_WORKFLOWS, VITE_FEATURE_SCHEMA_REGISTRY, VITE_FEATURE_CONNECTORS |
| Services | VITE_PIPELINE_API_URL, VITE_OPERATOR_API_URL, VITE_SCHEMA_REGISTRY_API_URL, VITE_SYNTHETIC_DATA_API_URL, VITE_KAFKA_API_URL, VITE_CACHE_API_URL, VITE_EXPRESSIONS_API_URL, VITE_OBSERVABILITY_API_URL |
| Branding | VITE_BRAND_NAME, VITE_BRAND_LOGO |
| User | VITE_DEFAULT_USER_NAME, VITE_DEFAULT_USER_EMAIL, VITE_DEFAULT_USER_AVATAR |
| Monitoring | VITE_SENTRY_DSN, VITE_SENTRY_ENVIRONMENT |
| Dev | VITE_DEV_TOOLS_ENABLED, VITE_DEBUG_MODE |
Environment Files
| File | Purpose |
|---|---|
.env.local | Local development |
.env.dev | DEV deployment |
.env.test | TEST deployment |
.env.production | Production deployment |