Nitip Design System
Reusable tokens and components for every page of the Nitip template. The published Framer template is the reference for look and behavior; component names follow the Figma file so designers and developers talk about the same thing.
See it live at /style-guide (not linked from the site, not indexed).
Structure
Section titled “Structure”src/ design-system/ ← this folder: page-agnostic building blocks theme.css ← color, breakpoint, easing and animation tokens (Tailwind v4 @theme) tokens/text.ts ← text styles (h01 … menu) tokens/motion.ts ← transitions and variant presets utils/ ← cn(), link helpers components/ ← actions, brand, navigation, layout, cards, media, data, patterns, forms, cursor index.ts ← import everything from "@/design-system" components/ site/ ← Header, Footer (design system + site content) sections/ ← page sections, reusable across pages, content passed in as props content/ types.ts ← content model (plain data) routes.ts ← every URL site.ts ← brand, navigation, contact, footer collections/ ← projects, services, posts, testimonials, careers, team pages/ ← page copy (home.ts, about.ts, …) lib/to-ui.ts ← maps content items to component props- Design-system components never import from
@/content. Data comes in through props, so the same component works on any page and in any template. - Pages pass content to sections; sections compose design-system components. Keep copy out of components.
- Links come from
routes(routes.project(slug)), never hard-coded strings. - Use tokens, not raw values:
text.h02,bg-ink,border-line,springButton. If a new value repeats, add a token. - Match Framer first. Any deliberate refinement is documented in the component’s comment.
- New component? Put it in the right
components/group, export it fromindex.ts, add it to/style-guideand the table below.
Tokens
Section titled “Tokens”| Token | Values |
|---|---|
| Breakpoints | Phone < 810 · md Tablet 810–1199 · lg Desktop ≥ 1200 |
| Colors | ink #101010 · canvas #F6F6F6 · line #D9D9D9 · muted #818181 · accent #FC5000 · star #FDCA49 · danger #FF2244 |
| Font | Inter (font-sans) |
| Text styles | text.h01 46/58/72 · h02 44/52/64 · h2 32/36/42 · h3 28/32/36 · h4 24/26/28 · h5 20/22/24 · h6 18/19/20 · hugeParagraph 24/28/32 · largeParagraph 18 · paragraph 16 · smallParagraph 14 · button 14 uppercase · menu 13 uppercase |
| Section spacing | <Section>: sectionGutters 20/30/40, sectionPadding 60/80/100 · sectionGap 60/80/100 between header and content · pageTitlePadding 50 top for page titles |
| Motion | springButton (spring 0.4s, bounce 0.2) · springSoft (0.4s, no bounce) · springSlide (200/40) · springCursor (500/60) · reveal (height reveal) · ease-framer CSS tween for image zooms |
Components
Section titled “Components”| Component | Figma name | Notes |
|---|---|---|
PrimaryButton |
Primary Button (Default / No Icon) | icon={false} for No Icon. Hover: shadow + arrow 45° |
SecondaryButton |
Secondary Button | Hover: underline + arrow -45° |
BigButton |
Big Button | Footer menu link |
SocialMediaLink |
Social Media | Hover: black row, white text |
MenuButton |
Menu (Default / Hover / Active) | Active has no hover |
TextLink |
— (Framer link preset) | 80% ink + underline on hover; external links handled |
ArrowButton |
— (Framer slideshow arrow) | |
SwitchButton, Switch |
Switch Button (Default / Active), Switch | Square toggle, #222 outline; Default hover 50% opacity |
LoadMoreButton |
Load More | Square ink button, 150 × 40, no hover; the parent places it (centered under the blog grid, left under careers) |
Logo |
Logo (Black / White) | tone="light" for dark backgrounds |
Icon |
Phosphor icon set | name, tone, size via className |
Navigation |
Navigation (Default / Home / …) | Active item from pathname; layout="stack" for mobile |
Hamburger |
Hamburger (Default / Close) | |
Breadcrumbs |
— (Framer “Breadcrumbs”) | Last item is the current page |
Section, SectionHeader, SectionLabel, Divider |
Section / Title Section | SectionHeader size="small" for Heading 6 titles; leadClassName sets the lead width |
PageTitle |
Page Title | Breadcrumbs (optional), h1, divider, description (max 600, descriptionWidth="wide" 850). Use with padding={pageTitlePadding} |
ProjectCard |
Project With Details (Default) | “View Project” cursor on the image |
ProjectSimpleCard |
Project Simple Card (Open / Close) | Used by ProjectRecentList |
ProjectListItem |
Project With Details (Desktop / Tablet / Phone List) | Row with divider; View Details and image zoom on desktop |
PostCard |
Post Card | “Read” cursor |
TestimonialCard |
Testimonial (Desktop / Tablet / Mobile) | |
TextPoint |
Text Point | List row with dot |
HighlightList |
— (Framer rich text) | Bulleted list with a bold lead phrase |
FactCard |
Fact Number | tone="dark" for the ink card; ring cursor |
TeamCard |
Team | Portrait, name, role, email. No hover |
CoverImage |
— (Framer Image + Cover) | Bottom gradient with content; ring cursor |
ParallaxImage |
— (Framer Parallax) | speed/phoneSpeed/offset/scale; image sized so no gap ever shows; clip={false} to clip in the parent |
ScrollTransform |
— (Framer Scroll Transform, In View) | from/phoneFrom (x, y, scale, opacity) → rest while the frame scrolls into view |
Chart |
Chart (Desktop / Desktop Start / Mobile) | Grows on scroll; ring cursor |
PricingCard |
Pricing | Plan switch (hidden with one plan), included list, price, CTA |
Rating, AvatarGroup |
Hero “User Rating” | |
AccordionItem |
Service / Careers row | Shared accordion row; layout="service" | "career" sets columns. Closed rows hide the divider up to the title column (tablet/desktop) |
ServiceList |
Service (Open / Close) | |
CareerList |
Careers (Open / Close) | Dot marker, About the Role + Requirement; pageSize adds a left-aligned Load More |
ValueList |
Value (Desktop / Tablet / Phone) | Numbered rows. No hover |
ProjectRecentList |
Project Recent List | |
ProjectGallery |
Projects page Grid / List | Switch + ProjectCard grid or ProjectListItem list |
PostGrid |
Blog archive grid | 1 / 2 / 3 columns, Load More, 4 or 6 posts per page |
RichText |
— (Framer rich text) | Post body: headings 40 above, paragraphs and lists 20; numbered and nested lists, bold leads |
Slideshow, TestimonialSlideshow |
Testimonial Slide Show | Autoplay 5s, drag, keyboard |
Ticker |
— (Framer Ticker) | 30 px/s |
BigFooter |
Big Footer | “More Details” cursor |
Form |
— (Framer form) | Posts to a server action; shows pending / success / error on the Submit button; resets on success only; honeypot field honeypotField. Delivery: src/lib/forms |
CheckboxGroup |
— (Framer checkboxes) | Label + wrapping 16 px square checkboxes; every checked option is sent under one name |
FormField |
— (Framer input / textarea) | Label + 40 px input or 200 px message box; ink 3% fill, focus turns white |
SubmitButton |
Form (Default / Loading / Success / Error) | Full width; status prop |
Cursor |
Cursor (Dot / Active / View Project / Read / More Details) | Render once in the layout; use data-cursor="…" |
MotionProvider |
— | Honors reduced motion |
CurrentYear |
— | Always-current copyright year |
Cursor
Section titled “Cursor”<Cursor /> is rendered once in app/layout.tsx. Mark elements with data-cursor:
<Link href={href} data-cursor="view-project">…</Link> // also: "read", "more-details", "ring"Planned (add when the page that uses them is built, from the Framer page)
Section titled “Planned (add when the page that uses them is built, from the Framer page)”| Component | Figma name | Page |
|---|---|---|
SubmitButton |
Submit Button | Contact |
Play cursor |
Cursor / Play | Video blocks |