Skip to content

Latest commit

 

History

History
175 lines (122 loc) · 6.12 KB

File metadata and controls

175 lines (122 loc) · 6.12 KB

Setup

First-run guide for branding a fresh copy of deck-forge. The fastest path is the /setup agent in Cursor or Claude Code; everything it does can also be done by hand. Both routes are below.


Prerequisites

npm install
npm run dev    # http://localhost:8080 — example deck at /d/example

Option A — /setup (agent)

Open the project in Cursor or Claude Code and run:

/setup

(No slash command? Just tell the agent: "set up this template for my brand.")

The interview

The agent asks a short set of questions, with sensible defaults, and confirms before writing anything:

  1. Product / company name
  2. One-line tagline
  3. Primary brand color (hex, e.g. #2563EB)
  4. Secondary / accent color (hex, optional)
  5. Landing background — dark or light
  6. Logo — a path to a file you will drop in /public (e.g. /logo.svg), or skip for a wordmark
  7. Fonts — heading/sans and mono (default Inter + JetBrains Mono)
  8. Canonical URL

What it changes

File What gets written
src/index.css Brand tokens (hex → HSL channels, light tints + their *-dark variants), the font @import, and the body font-family
tailwind.config.ts fontFamily.sans / fontFamily.mono
src/brand.config.ts brand.name, tagline, url, logo, landingTheme
index.html <title> and the meta/OG description
package.json The kebab-case name

It then offers to delete the example deck so you start clean (see below for exactly what that removes). After applying:

npm install      # if you haven't already
npm run dev
npm run build    # verify it still compiles

Option B — by hand

Edit the same files yourself. The mapping from interview answer to file:

1. Colors — src/index.css

This file is the brand surface. Colors are stored as raw HSL channels in the form H S% L% (e.g. 221 83% 53%) so they compose with opacity: hsl(var(--brand-primary) / 0.4). Never store hex in a token.

Edit these first, in the :root block:

--brand-primary: 221 83% 53%; /* your primary accent */
--brand-primary-light: 221 83% 96%; /* tint for light surfaces */
--brand-primary-light-dark: 221 70% 16%; /* tint used on dark slides */
--brand-accent: 215 16% 47%; /* secondary / muted brand line */

Then, if you want to tune them, the surfaces (--bg-page/-dark, --bg-surface*, --bg-code*), text (--text-primary/secondary/muted/ faint/on-brand and their *-dark counterparts), borders, and status colors.

Keep the editor-UI tokens in sync with your primary so the app chrome matches:

--primary: 221 83% 53%; /* = --brand-primary */
--ring: 221 83% 53%; /* = --brand-primary */

Dark slides need no extra work. The .slide-dark block (used when a slide declares <SlideFrame theme="dark">) remaps surfaces and text to their *-dark counterparts automatically. Just set the token values.

Converting hex → HSL channels

When you have a hex color, convert it before storing. Example for #2563EB:

  1. Normalize to 0–1: R = 0x25/255 = 0.145, G = 0x63/255 = 0.388, B = 0xEB/255 = 0.922.
  2. max = 0.922 (B), min = 0.145 (R), delta = 0.777.
  3. L = (max + min) / 2 = 0.533 → 53%.
  4. S = delta / (1 − |2L − 1|) = 0.777 / 0.933 = 0.833 → 83%.
  5. H (max is B): H = 60 × (((R − G) / delta) + 4) = 60 × (3.69) ≈ 221°.

So #2563EB → 221 83% 53%. Sanity-check by pasting hsl(221 83% 53%) into any color picker and comparing to the original hex.

2. Fonts — TWO files (plus the body rule)

Fonts live in two places, and both must agree:

  • src/index.css — change the Google Fonts @import at the top of the file and the body { font-family: ... } rule lower down.
  • tailwind.config.ts — change fontFamily.sans and fontFamily.mono under theme.extend.

Default is Inter + JetBrains Mono.

3. Identity — src/brand.config.ts

Set the non-color identity in the brand object:

export const brand = {
  name: 'Your Name',
  tagline: 'Your one-liner.',
  url: 'https://yourdomain.com',
  logo: '/logo.svg', // path under /public; '' renders a wordmark
  landingTheme: 'dark', // 'dark' | 'light'
}

4. Page metadata — index.html

Update <title> and the meta/OG description (name="description", og:title, og:description, twitter:*).

5. Package name — package.json

Set the kebab-case "name" field to your project, e.g. "name": "your-name".


Remove the example deck

Once you have your own deck (or as the last step of setup), delete the demo so the app still builds:

  1. Delete the folder src/slides/example-deck/ (all SlideNN*.tsx plus index.ts).
  2. Delete the page src/pages/ExampleDeck.tsx.
  3. Delete src/slides/_shared/data.ts (it only holds example copy — keep it if you reuse the pattern).
  4. In src/brand.config.ts, remove the example-deck entry from the decks array.
  5. In src/App.tsx, remove import ExampleDeck from './pages/ExampleDeck' and the 'example-deck': ExampleDeck entry in the deckPages map.

The app builds with an empty decks array — the landing simply lists nothing.

Adding your own deck is a separate, four-step flow. See docs/AUTHORING.md.


Verify gate

Before you commit, run the same checks CI runs:

npm run build && npm run lint && npx prettier --check .

Formatting is Prettier with semi: false, singleQuote: true, printWidth: 120, trailingComma: es5. Auto-fix with npm run format. Tests: npm test.