Design Tokens — Make It Yours
Set up the colours, fonts, and spacing rules once. Then every component you build looks intentional automatically.
A design token is just a named value. Instead of writing #4F46E5 everywhere you need indigo, you write indigo. Instead of 'Cormorant Garamond, serif' everywhere, you write font-display. Then if you decide your school's indigo should be a touch warmer, you change one place and every page updates.
This is the whole reason real projects feel "designed" and prototypes don't.
1. Pick Your Tokens
Open the brief you wrote in Project 1. You have three adjectives and probably a sense of the colours. Now pin them down.
Pick exactly:
- Two colours — a primary accent (used for buttons, links, highlights) and a secondary accent (used sparingly for a different kind of emphasis).
- One dark surface colour — for footers, dark sections, dark mode if you add it later.
- Two fonts — one for body text (sans-serif), one for the main heading (serif or display font for character).
Aurora Public School's choices (used in examples throughout):
You can use these exact values if you can't decide. They're tested and they work for a school site.
2. Add Your Tokens to globals.css
create-next-app generates a globals.css that starts with @import "tailwindcss". That one line pulls in every Tailwind utility. Right after it, add an @theme block — Tailwind v4's way of declaring design tokens:
After saving, in any component you can now write:
And it just works. The @theme variable names are the source of truth — Tailwind generates bg-indigo, text-dark-base, font-display, etc. directly from them. No separate config file needed.
tailwind.config.ts (older templates still generate one), you can delete it — @theme in CSS replaces it entirely in Tailwind v4.3. Load the Fonts
Next.js has built-in font optimisation. Open src/app/layout.tsx. Add font imports at the top:
The --font-sans and --font-display CSS variables that layout.tsx injects get picked up by the @theme block you wrote in step 2. No extra config needed.
Now <h1 className="font-display">...</h1> renders in Cormorant Garamond. <p>...</p> defaults to DM Sans.
4. Finish globals.css
Your final globals.css combines the Tailwind import, your @theme tokens, and the two global rules from above:
That's it. Most styling is per-component, using Tailwind classes. Global CSS should stay tiny.
5. Store the School Data in One Place
Create src/lib/constants.ts. This is your school's "single source of truth" — the constant that every page imports.
Now every page imports from @/lib/constants and there is exactly one place to update if a branch phone number changes.
BRANCHES array.6. Add Photos to /public
Inside public/, create a branches/ folder. Drop your downloaded photos in:
Files inside public/ are served from the root of your site. So public/branches/andheri.jpg becomes the URL /branches/andheri.jpg — which matches the image: '/branches/andheri.jpg' in BRANCHES.
For now, even placeholder photos are fine. You can replace them later. The naming is what matters.
7. Commit and Push
Wait ~60s, then refresh aurora-school.vercel.app. The default Next welcome page is still there (we haven't touched page.tsx yet), but the production build now includes your fonts and tokens — ready to use on the next page.
What's Next
The infrastructure is set. The design language is locked in. Now you build the actual pages.
The next page (branches-page.mdx) builds the /branches route — and along the way you'll see how having BRANCHES as one constant makes the whole thing trivial. After that, the home page, the admissions page with a working contact form, and finally about + deploy + checklist.