env-config
Setup environment configuration with type-safe validation and local development defaults. Use this skill when the user says "setup env", "configure environment", "env vars", or "environment setup".
What this skill does
# Environment Configuration Setup
Creates a type-safe environment configuration system using `@t3-oss/env-nextjs` with Zod validation, plus a `.env.local` template for local development.
## Installation
```bash
bun add @t3-oss/env-nextjs zod
```
## What Gets Created
### `env.ts` or `src/env.ts`
Create this file with type-safe environment variable validation:
- **With src directory** (Next.js with `--src-dir`): `src/env.ts`
- **Without src directory** (Next.js with `--no-src-dir`): `env.ts` in project root
Check your project structure first:
```bash
# If you have a src directory, use src/env.ts
ls src/ 2>/dev/null && echo "Use src/env.ts" || echo "Use env.ts"
```
```typescript
import { createEnv } from "@t3-oss/env-nextjs";
import { z } from "zod";
export const env = createEnv({
server: {
// --- Core (always required) ---
DATABASE_URL: z.string().url(),
BETTER_AUTH_SECRET: z.string().min(1),
// --- Infrastructure (optional — add based on project needs) ---
REDIS_URL: z.string().url().optional(),
S3_ENDPOINT: z.string().url().optional(),
S3_ACCESS_KEY: z.string().optional(),
S3_SECRET_KEY: z.string().optional(),
S3_REGION: z.string().default("us-east-1"),
S3_BUCKET: z.string().optional(),
BLOB_READ_WRITE_TOKEN: z.string().optional(),
SMTP_HOST: z.string().optional(),
SMTP_PORT: z.string().optional(),
RESEND_API_KEY: z.string().optional(),
MEILI_URL: z.string().url().optional(),
MEILI_MASTER_KEY: z.string().optional(),
// --- Payments (optional — add if using Stripe) ---
STRIPE_SECRET_KEY: z.string().optional(),
STRIPE_WEBHOOK_SECRET: z.string().optional(),
// --- AI Services (optional — add based on providers used) ---
OPENAI_API_KEY: z.string().optional(),
FAL_KEY: z.string().optional(),
REPLICATE_API_TOKEN: z.string().optional(),
AI_GATEWAY_API_KEY: z.string().optional(),
AI_GATEWAY_MODEL: z.string().default("google/gemini-2.5-flash-lite"),
EXA_API_KEY: z.string().optional(),
// --- Queue (optional — Inngest defaults for local dev) ---
INNGEST_EVENT_KEY: z.string().default("local"),
INNGEST_SIGNING_KEY: z.string().default("local"),
},
client: {
NEXT_PUBLIC_APP_URL: z.string().url(),
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY: z.string().optional(),
},
runtimeEnv: {
DATABASE_URL: process.env.DATABASE_URL,
BETTER_AUTH_SECRET: process.env.BETTER_AUTH_SECRET,
REDIS_URL: process.env.REDIS_URL,
S3_ENDPOINT: process.env.S3_ENDPOINT,
S3_ACCESS_KEY: process.env.S3_ACCESS_KEY,
S3_SECRET_KEY: process.env.S3_SECRET_KEY,
S3_REGION: process.env.S3_REGION,
S3_BUCKET: process.env.S3_BUCKET,
BLOB_READ_WRITE_TOKEN: process.env.BLOB_READ_WRITE_TOKEN,
SMTP_HOST: process.env.SMTP_HOST,
SMTP_PORT: process.env.SMTP_PORT,
RESEND_API_KEY: process.env.RESEND_API_KEY,
MEILI_URL: process.env.MEILI_URL,
MEILI_MASTER_KEY: process.env.MEILI_MASTER_KEY,
STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
STRIPE_WEBHOOK_SECRET: process.env.STRIPE_WEBHOOK_SECRET,
OPENAI_API_KEY: process.env.OPENAI_API_KEY,
FAL_KEY: process.env.FAL_KEY,
REPLICATE_API_TOKEN: process.env.REPLICATE_API_TOKEN,
AI_GATEWAY_API_KEY: process.env.AI_GATEWAY_API_KEY,
AI_GATEWAY_MODEL: process.env.AI_GATEWAY_MODEL,
EXA_API_KEY: process.env.EXA_API_KEY,
INNGEST_EVENT_KEY: process.env.INNGEST_EVENT_KEY,
INNGEST_SIGNING_KEY: process.env.INNGEST_SIGNING_KEY,
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY:
process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY,
},
});
```
**Features:**
- Type-safe environment variable validation at build time
- Separates server-only and client-safe variables
- Descriptive error messages for missing variables
- Works with local Docker stack by default
- Supports production services (Neon, Upstash, Vercel Blob, Resend, etc.)
### `.env.local.example` (canonical reference)
Local development defaults pre-configured for Docker services.
**This file is the source of truth** — the reconciliation step above uses it to fill gaps in `.env.local`.
```env
# --- Core (always required) ---
DATABASE_URL=postgresql://app:password@localhost:5432/appdb
BETTER_AUTH_SECRET=dev-secret-change-in-production
# Application
NEXT_PUBLIC_APP_URL=http://localhost:3000
# --- Infrastructure (uncomment as needed) ---
REDIS_URL=redis://localhost:6379
# Storage (S3-compatible local)
S3_ENDPOINT=http://localhost:9000
S3_ACCESS_KEY=rustfsadmin
S3_SECRET_KEY=rustfsadmin
S3_BUCKET=uploads
# Email (Mailpit local)
SMTP_HOST=localhost
SMTP_PORT=1025
# Search (Meilisearch)
MEILI_URL=http://localhost:7700
MEILI_MASTER_KEY=devMasterKey123
# --- Payments (optional — add if using Stripe) ---
# STRIPE_SECRET_KEY=sk_test_...
# STRIPE_WEBHOOK_SECRET=whsec_test_...
# NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...
# --- AI Services (load from 1Password in production) ---
# OPENAI_API_KEY=sk-...
# FAL_KEY=
# REPLICATE_API_TOKEN=
# AI_GATEWAY_API_KEY=
# EXA_API_KEY=
```
## What This Does
1. Creates `env.ts` (or `src/env.ts` if using src directory) with validated environment variables
2. Creates `.env.local.example` as the canonical reference for all env vars with defaults
3. **Reconciles `.env.local`** — appends any missing keys from `.env.local.example` (preserves existing values like 1Password secrets)
4. All services point to Docker stack by default
5. Provides clear error messages for missing required vars
6. Enables type-safe `import { env } from "@/env"` throughout the app (works with both `--src-dir` and `--no-src-dir` via tsconfig paths)
## Reconcile `.env.local` (CRITICAL)
**This step prevents missing env var errors in CI and local dev.**
After creating `env.ts` and `.env.local.example`, run this reconciliation:
```bash
# If .env.local exists (e.g., from 1Password dump), append missing keys from .env.local.example.
# If .env.local doesn't exist, copy the example as the starting point.
if [[ -f .env.local ]]; then
echo "Reconciling .env.local against .env.local.example..."
ADDED=0
while IFS= read -r line; do
# Skip comments and empty lines
[[ "$line" =~ ^#.*$ || -z "$line" ]] && continue
# Skip commented-out vars (lines starting with "# KEY=")
[[ "$line" =~ ^[[:space:]]*# ]] && continue
# Extract key name (everything before first =)
KEY="${line%%=*}"
# Append if key is missing from .env.local
if ! grep -q "^${KEY}=" .env.local 2>/dev/null; then
echo "$line" >> .env.local
ADDED=$((ADDED + 1))
fi
done < .env.local.example
echo "Added $ADDED missing keys to .env.local"
else
cp .env.local.example .env.local
echo "Created .env.local from .env.local.example"
fi
```
**Why this matters:**
- add-project Phase 4 dumps 1Password → `.env.local` with secrets (API keys, tokens)
- 1Password typically doesn't include infrastructure defaults (`REDIS_URL`, `STORAGE_*`, `SMTP_*`)
- Without reconciliation, `.env.local` is incomplete and tests/build fail
- This step fills gaps with safe defaults while preserving real secrets
## Import Path Configuration
Both project structures use the same import path thanks to TypeScript path mapping:
```typescript
// In any file (API routes, components, etc.)
import { env } from "@/env";
```
**With `--src-dir`**: `@/env` resolves to `src/env.ts`
**With `--no-src-dir`**: `@/env` resolves to `env.ts` (tsconfig.json should have `"@/*": ["./*"]`)
This ensures consistent imports regardless of project structure.
## Next Steps
1. Generate a production auth secret:
```bash
openssl rand -base64 32
```
2. **Load external service API keys from 1Password** (recommended):
- Use the `/env-from-1password` skill to automatically load:
- `FAL_KEY`
- `REPLICATE_API_TOKEN`
- `AI_GATEWAY_API_KEY`
- `EXA_API_KEY`
- `BLOB_READ_WRITE_TOKEN`
- `RESEND_API_KEY`
- Alternatively, manually copy keys from 1Password to `.env.loRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.