fractal-template-bootstrap

Frontmatter
name: fractal-template-bootstrap
description: Bootstrap skill for starting a new project from the philogicae/fractal-template. Use when a user asks to scaffold a new webapp. Covers cloning, the folder layout, what must be customized/deleted, and the template's conventions.
license: MIT
notes: Content negotiation - Returns raw markdown for agents/curl (detected via User-Agent). Returns styled HTML for browsers. Use '?raw=1' query parameter to force raw markdown (e.g., /skill.md?raw=1).
metadata:
  author: philogicae
  version: "1.5.2"
  template-type: nextjs
  source: https://github.com/philogicae/fractal-template
  live-demo: https://fractal-template.binaryeyelabs.xyz
  stack:
    - Next.js 16 (App Router, Turbopack)
    - React 19
    - TypeScript (strict)
    - Tailwind CSS v4 (CSS-first)
    - HeroUI v3
    - Zustand (+ persist)
    - Biome
  features:
    - App Router + React Server Components
    - Internationalization via a server-resolved locale (`NEXT_LOCALE` cookie + `Accept-Language`) and a client `LocaleProvider` — **no `[lang]` URL segment**. Ships with 12 locales (`en`, `zh`, `es`, `ar`, `fr`, `pt`, `ru`, `ja`, `de`, `ko`, `it`, `ro`); delete the ones you don't need when customizing, add more only when needed. **All user-visible text must use i18n** — no hardcoded strings in components
    - Dark mode via `next-themes` with FOUC prevention (theme-aware html background)
    - Mobile-first responsive layout
    - Error boundary, loading (Skeleton-based) and 404 pages
    - Debounce hooks, `useSyncExternalStore`-backed media-query hook
    - Security headers, AVIF/WebP image optimization with strict SVG CSP
    - Site-wide config at `app/config/site.ts` as single source of truth
    - Multi-stage Dockerfile with Next.js standalone output
    - Pre-configured design system with dark/light modes — see [`DESIGN.md`](./DESIGN.md) for complete reference

Fractal Template — Bootstrap Skill

Audience. AI agents spinning up a new project from philogicae/fractal-template. This document is self-contained: it covers both the bootstrap steps and the conventions the agent needs to customize the repo correctly.

1. Clone and install

git clone https://github.com/philogicae/fractal-template.git <project-name>
cd <project-name>
rm -rf .git && git init
pnpm install
pnpm dev           # http://localhost:3000

Requirements: Node.js 24+, pnpm 11+, modern browser.

2. Repository tour

<project-name>/
├── app/
│   ├── api/
│   │   └── hello/               # DEMO endpoint — delete or replace
│   ├── skill.md/                # Route that serves SKILL.md raw — KEEP
│   ├── components/              # Shared UI (no barrel — import per file)
│   │   ├── Container.tsx        # Keep (generic width wrapper)
│   │   ├── FeatureCard.tsx      # DEMO — delete if unused
│   │   ├── LanguageSwitcher.tsx # Keep (locale dropdown)
│   │   ├── Skeleton.tsx         # Keep (themed pulse placeholder)
│   │   ├── StatusBadge.tsx      # DEMO — delete if unused
│   │   └── ThemeToggle.tsx      # Keep (uses next-themes)
│   ├── config/                  # Site-wide config (single source of truth)
│   │   └── site.ts              # Name, description, nav (labelKey), socials, theme colors
│   ├── i18n/                    # Internationalization (provider-based, no URL segment)
│   │   ├── config.ts            # SINGLE REGISTRY: Locale, Dictionary, locales,
│   │   │                        # localeMeta, hasLocale(), getDictionary()
│   │   ├── dictionaries/        # en.json (default). Delete extra locales when customizing;
│   │   │                        # add more only when needed. Each ships `meta: { flag, native }`
│   │   ├── get-locale.ts        # Zero-dep Accept-Language matcher
│   │   ├── server.ts            # getCurrentLocale(), getCurrentDictionary()
│   │   ├── actions.ts           # setLocaleAction Server Action (NEXT_LOCALE cookie)
│   │   └── LocaleProvider.tsx   # Client context: useLocale(), useDict()
│   ├── layout/                  # Navbar.tsx (with LanguageSwitcher), Footer.tsx — driven by `@config/site`
│   ├── stores/                  # Zustand (no barrel — import per file)
│   │   └── counter.ts           # DEMO — delete
│   ├── utils/                   # cn(), debounce, media-query, click-outside — Keep
│   ├── playground/              # DEMO page — DELETE
│   ├── globals.css              # Design tokens — CUSTOMIZE
│   ├── layout.tsx               # Root layout + metadata — CUSTOMIZE
│   ├── providers.tsx            # Client providers (next-themes) — Keep
│   ├── page.tsx                 # Landing page — REPLACE
│   ├── error.tsx / loading.tsx / not-found.tsx   # Keep, restyle
├── public/                      # favicon, logo, manifest, robots — REPLACE
├── .env.example                 # Customize variables
├── next.config.mjs              # Security headers, image formats — review
├── biome.json                   # Lint/format config
├── package.json                 # name/description/repo — CUSTOMIZE
├── Dockerfile / compose.yaml    # Ready to use — override names/port via .env
├── README.md                    # REWRITE for the new project
├── AGENTS.md                    # In-repo agent conventions — keep in sync as you modify the project
├── SKILL.md                     # REWRITE to describe the new app (see §5) or delete if the app needs no agent surface
├── CHECKLIST.md                 # Tickable bootstrap checklist — delete once every box is ticked
└── DESIGN.md                    # Complete design system reference

Path aliases (tsconfig.json):

"@components/*": ["./app/components/*"],
"@config/*":     ["./app/config/*"],
"@i18n/*":       ["./app/i18n/*"],
"@layout/*":     ["./app/layout/*"],
"@stores/*":     ["./app/stores/*"],
"@utils/*":      ["./app/utils/*"]

No barrel exports. Every import targets a specific file (@components/Container, @stores/counter, @layout/Navbar, ...).

3. Customization checklist

Use CHECKLIST.md at the repo root — do not work from a list in this document. CHECKLIST.md is the single, tickable source of truth for every customization step (identity & metadata, public assets, layout / chrome, landing page, design tokens, internationalization, demo-code deletions, environment & infrastructure, documentation, sanity checks). Work through it top-to-bottom and tick boxes as you go so the next session sees exactly what is left.

This skill covers the conventions needed to carry out those steps correctly (i18n wiring, siteConfig as the identity single-source-of-truth, nav labelKey contract, common tasks); the project-wide instructions below support that work. For the task list itself, switch to CHECKLIST.md.

Conventions worth knowing up front

4. Delete demo-only code

These files exist only to showcase the template. Remove them before writing product code, unless the user explicitly wants them kept:

Keep the app/skill.md/route.ts handler — it is the delivery mechanism for the rewritten SKILL.md (see §5).

5. Rewrite SKILL.md for the new project (default) — or delete it

Default path. After customization, this file must be rewritten so agents can interact with the shipped application through /skill.md. Its new purpose is to describe the app — its routes, API, auth, and how an agent should consume it — not how to install the template.

Opt-out. If the project has no agent-facing surface and the user does not want one, delete instead:

Suggested structure when rewriting:

---
name: <project-name>
description: <what the app does, who it is for>
---

# <Project name>

## Overview

Short description of the product and its primary users.

## Routes

- `/` — <purpose>
- `/<route>` — <purpose>

## API

- `GET /api/<endpoint>` — params, response shape, auth
- `POST /api/<endpoint>` — body, response shape

## Data model / state

- Zustand stores and what they own
- External data sources, DB, third-party APIs

## Environment variables

List every required variable with a one-line description.

## How an agent should interact with the app

- Preferred endpoints for programmatic use
- Auth flow
- Rate limits, error shapes

AGENTS.md must be kept in sync throughout customization — not as a one-shot pass at the end. As soon as you remove the playground / counter store / demo components, drop them from the "Demo code to remove" list; as soon as you add new routes, stores, or env variables, record them in the relevant sections so the next agent reading AGENTS.md sees an accurate picture of the project.

6. Sanity checks before handing off

pnpm lint        # Biome auto-fix
pnpm build       # Production build must succeed

Grep for any leftover template branding:

rg -i "next\.js template|philogicae|fractal-template|playground|counter"

Every match should be intentional.


Reference — template conventions

Quick reference for the conventions baked into the template, needed while customizing.

Tech stack details

Framework

Styling

UI — HeroUI v3

State — Zustand

Dev tooling

Code conventions

File placement

Naming

Server vs Client components

Imports

import { Container } from "@components/Container";
import { ThemeToggle } from "@components/ThemeToggle";
import { siteConfig } from "@config/site";
import { NavBar } from "@layout/Navbar";
import { useCounterStore } from "@stores/counter";
import { cn } from "@utils/tw";

Common tasks

Add a page

  1. Create app/<route>/page.tsx.
  2. Add an entry to siteConfig.nav in app/config/site.ts if it should appear in the header.

Add an API route

// app/api/<endpoint>/route.ts
export async function GET(): Promise<Response> {
  return Response.json({ ok: true });
}

export async function POST(request: Request): Promise<Response> {
  const body = await request.json();
  return Response.json({ received: body });
}

Create a Zustand store

// app/stores/<name>.ts
import { create } from "zustand";

interface State {
  value: string;
  setValue: (v: string) => void;
}

export const useMyStore = create<State>()((set) => ({
  value: "",
  setValue: (v) => set({ value: v }),
}));

Consume a store (with selectors)

import { useCounterStore } from "@stores/counter";

// Good — re-renders only when `count` changes
const count = useCounterStore((s) => s.count);

// Bad — re-renders on any state change
const { count } = useCounterStore();

Client component example

"use client";
import { Container } from "@components/Container";
import { Button } from "@heroui/react";
import { useState } from "react";

export function Example(): React.ReactElement {
  const [value, setValue] = useState("");
  return (
    <Container size="md">
      <Button variant="outline" onPress={() => setValue("x")}>
        Click
      </Button>
    </Container>
  );
}

Theme system

CSS variables (app/globals.css):

See DESIGN.md for the complete design reference including the color palette, typography, elevation, and component tokens.

Important: DESIGN.md and app/globals.css must always stay synchronized. When you modify any design token in globals.css, update the corresponding section in DESIGN.md immediately. These are twin source-of-truth files — the CSS is the implementation, the markdown is the documentation.

Looking for design inspiration? Browse curated design templates at styles.refero.design.

Usage:

<div className="bg-(--color-bg-primary) text-(--color-text-primary)">
  <button className="btn-primary">Click</button>
  <button className="btn-cta-ghost">Ghost</button>
</div>

Dark mode:

Utilities

import { cn } from "@utils/tw";
import { useMediaQuery, useBreakpoint } from "@utils/media-query";
import {
  useDebounce,
  useDebouncedCallback,
  useDebounceState,
} from "@utils/debounce";
import { useClickOutside } from "@utils/click-outside";

Performance notes

Scripts

pnpm dev      # Dev server, Turbopack, 0.0.0.0:3000
pnpm build    # Production build (Turbopack)
pnpm start    # Production server
pnpm lint     # Biome check + auto-fix
pnpm upgrade  # pnpm update && pnpm prune
pnpm clean    # rimraf .next out node_modules && pnpm install
pnpm repomix  # Markdown snapshot of the codebase for agents

References