From 2fbf1f532d3ca2a18b9e546932c235d1332df375 Mon Sep 17 00:00:00 2001 From: Poyraz Avsever Date: Wed, 11 Mar 2026 10:00:20 +0300 Subject: [PATCH] content: update building-minimal-design-systems.md, deneme.md, blog-detail.ts (2026-03-11 07:00) --- .../blog/building-minimal-design-systems.md | 190 ++++++++++++++ content/blog/deneme.md | 10 + data/blog-detail.ts | 237 ++++-------------- 3 files changed, 252 insertions(+), 185 deletions(-) create mode 100644 content/blog/building-minimal-design-systems.md create mode 100644 content/blog/deneme.md diff --git a/content/blog/building-minimal-design-systems.md b/content/blog/building-minimal-design-systems.md new file mode 100644 index 0000000..c47dd02 --- /dev/null +++ b/content/blog/building-minimal-design-systems.md @@ -0,0 +1,190 @@ +--- +title: "Building Minimal Design Systems" +category: "React" +date: "March 2026" +readTime: "12 min read" +author: "Poyraz Avsever" +excerpt: "A practical and detailed playbook for building a clean, scalable UI system with markdown-driven documentation, mermaid diagrams, and implementation-ready code." +coverImage: "/news/design.svg" +--- + +## Why Most Design Systems Become Heavy + +Most teams start with good intentions and end up with too many variants, too many exceptions, and no clear usage guide. +The real problem is usually **decision sprawl**: + +- Too many size and style combinations +- Inconsistent naming conventions +- Documentation that explains props, but not decisions + +--- + +## Core Principle: Constrain First, Expand Later + +Start with a strict base: + +1. Typography scale +2. Spacing scale +3. Semantic colors +4. A handful of primitives + +> A design system is not a component museum. +> It is an agreement that helps teams ship consistent UI quickly. + +--- + +## Suggested Token Strategy + +```json +{ + "font": { + "size": { "sm": "0.875rem", "base": "1rem", "lg": "1.125rem" }, + "weight": { "regular": 400, "medium": 500, "bold": 700 } + }, + "space": { + "1": "0.25rem", + "2": "0.5rem", + "3": "0.75rem", + "4": "1rem", + "6": "1.5rem" + } +} +``` + +--- + +## Architecture Flow + +```mermaid +flowchart LR + A[Design Tokens] --> B[Primitives] + B --> C[Composed Components] + C --> D[Page Sections] + D --> E[Product Screens] +``` + +--- + +## Example: Button Primitive + +```tsx +import { cva } from "class-variance-authority"; + +const buttonVariants = cva( + "inline-flex items-center justify-center rounded-sm text-sm font-medium transition-colors", + { + variants: { + variant: { + default: "bg-primary text-primary-foreground", + outline: "border border-border bg-background", + ghost: "bg-transparent" + }, + size: { + sm: "h-8 px-3", + md: "h-9 px-4", + lg: "h-10 px-5" + } + }, + defaultVariants: { + variant: "default", + size: "md" + } + } +); +``` + +Why this works: + +- Variants are explicit +- Defaults are stable +- Consumers avoid ad-hoc class combinations + +--- + +## Documentation Pattern That Scales + +Instead of "prop-only docs", use this pattern for every component: + +### 1) When to use +Explain context and intent. + +### 2) Do / Don't +Show 2 positive and 2 negative examples. + +### 3) Accessibility checklist + +- Keyboard interaction +- Focus visibility +- ARIA coverage + +### 4) Code examples by complexity + +- Basic +- With validation +- With async state + +--- + +## Mermaid Sequence for Contribution Workflow + +```mermaid +sequenceDiagram + participant Dev as Developer + participant DS as Design System + participant App as Product App + + Dev->>DS: Add primitive or variant + DS-->>Dev: Exports + docs update + Dev->>App: Integrate component + App-->>Dev: UX feedback + Dev->>DS: Refine API +``` + +--- + +## Example: Page-Level Composition + +```tsx +export function BlogHeader() { + return ( +
+ React +

Building Minimal Design Systems

+

+ Practical notes from shipping real components. +

+
+ ); +} +``` + +--- + +## Common Failure Modes + +| Problem | Why it happens | Better approach | +|---|---|---| +| Variant explosion | No ownership rules | Add contribution guardrails | +| Styling overrides everywhere | Weak defaults | Strengthen semantic tokens | +| Inconsistent docs | No template | Use one markdown template | +| Slow adoption | API too abstract | Show direct usage examples | + +--- + +## Final Checklist Before Shipping a New Component + +- [ ] API is minimal and explicit +- [ ] States are documented (default, hover, focus, disabled, loading) +- [ ] Keyboard support verified +- [ ] Mobile rendering verified +- [ ] Real usage example added to docs + +--- + +## Closing Notes + +A minimal design system should feel boring in the best way. +When engineers can predict behavior, teams move faster with fewer regressions. + +Focus on **consistency, clarity, and constraints**. +Those three will outperform "feature-rich" component sets in the long run. diff --git a/content/blog/deneme.md b/content/blog/deneme.md new file mode 100644 index 0000000..e0cee23 --- /dev/null +++ b/content/blog/deneme.md @@ -0,0 +1,10 @@ +--- +title: deneme +category: General +date: Mart 2026 +readTime: 12 min read +author: Poyraz Avsever +excerpt: asdasdasdasd +coverImage: /news/design.svg +--- +asdasdasdasd diff --git a/data/blog-detail.ts b/data/blog-detail.ts index fec83b3..839a42a 100644 --- a/data/blog-detail.ts +++ b/data/blog-detail.ts @@ -1,3 +1,7 @@ +import fs from "node:fs/promises"; +import path from "node:path"; +import matter from "gray-matter"; + export type BlogDetail = { slug: string; title: string; @@ -10,202 +14,65 @@ export type BlogDetail = { markdown: string; }; -export const BLOG_DETAILS: BlogDetail[] = [ - { - slug: "building-minimal-design-systems", - title: "Building Minimal Design Systems", - category: "React", - date: "March 2026", - readTime: "12 min read", - author: "Poyraz Avsever", - excerpt: - "A practical and detailed playbook for building a clean, scalable UI system with markdown-driven documentation, mermaid diagrams, and implementation-ready code.", - coverImage: "/news/design.svg", - markdown: ` -## Why Most Design Systems Become Heavy +const BLOG_CONTENT_DIR = path.join(process.cwd(), "content", "blog"); -Most teams start with good intentions and end up with too many variants, too many exceptions, and no clear usage guide. -The real problem is usually **decision sprawl**: - -- Too many size and style combinations -- Inconsistent naming conventions -- Documentation that explains props, but not decisions - ---- - -## Core Principle: Constrain First, Expand Later - -Start with a strict base: - -1. Typography scale -2. Spacing scale -3. Semantic colors -4. A handful of primitives - -> A design system is not a component museum. -> It is an agreement that helps teams ship consistent UI quickly. - ---- - -## Suggested Token Strategy - -\`\`\`json -{ - "font": { - "size": { "sm": "0.875rem", "base": "1rem", "lg": "1.125rem" }, - "weight": { "regular": 400, "medium": 500, "bold": 700 } - }, - "space": { - "1": "0.25rem", - "2": "0.5rem", - "3": "0.75rem", - "4": "1rem", - "6": "1.5rem" - } +function toSafeString(value: unknown, fallback: string) { + if (typeof value !== "string") return fallback; + const trimmed = value.trim(); + return trimmed || fallback; } -\`\`\` ---- +function normalizeSlug(fileName: string) { + return fileName.replace(/\.md$/i, ""); +} -## Architecture Flow +function mapMarkdownToBlogDetail(fileName: string, raw: string): BlogDetail { + const parsed = matter(raw); + const slug = normalizeSlug(fileName); -\`\`\`mermaid -flowchart LR - A[Design Tokens] --> B[Primitives] - B --> C[Composed Components] - C --> D[Page Sections] - D --> E[Product Screens] -\`\`\` + return { + slug, + title: toSafeString(parsed.data.title, slug), + category: toSafeString(parsed.data.category, "General"), + date: toSafeString(parsed.data.date, ""), + readTime: toSafeString(parsed.data.readTime, ""), + author: toSafeString(parsed.data.author, "Poyraz Avsever"), + excerpt: toSafeString(parsed.data.excerpt, ""), + coverImage: toSafeString(parsed.data.coverImage, "/news/design.svg"), + markdown: parsed.content.trim(), + }; +} ---- - -## Example: Button Primitive - -\`\`\`tsx -import { cva } from "class-variance-authority"; - -const buttonVariants = cva( - "inline-flex items-center justify-center rounded-sm text-sm font-medium transition-colors", - { - variants: { - variant: { - default: "bg-primary text-primary-foreground", - outline: "border border-border bg-background", - ghost: "bg-transparent" - }, - size: { - sm: "h-8 px-3", - md: "h-9 px-4", - lg: "h-10 px-5" - } - }, - defaultVariants: { - variant: "default", - size: "md" - } +export async function listBlogDetails(): Promise { + let files: string[] = []; + try { + files = await fs.readdir(BLOG_CONTENT_DIR); + } catch { + return []; } -); -\`\`\` -Why this works: - -- Variants are explicit -- Defaults are stable -- Consumers avoid ad-hoc class combinations - ---- - -## Documentation Pattern That Scales - -Instead of “prop-only docs”, use this pattern for every component: - -### 1) When to use -Explain context and intent. - -### 2) Do / Don't -Show 2 positive and 2 negative examples. - -### 3) Accessibility checklist - -- Keyboard interaction -- Focus visibility -- ARIA coverage - -### 4) Code examples by complexity - -- Basic -- With validation -- With async state - ---- - -## Mermaid Sequence for Contribution Workflow - -\`\`\`mermaid -sequenceDiagram - participant Dev as Developer - participant DS as Design System - participant App as Product App - - Dev->>DS: Add primitive or variant - DS-->>Dev: Exports + docs update - Dev->>App: Integrate component - App-->>Dev: UX feedback - Dev->>DS: Refine API -\`\`\` - ---- - -## Example: Page-Level Composition - -\`\`\`tsx -export function BlogHeader() { - return ( -
- React -

Building Minimal Design Systems

-

- Practical notes from shipping real components. -

-
+ const markdownFiles = files.filter((fileName) => fileName.endsWith(".md")); + const posts = await Promise.all( + markdownFiles.map(async (fileName) => { + const targetPath = path.join(BLOG_CONTENT_DIR, fileName); + const raw = await fs.readFile(targetPath, "utf8"); + return mapMarkdownToBlogDetail(fileName, raw); + }), ); + + return posts.sort((a, b) => a.slug.localeCompare(b.slug)); } -\`\`\` ---- +export async function getBlogDetailBySlug(slug: string): Promise { + const safeSlug = slug.trim().toLowerCase(); + if (!safeSlug) return null; -## Common Failure Modes + const targetPath = path.join(BLOG_CONTENT_DIR, `${safeSlug}.md`); -| Problem | Why it happens | Better approach | -|---|---|---| -| Variant explosion | No ownership rules | Add contribution guardrails | -| Styling overrides everywhere | Weak defaults | Strengthen semantic tokens | -| Inconsistent docs | No template | Use one markdown template | -| Slow adoption | API too abstract | Show direct usage examples | - ---- - -## Final Checklist Before Shipping a New Component - -- [ ] API is minimal and explicit -- [ ] States are documented (default, hover, focus, disabled, loading) -- [ ] Keyboard support verified -- [ ] Mobile rendering verified -- [ ] Real usage example added to docs - ---- - -## Closing Notes - -A minimal design system should feel boring in the best way. -When engineers can predict behavior, teams move faster with fewer regressions. - -Focus on **consistency, clarity, and constraints**. -Those three will outperform “feature-rich” component sets in the long run. -`, - }, -] as const; - -export function getBlogDetailBySlug(slug: string) { - return BLOG_DETAILS.find((post) => post.slug === slug) ?? null; + try { + const raw = await fs.readFile(targetPath, "utf8"); + return mapMarkdownToBlogDetail(`${safeSlug}.md`, raw); + } catch { + return null; + } }