Constants & Configuration Pattern
SkillDev toolsCentralize all configuration constants — environment variables, cache keys — in the constants/ directory with strict naming and export conventions
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Constants & Configuration Pattern skill
What this skill tells your AI
The instructions your AI receives, as published by cliqrelay/cliqrelay in .agents/skills/frontend/constants-configuration-pattern/SKILL.md and read by ahel’s review.
All configuration and constant values are centralized in constants/, organized by concern. No hardcoded strings in service or component files.
Key Change: API Endpoints No Longer Manual
With @repo/api-client, API endpoint URLs are no longer defined manually. The auto-generated SDK handles all URL construction using import.meta.env.VITE_API_URL (set via @t3-oss/env-core). See env.ts below.
For domains not covered by @repo/api-client, API endpoints can still be defined — see the legacy pattern at the end of this document.
Folder Structure
constants/
├── env.ts ← Environment variables (required)
├── query-keys.ts ← Cache keys (when using manual TanStack React Query)
└── index.ts ← Optional re-exports
Environment Config (constants/env.ts)
Use @t3-oss/env-core with Zod schemas for validated, typed environment variables. Choose the example that matches your framework.
Vite / TanStack Start
Uses import.meta.env with VITE_ prefix:
// constants/env.ts
import { createEnv } from "@t3-oss/env-core";
import { z } from "zod";
export const env = createEnv({
server: {
DATABASE_URL: z.string().nonempty(),
API_SECRET: z.string().nonempty()
},
clientPrefix: "VITE_",
client: {
VITE_API_URL: z.string().nonempty().url(),
VITE_BASE_URL: z.string().nonempty().url(),
VITE_APP_NAME: z.string().nonempty(),
VITE_APP_VERSION: z.string().nonempty()
},
runtimeEnv: import.meta.env,
emptyStringAsUndefined: true
});
Note:
VITE_API_URLis consumed by@repo/api-client(Orval config readsimport.meta.env.VITE_API_URL). No manual URL construction needed.
✅ DO — Use createEnv with Zod for validated env vars
✅ DO — Separate server and client blocks
✅ DO — Set emptyStringAsUndefined: true
✅ DO — Use VITE_ prefix for client variables
❌ DON'T — Access raw env vars directly in service/hook files
// ❌ DON'T — Raw access
const apiUrl = import.meta.env.VITE_API_URL;
// ✅ DO — Always import from ./env
import { env } from "[project-root]/constants/env";
const apiUrl = env.VITE_API_URL;
If Using Manual TanStack React Query (Non-api-client Domains)
Query keys go in constants/query-keys.ts. QueryClient setup and cache utilities belong in lib/query-client.ts — see the React Query Cache Utilities skill.
Legacy Pattern: Manual API Endpoints (Non-api-client Domains)
For domains not covered by @repo/api-client, define API endpoints manually:
// constants/api-endpoints.ts
import { env } from "./env";
const API_ENDPOINTS = {
metadata: {
app: `${env.VITE_API_URL}/app_metadata`
},
auth: {
createAccount: `${env.VITE_API_URL}/auth/create_account`
},
users: {
getMe: `${env.VITE_API_URL}/users/me`,
},
} as const;
export default API_ENDPOINTS;
✅ DO — Legacy endpoint conventions
API_ENDPOINTSusesas constfor type safety- Template literals for URL construction:
`${env.VITE_API_URL}/path` - Only define endpoints for APIs not covered by
@repo/api-client
❌ DON'T — Duplicate what api-client already provides
// ❌ DON'T — @repo/api-client already defines these URLs
const API_ENDPOINTS = {
guides: {
create: `${env.VITE_API_URL}/guides`,
getAll: `${env.VITE_API_URL}/guides`,
}
} as const;
Rules
✅ DO
- Use
createEnvfrom@t3-oss/env-corewith Zod for env validation - Separate
serverandclientenv vars - Set
emptyStringAsUndefined: true - Match
clientPrefixto your framework's convention - Access env through
envexport, never directly from env globals - Let
@repo/api-clienthandle all API URL construction for covered domains - Only define manual API endpoints for domains NOT covered by
@repo/api-client - Query keys are enum members, not string literals
- One config concern per file
❌ DON'T
- Don't manually define API endpoints for domains covered by
@repo/api-client - Don't access raw env vars in service, hook, or component files
- Don't mix config concerns in the same file
- Don't skip Zod validation on environment variables
Signals
- GitHub stars
- 40
- Forks
- 1
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
constants-configuration-pattern- Source
- github.com/cliqrelay/cliqrelay