astro — 1thay documentation site
build target:
1thay.com· deploy: cloudflare pages · linked files: 1thay.md, design-tokens.md, storybook.md, CLAUDE.md
overview
astro builds the 1thay design system documentation site. it uses react components from src/components/, design tokens from src/tokens/, and follows conventions from 1thay.md.
site structure: home hub → foundations → components → patterns
project config
astro.config.mjs
import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
export default defineConfig({
integrations: [react()],
output: 'static',
site: 'https://1thay.com',
});
package.json scripts
{
"dev": "astro dev",
"build": "astro build",
"preview": "astro preview",
"lint": "astro check",
"sync": "astro sync"
}
deploy
| setting | value |
|---|---|
| platform | cloudflare pages |
| repo | kien-day/1thay-com |
| branch | main |
| framework | astro |
| build command | npm run build |
| output directory | dist/ |
| domain | 1thay.com |
| preview | 1thay-com.pages.dev |
directory structure
src/
├── tokens/ # design-tokens.md — single source of truth
│ ├── tokens.css imported by both astro + storybook
│ └── tokens.js js export (storybook theme)
├── components/ # react components — shared with storybook.md
│ ├── Button/
│ ├── Card/
│ ├── Input/
│ └── Icon/
├── layouts/
│ ├── BaseLayout.astro # root layout: fonts, global css, <html>/<head>/<body>
│ └── DocsLayout.astro # documentation layout: sidebar nav + content
├── pages/
│ ├── index.astro # home hub — links to all 3 sections
│ ├── foundations/
│ │ ├── index.astro # overview + card links
│ │ ├── colors.astro # brand palettes + neutral + semantic
│ │ ├── typography.astro # 4 fonts + type scale + weights
│ │ ├── spacing.astro # spacing, radius, shadows, opacity, z, sizes
│ │ └── iconography.astro# lucide (line) + carbon (fill) demo
│ ├── components/
│ │ ├── index.astro # overview + card links
│ │ ├── button.astro # variants, sizes, states, tokens
│ │ ├── card.astro # variants, anatomy, tokens
│ │ └── input.astro # sizes, label/helper, validation, tokens
│ └── patterns/
│ ├── index.astro # overview + card links
│ ├── signup.astro # single-step + multi-step flow
│ ├── layout.astro # dashboard, bento, sidebar, centered
│ ├── navigation.astro # top nav, sidebar, breadcrumbs, tabs
│ └── data-visualize.astro # metric cards, chart layout, principles
└── styles/
└── global.css # base reset + token import + typography defaults
layout system
BaseLayout
wraps every page. provides:
<html lang="vi">+ charset + viewport- google fonts preconnect + link (Hanken Grotesk, Inter, Merriweather, Space Grotesk)
<title>via slot/head propagation- imports
src/styles/global.csswhich importssrc/tokens/tokens.css - top navbar (56px, sticky): logo "1thay" → foundations | components | patterns + storybook/github links
- active section auto-detected from
Astro.url.pathname - external links marked with
↗ - responsive: external links hidden on mobile
- active section auto-detected from
<slot />for page content
DocsLayout
extends BaseLayout for documentation pages. provides:
- sidebar (260px, sticky,
--surface-dimbackground)- logo link to
/ - foundations group: overview, colors, typography, spacing, iconography
- components group: overview, button, card, input
- patterns group: overview, signup, layout, navigation, data viz
- footer: storybook + github links
- logo link to
- content area (flex 1, max-width 960px, padding
--space-3xl)<h1>fromtitleprop with bottom border<slot />for page content
- responsive: sidebar collapses to top on mobile (< 768px)
props:
interface Props {
title: string; // h1 content
section: 'foundations' | 'components' | 'patterns'; // active nav section
}
component rules
react components in astro
- react components receive react-style props (camelCase, style objects), not html-style
- critical: never pass string
styleprop to react components in astro — it expectsstyle={{...}} - for layout spacing, wrap react components in astro
<div style="...">elements - use
client:loaddirective for interactive components (Input)
page conventions
- each documentation page imports
DocsLayoutand setstitle+section - token values displayed as code blocks:
<code>value</code> - visual demos use live tokens via css custom properties
- pages are static — no client-side js except for interactive components
adding a new foundation page
- create
src/pages/foundations/name.astro - add to
DocsLayout.astrosidebar under foundations group - add card link to
src/pages/foundations/index.astro - update this file and
project-logs.md
adding a new component page
- build component in storybook first (see
storybook.md) - create
src/pages/components/name.astro - add to
DocsLayout.astrosidebar under components group - add card link to
src/pages/components/index.astro - update this file and
project-logs.md
adding a new pattern page
- create
src/pages/patterns/name.astro - add to
DocsLayout.astrosidebar under patterns group - add card link to
src/pages/patterns/index.astro - update this file and
project-logs.md
fonts
all fonts loaded via google fonts in BaseLayout.astro:
| family | weights | css variable | use |
|---|---|---|---|
| Hanken Grotesk | 600, 700 | --font-display |
hero, h1-h4 |
| Inter | 400, 500 | --font-text |
body, ui, labels |
| Merriweather | 400 | --font-content |
long-form reading |
| Space Grotesk | 500, 600 | --font-number |
data, metrics |
icons
| set | package | type | use |
|---|---|---|---|
| lucide | lucide-react |
line stroke | function, navigation, modules |
| carbon | @carbon/icons-react |
shape fill | data, mini actions |
wrapper components in src/components/Icon/:
<Icon>— lucide line icons, 4 sizes (sm/md/lg/xl)<IconFill>— carbon fill icons, 4 sizes
linked references
- 1thay.md — philosophy, naming conventions, decision-making
- design.md — google labs spec (machine-readable)
- design-tokens.md — complete token definitions
- figma.md — figma file setup, variable conventions, sync workflow
- storybook.md — storybook setup and component patterns
- project-logs.md — decision log, changelog, roadmap
- CLAUDE.md — claude code agent configuration