wcz-layout
Version:
182 lines (133 loc) • 5.22 kB
Markdown
name: project-initialization
description: >
Scaffold a new wcz-layout project from the template. Covers placeholder
replacement across three naming conventions (kebab-case, Title Case,
snake_case), .env and .env.local configuration, VITE_ENTRA_CLIENT_ID,
VITE_APP_TITLE, VITE_MUI_LICENSE_KEY, favicon generation via favicon.io,
and viteWczLayout() Vite plugin registration. Activate when starting a
new internal project or configuring environment variables.
type: lifecycle
library: wcz-layout
library_version: "7.6.1"
sources:
- "wcz-layout:src/env.ts"
- "wcz-layout:src/lib/vite-plugin.ts"
- "wcz-layout:vite.config.ts"
- "wcz-layout:.env"
# Project Initialization
## Setup
After cloning the template repository, initialize the project in this order:
### 1. Replace all template placeholders
Use your editor's replace-all (across all files) for each naming convention:
| Find | Replace with | Used in |
| -------------- | ------------ | ------------------------------------------------ |
| `project-name` | `app-store` | package.json name, URLs, CSS classes |
| `Project Name` | `App Store` | VITE_APP_TITLE, display strings, docs |
| `my_app` | `app_store` | Database names, env vars, snake_case identifiers |
### 2. Configure environment variables
```sh
# .env — committed to repo, shared across team
VITE_ENTRA_CLIENT_ID=your-entra-client-id
VITE_ENTRA_TENANT_ID=your-tenant-id
VITE_APP_TITLE=App Store
VITE_MUI_LICENSE_KEY=your-mui-license-key
```
Create `.env.local` (gitignored) for local secret overrides:
```sh
# .env.local — never committed
VITE_ENTRA_CLIENT_ID=your-dev-client-id
ENTRA_CLIENT_ID=your-server-client-id
ENTRA_TENANT_ID=your-server-tenant-id
ENTRA_CLIENT_SECRET=your-client-secret
```
### 3. Generate favicon
Go to https://favicon.io/favicon-converter/, upload your logo, and place the generated files in `public/`.
### 4. Verify Vite plugin registration
```typescript
// vite.config.ts
import { viteWczLayout } from "wcz-layout/vite";
export default defineConfig({
plugins: [
tanstackStart(),
nitro(),
viteReact(),
babel(reactCompilerPreset()),
checker({ typescript: true }),
viteWczLayout(),
],
});
```
## Core Patterns
### Environment validation with createEnv
```typescript
// src/env.ts
import { createEnv } from "wcz-layout/utils";
import { z } from "zod";
export const clientEnv = createEnv({
clientPrefix: "VITE_",
client: {
VITE_ENTRA_CLIENT_ID: z.string(),
VITE_ENTRA_TENANT_ID: z.string(),
VITE_APP_TITLE: z.string(),
VITE_MUI_LICENSE_KEY: z.string(),
},
runtimeEnv: import.meta.env,
emptyStringAsUndefined: true,
});
export const serverEnv = createEnv({
server: {
ENTRA_CLIENT_ID: z.string(),
ENTRA_TENANT_ID: z.string(),
ENTRA_CLIENT_SECRET: z.string(),
},
runtimeEnv: process.env,
emptyStringAsUndefined: true,
});
```
### Vault secrets for local development
The `viteWczLayout()` plugin automatically loads secrets from HashiCorp Vault during `vite dev` if `VAULT_ADDRESS`, `VAULT_USERNAME`, `VAULT_PASSWORD`, and `VAULT_SECRET_PATH` are set in `.env`. Vault-loaded secrets only populate `process.env` keys that are not already set.
## Common Mistakes
### CRITICAL Missing viteWczLayout() in Vite config
Wrong:
```typescript
// vite.config.ts
export default defineConfig({
plugins: [tanstackStart(), viteReact()],
});
```
Correct:
```typescript
// vite.config.ts
import { viteWczLayout } from "wcz-layout/vite";
export default defineConfig({
plugins: [tanstackStart(), viteReact(), viteWczLayout()],
});
```
Without `viteWczLayout()`, the `virtual:wcz-layout` module won't resolve, breaking i18n resources, permissions, and scopes at build time.
Source: wcz-layout:src/lib/vite-plugin.ts
### HIGH Forgetting .env.local for local secrets
`.env` is committed to the repo and shared across the team. Local overrides (Entra client IDs, secrets) must go in `.env.local` which is gitignored. Committing secrets to `.env` exposes them in the repository.
Source: maintainer interview
### HIGH Not replacing all naming conventions
The template uses three naming conventions. Use replace-all across the entire project for each one. Missing any convention leaves stale references in package.json, env files, or source imports.
Source: maintainer interview
### MEDIUM Empty string env vars pass silently
Wrong:
```sh
# .env
VITE_APP_TITLE=
```
Correct:
```sh
# .env
VITE_APP_TITLE=My Application
```
`createEnv` uses `emptyStringAsUndefined: true`, so empty strings become `undefined` and fail Zod validation at runtime, not build time.
Source: wcz-layout:src/env.ts
### HIGH Tension: Simplicity vs. full-stack rigor
This skill's simple setup conflicts with production readiness from api-routes. Agents scaffolding a quick prototype may skip authorizationMiddleware and validationMiddleware, producing code that works locally but is insecure in production. Always include middleware from the start.
See also: skills/api-routes/SKILL.md § Common Mistakes
See also: skills/project-structure/SKILL.md — After init, understand where to place new code.