This skill should be used when the user asks to "create a new website", "spin up a frontend", "set up a Next.js site with aegis auth", "scaffold a new web app with authentication", "create a site with login and i18n", or needs a production-ready Next.js frontend integrated with ByteForge Aegis authentication. Provides complete project scaffolding with auth pages, internationalization, Docker deployment, and a design system.
npx claudepluginhub jmazzahacks/byteforge-claude-skills --plugin byteforge-skillsThis skill uses the workspace's default tool permissions.
This skill scaffolds a complete Next.js 16 frontend with ByteForge Aegis authentication, internationalization (next-intl), Tailwind CSS v4, and Docker deployment. The generated project includes login, email verification, password reset, and protected dashboard pages out of the box.
references/auth-page-templates.mdreferences/auth-templates.mdreferences/backend-auth-templates.mdreferences/build-publish-template.mdreferences/component-templates.mdreferences/config-templates.mdreferences/design-system.mdreferences/docker-templates.mdreferences/i18n-templates.mdreferences/logging-templates.mdreferences/page-templates.mdreferences/tenant-api-key-templates.mdreferences/webhook-templates.mdCreates isolated Git worktrees for feature branches with prioritized directory selection, gitignore safety checks, auto project setup for Node/Python/Rust/Go, and baseline verification.
Executes implementation plans in current session by dispatching fresh subagents per independent task, with two-stage reviews: spec compliance then code quality.
Dispatches parallel agents to independently tackle 2+ tasks like separate test failures or subsystems without shared state or dependencies.
This skill scaffolds a complete Next.js 16 frontend with ByteForge Aegis authentication, internationalization (next-intl), Tailwind CSS v4, and Docker deployment. The generated project includes login, email verification, password reset, and protected dashboard pages out of the box.
[locale] dynamic segmentsbrowserClient with token refresh, useAuth hook with proactive refresh, AuthCTA component/api/health for container orchestrationIMPORTANT: Before creating any files, ask the user these questions:
"What is your project name?" (e.g., "DevNotes", "TaskFlow", "ReleasePad")
{ProjectName} - Display name (e.g., "DevNotes"){project-name} - Kebab case for package.json, Docker, URLs (e.g., "devnotes"){project_name} - Snake case for internal use (e.g., "dev_notes")"What is the site domain?" (e.g., "devnotes.ai", "taskflow.reallybadapps.com")
NEXT_PUBLIC_SITE_DOMAIN"What is the Aegis API URL?" (default: https://aegis.reallybadapps.com)
NEXT_PUBLIC_AEGIS_API_URL (browser bootstrap) and AEGIS_API_URL (server-side proxy)3a. "What is the tenant API key for this site? (Get it from the Aegis admin dashboard → Site → Settings → Tenant API Key)"
AEGIS_TENANT_API_KEY (server-side only). REQUIRED for the gated public auth endpoints. See Step 5b and references/tenant-api-key-templates.md.3b. "What is the site_id for this site in Aegis?" (visible in the admin dashboard)
AEGIS_SITE_ID (server-side, used by proxy routes for verify-email/etc.)."What is the container registry URL?" (e.g., ghcr.io/org/project-frontend)
"What is a one-line description of the project?" (e.g., "AI-powered release notes platform")
"Does your backend need to provision users when they verify on Aegis? If yes, what backend handles it?" (e.g., "Yes, Flask backend" / "Yes, Next.js API routes" / "No")
{project-name}-frontend/
├── app/
│ ├── layout.tsx
│ ├── globals.css
│ ├── [locale]/
│ │ ├── layout.tsx
│ │ ├── page.tsx # Home page (customize per project)
│ │ ├── login/page.tsx
│ │ ├── verify-email/page.tsx
│ │ ├── forgot-password/page.tsx
│ │ ├── reset-password/page.tsx
│ │ ├── confirm-email-change/page.tsx
│ │ ├── welcome/page.tsx
│ │ └── dashboard/page.tsx
│ └── api/health/route.ts
├── i18n/
│ ├── routing.ts
│ ├── request.ts
│ └── navigation.ts
├── lib/
│ ├── browserClient.ts
│ ├── logger.ts
│ └── useAuth.ts
├── components/
│ ├── AuthCTA.tsx
│ └── LanguageSwitcher.tsx
├── messages/
│ └── en.json
├── public/
│ └── .gitkeep # required so Dockerfile COPY /app/public succeeds
├── proxy.ts # next-intl middleware
├── package.json
├── next.config.ts
├── tsconfig.json
├── tailwind.config.ts
├── postcss.config.mjs
├── global.d.ts
├── .env.example
├── .gitignore # includes VERSION (and build-publish.sh if Tier 2)
├── Dockerfile
├── docker-compose.example.yaml
└── build-publish.sh # chmod +x, see Step 12
Generate each configuration file using the templates in references/config-templates.md. These files are mostly boilerplate with placeholder substitutions:
package.json - Dependencies including byteforge-aegis-client-js, byteforge-loki-logging-ts, next-intl, Tailwind v4next.config.ts - next-intl plugin, transpilePackages for aegis client and loki logging, standalone outputtsconfig.json - ES2017 target, strict mode, @/* path aliastailwind.config.ts - Content paths for app/ and components/postcss.config.mjs - @tailwindcss/postcss pluginglobal.d.ts - IntlMessages type declaration.env.example - NEXT_PUBLIC_AEGIS_API_URL, NEXT_PUBLIC_SITE_DOMAIN, and Loki logging variablesCRITICAL: Replace all instances of {project-name}, {ProjectName}, {site_domain}, {aegis_api_url}, and {project_description} in every file.
Generate files from references/i18n-templates.md:
i18n/routing.ts - Locale definitions (start with ['en'], add more as needed)i18n/request.ts - Server-side message loadingi18n/navigation.ts - Locale-aware Link, useRouter, usePathnameproxy.ts - next-intl middleware (matches all paths except /api, /_next, static files)These files are identical across projects. No placeholder substitution needed.
Generate files from references/auth-templates.md:
lib/browserClient.ts - Singleton AuthClient that persists tokens in memory and syncs to localStorage. Includes initAuthClientFromLogin(), refreshAuthTokens(), isTokenExpired(), clearAuthClient(), and the browserAuthProxy shim that posts to the local /api/frontend/auth/* proxy routes (used by auth pages for the six tenant-key-gated endpoints).lib/useAuth.ts - React hook that reads auth state from localStorage, proactively refreshes tokens (5-minute buffer, 60-second check interval), and auto-logs out on refresh failure.These files are identical across projects except for the default env variable values ({aegis_api_url}, {site_domain}).
After backend image v40+, six public auth endpoints (register, login, request-password-reset, reset-password, verify-email, check-verification-token) require an X-Tenant-Api-Key header that must live server-side. This means scaffolded apps need backend proxy routes for these flows — the browser cannot call Aegis directly for them.
Generate from references/tenant-api-key-templates.md:
lib/serverAuthClient.ts — server-side AuthClient factory configured with AEGIS_TENANT_API_KEY and AEGIS_SITE_ID from env.app/api/frontend/auth/register/route.tsapp/api/frontend/auth/login/route.tsapp/api/frontend/auth/request-password-reset/route.tsapp/api/frontend/auth/reset-password/route.tsapp/api/frontend/auth/verify-email/route.tsapp/api/frontend/auth/check-verification-token/route.tsbrowserAuthProxy helper is already inlined in lib/browserClient.ts from Step 5 — auth pages call it instead of the singleton AuthClient for the gated endpoints.)Ask the user: "Do you have a tenant API key for this site (from the Aegis admin dashboard)?" If yes, set AEGIS_TENANT_API_KEY in .env.local. If no, direct them to Aegis admin → Site → Settings → Tenant API Key. The site's id becomes AEGIS_SITE_ID.
The auth pages (Step 6) call browserAuthProxy.* for the six gated endpoints; the singleton AuthClient from auth-templates.md is still used for unprotected calls (getSiteByDomain, me, change-password, logout, refresh).
Generate all authentication pages from references/auth-page-templates.md:
app/[locale]/login/page.tsx - Email/password form, site lookup, token storageapp/[locale]/verify-email/page.tsx - Token validation, optional password setupapp/[locale]/forgot-password/page.tsx - Email input, always shows success (security)app/[locale]/reset-password/page.tsx - New password form with confirmationapp/[locale]/confirm-email-change/page.tsx - Auto-confirms on loadapp/[locale]/welcome/page.tsx - Success page with confetti animationCRITICAL: In each auth page, replace the branded footer text. The pattern uses a split-color brand display:
<span className="text-[var(--foreground)]">{BrandPart1}</span>
<span className="text-[var(--amber-glow)]">{BrandPart2}</span>
Replace these spans with the new project's brand name.
Generate from references/component-templates.md:
components/AuthCTA.tsx - Smart button: shows "Sign In" or "Go to Dashboard" based on auth statecomponents/LanguageSwitcher.tsx - Dropdown with globe icon, scales to any number of languagesapp/layout.tsx - Root layout with metadataapp/[locale]/layout.tsx - Locale layout with NextIntlClientProviderGenerate from references/page-templates.md:
app/[locale]/dashboard/page.tsx - Protected page with header, logout, language switcher, placeholder contentapp/[locale]/page.tsx - This page is project-specific. Use the template as a starting point but customize the hero section, feature cards, and description for the actual project.Generate app/globals.css from references/design-system.md.
The design system includes:
prefers-color-scheme.card, .input-field, .btn-primary, .btn-secondary, .spinner.status-success, .status-errorfadeInUp, fadeIn, scaleIn, delay classesGenerate messages/en.json from references/i18n-templates.md.
Contains all translation keys organized by page: Common, Home, Welcome, Login, Verify, ForgotPassword, ResetPassword, ConfirmEmailChange, Dashboard.
CRITICAL: Replace {ProjectName} and {project_description} in the translation values.
Generate from references/docker-templates.md:
Dockerfile - 3-stage build (deps → builder → runner) with CR_PAT for private GitHub packagesdocker-compose.example.yaml - Service definition with image URL and port mappingapp/api/health/route.ts - Returns JSON with status, service name, and unix timestampGenerate build-publish.sh from references/build-publish-template.md. Ask the user which tier to use before generating:
NEXT_PUBLIC_AEGIS_API_URL and NEXT_PUBLIC_SITE_DOMAIN hardcoded at the top of the script. Best for developer laptops with a single stable deployment target. Must be gitignored.Why this step exists: The flask-docker-deployment build-publish.sh pattern only passes CR_PAT as a build arg. A Next.js frontend also needs NEXT_PUBLIC_AEGIS_API_URL and NEXT_PUBLIC_SITE_DOMAIN as build args because those values are baked into the client JavaScript bundle at build time. Blindly copying the Flask pattern produces an image that starts successfully but has the wrong backend URL in the client bundle.
Actions:
Generate build-publish.sh from the chosen tier in the template. Replace {registry_url} with the container registry URL from Step 1. For Tier 2, also replace {aegis_api_url} and {site_domain}.
chmod +x build-publish.sh
Create public/ with a .gitkeep:
mkdir -p public && touch public/.gitkeep
The Dockerfile has COPY --from=builder /app/public ./public, which fails if the directory does not exist. Next.js does not create public/ by default.
Create or update .gitignore to include:
VERSION
For Tier 2, also add:
build-publish.sh
Generate lib/logger.ts from references/logging-templates.md.
This provides a dual-mode logger:
DEBUG_LOCAL=true) — Formatted console output, no Loki connection neededLOKI_URL set) — Structured JSON logs shipped to Grafana Loki with batchingAfter creating lib/logger.ts, import the logger singleton in all API route handlers (app/api/**/route.ts). Use logger.info() for success paths and logger.error() in catch blocks, always including the route field in extra for Loki filtering.
CRITICAL: Replace {project-name} in the logger template (appears in emitter tags and the default singleton).
CRITICAL: byteforge-loki-logging-ts is server-side only (uses node:https). Never import it in 'use client' files or Edge Runtime routes.
If the user indicated their backend needs to provision users on verification (Step 1, question 6), guide them through webhook setup using references/webhook-templates.md.
This step is backend-agnostic — the webhook handler can live in a Next.js API route, Flask endpoint, Express server, or any other backend that can receive HTTP POST requests.
Key actions:
AEGIS_WEBHOOK_SECRET to the project's .env.examplewebhook_url on their Aegis site via the admin APIIf the user does not need webhook provisioning, skip this step entirely.
npm install
npm run build
Verify all 10 pages generate (3 locales × pages if multiple languages, or just /en/* for single language).
browserClient.ts persists tokens in memory and syncs to localStorageinitAuthClientFromLogin() instead of manual localStorage.setItem() callsuseAuth hook proactively refreshes tokens 5 minutes before expiry (checks every 60s)clearAuthClient() is the single source of truth for clearing all auth state on logoutauth_token, refresh_token, token_expires_at, user_id, site_id, site_name)/login when not authenticated/{locale}/page (e.g., /en/login, /es/login)localePrefix: 'always' ensures locale is always in the URLuser.verified webhook → tenant backend provisions user (creates DB record, generates API key, etc.)"{timestamp}.{body}" with shared secret — tenant verifies before processingThe build-publish.sh script generated in Step 12 is specific to this skill — do not substitute the flask-docker-deployment version. Next.js frontends require NEXT_PUBLIC_AEGIS_API_URL and NEXT_PUBLIC_SITE_DOMAIN as build args (they are baked into the client JavaScript bundle at build time), and the frontend template validates all three build args up front to avoid silent misconfiguration. See references/build-publish-template.md for the full template and rationale.
If the project needs a database, use postgres-setup skill.
If the project also has a Flask backend on the same Loki infrastructure, use byteforge-loki-logging skill for the Python side. Both skills push to the same Grafana Loki instance and can be queried together using the application label.
/api/auth/me)When the frontend built with this skill talks to a custom backend (Next.js API routes, a sibling Flask service, etc.), that backend should validate incoming Aegis bearer tokens by forwarding them to GET /api/auth/me rather than trusting a client-asserted user_id. This is the supported service-to-service auth pattern as of Aegis image version 39 / byteforge-aegis-client-js@2.8.0 / byteforge-aegis-client-python@1.2.0.
The frontend itself does not need to call /me — it already has user info from /api/auth/login. Use /me only on the backend side.
See references/backend-auth-templates.md for drop-in middleware: a Next.js API route helper (lib/aegisAuth.ts) and a Flask decorator (@aegis_auth_required), both with short-TTL token caching and the 401-failure-mode guidance baked in.
All template code is organized in reference files for progressive loading:
references/config-templates.md - package.json, next.config.ts, tsconfig.json, tailwind, postcss, .envreferences/i18n-templates.md - Routing, request config, navigation, translations (en.json)references/auth-templates.md - browserClient.ts, useAuth.tsreferences/tenant-api-key-templates.md - 6 backend proxy routes for gated public auth endpoints, server-side AuthClient helper, browserAuthProxyreferences/auth-page-templates.md - All 6 authentication pagesreferences/component-templates.md - AuthCTA, LanguageSwitcher, layoutsreferences/page-templates.md - Dashboard, home pagereferences/design-system.md - globals.css with full design systemreferences/logging-templates.md - lib/logger.ts with Loki and console dual-mode loggingreferences/docker-templates.md - Dockerfile, docker-compose, health endpointreferences/build-publish-template.md - build-publish.sh script (two tiers: env-sourced and baked-in) with auto-versioning, three-build-arg validation, and public/ directory gotchareferences/webhook-templates.md - Aegis user.verified webhook contract, signature verification, and provisioning patternreferences/backend-auth-templates.md - /api/auth/me introspection pattern with Next.js API route helper and Flask decorator for validating Aegis tokens on downstream backends