diff --git a/.gitignore b/.gitignore
index 66d9451..d4db458 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,4 @@
-node_modules
-generated
-convert.ts
-/cssforge.config.ts
-/.cssforge
-TODO.md
\ No newline at end of file
+.vitepress/cache
+.vitepress/dist
+.cssforge
+docs.md
diff --git a/.vitepress/config.ts b/.vitepress/config.ts
new file mode 100644
index 0000000..5329887
--- /dev/null
+++ b/.vitepress/config.ts
@@ -0,0 +1,33 @@
+import { defineConfig } from "vitepress";
+
+export default defineConfig({
+ title: "CSS Forge",
+ description:
+ "0 runtime design tokens generator for modern style systems.",
+ appearance: "dark",
+ markdown: {
+ theme: "github-dark",
+ },
+ themeConfig: {
+ nav: [
+ { text: "Guide", link: "/docs" },
+ {
+ text: "JSR",
+ link: "https://jsr.io/@hebilicious/cssforge",
+ },
+ {
+ text: "GitHub",
+ link: "https://github.com/Hebilicious/cssforge",
+ },
+ ],
+ search: { provider: "local" },
+ editLink: {
+ pattern:
+ "https://github.com/Hebilicious/cssforge/edit/main/packages/docs/:path",
+ },
+ footer: {
+ message: "Released under the MIT License.",
+ copyright: "Copyright Hebilicious",
+ },
+ },
+});
diff --git a/.vitepress/theme/AnvilAnimation.vue b/.vitepress/theme/AnvilAnimation.vue
new file mode 100644
index 0000000..337801d
--- /dev/null
+++ b/.vitepress/theme/AnvilAnimation.vue
@@ -0,0 +1,310 @@
+
+
+
+
+
+
+
diff --git a/.vitepress/theme/custom.css b/.vitepress/theme/custom.css
new file mode 100644
index 0000000..501c0da
--- /dev/null
+++ b/.vitepress/theme/custom.css
@@ -0,0 +1,469 @@
+@import "../../.cssforge/output.css" layer(cssforge);
+
+/* ============================================================
+ CSSForge Docs — Full Cyberpunk Theme
+ All colors sourced from the anvil animation palette via
+ cssforge-generated --palette-forge-* tokens.
+ ============================================================ */
+
+/* ----- Typography ----- */
+
+@font-face {
+ font-family: "Geist Mono";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.4.1/dist/fonts/geist-mono/GeistMono-Regular.woff2")
+ format("woff2");
+ font-weight: 400;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Geist Mono";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.4.1/dist/fonts/geist-mono/GeistMono-Medium.woff2")
+ format("woff2");
+ font-weight: 500;
+ font-style: normal;
+ font-display: swap;
+}
+
+@font-face {
+ font-family: "Geist Mono";
+ src: url("https://cdn.jsdelivr.net/npm/geist@1.4.1/dist/fonts/geist-mono/GeistMono-Bold.woff2")
+ format("woff2");
+ font-weight: 700;
+ font-style: normal;
+ font-display: swap;
+}
+
+/* ----- Root: Force dark everywhere ----- */
+
+:root {
+ /* Font */
+ --vp-font-family-base: "Geist Mono", "Courier New", Courier, monospace;
+ --vp-font-family-mono: "Geist Mono", "Courier New", Courier, monospace;
+
+ /* Core palette — anvil metals */
+ --vp-c-gray-1: var(--palette-forge-metal-8);
+ --vp-c-gray-2: var(--palette-forge-metal-6);
+ --vp-c-gray-3: var(--palette-forge-metal-5);
+ --vp-c-gray-soft: rgba(85, 85, 104, 0.16);
+
+ /* Background — deep void / space */
+ --vp-c-bg: var(--palette-forge-void);
+ --vp-c-bg-alt: var(--palette-forge-metal-1);
+ --vp-c-bg-elv: var(--palette-forge-metal-2);
+ --vp-c-bg-soft: var(--palette-forge-metal-2);
+
+ /* Text — light on dark */
+ --vp-c-text-1: var(--palette-forge-text-1);
+ --vp-c-text-2: var(--palette-forge-text-2);
+ --vp-c-text-3: var(--palette-forge-text-3);
+
+ /* Borders — subtle metal edges */
+ --vp-c-border: var(--palette-forge-metal-5);
+ --vp-c-divider: var(--palette-forge-metal-4);
+ --vp-c-gutter: var(--palette-forge-metal-1);
+
+ /* Neutral */
+ --vp-c-neutral: var(--palette-forge-white);
+ --vp-c-neutral-inverse: var(--palette-forge-void);
+
+ /* Brand — cyan primary */
+ --vp-c-brand-1: var(--palette-forge-cyan);
+ --vp-c-brand-2: var(--palette-forge-cyan);
+ --vp-c-brand-3: var(--palette-forge-cyan);
+ --vp-c-brand-soft: rgba(0, 243, 255, 0.12);
+ --vp-c-brand: var(--palette-forge-cyan);
+
+ /* Tip / Note — cyan */
+ --vp-c-tip-1: var(--palette-forge-cyan);
+ --vp-c-tip-2: var(--palette-forge-cyan);
+ --vp-c-tip-3: var(--palette-forge-cyan);
+ --vp-c-tip-soft: rgba(0, 243, 255, 0.08);
+ --vp-c-note-1: var(--palette-forge-cyan);
+ --vp-c-note-2: var(--palette-forge-cyan);
+ --vp-c-note-3: var(--palette-forge-cyan);
+ --vp-c-note-soft: rgba(0, 243, 255, 0.08);
+
+ /* Important — magenta */
+ --vp-c-important-1: var(--palette-forge-magenta);
+ --vp-c-important-2: var(--palette-forge-magenta);
+ --vp-c-important-3: var(--palette-forge-magenta);
+ --vp-c-important-soft: rgba(255, 0, 160, 0.1);
+
+ /* Warning — keep yellow-ish but tinted */
+ --vp-c-warning-1: #f9b44e;
+ --vp-c-warning-2: #da8b17;
+ --vp-c-warning-3: #a46a0a;
+ --vp-c-warning-soft: rgba(234, 179, 8, 0.1);
+
+ /* Danger / Caution — magenta tint */
+ --vp-c-danger-1: var(--palette-forge-magenta);
+ --vp-c-danger-2: var(--palette-forge-magenta);
+ --vp-c-danger-3: var(--palette-forge-magenta);
+ --vp-c-danger-soft: rgba(255, 0, 160, 0.08);
+ --vp-c-caution-1: var(--palette-forge-magenta);
+ --vp-c-caution-2: var(--palette-forge-magenta);
+ --vp-c-caution-3: var(--palette-forge-magenta);
+ --vp-c-caution-soft: rgba(255, 0, 160, 0.08);
+
+ /* Success — cyan */
+ --vp-c-success-1: var(--palette-forge-cyan);
+ --vp-c-success-2: var(--palette-forge-cyan);
+ --vp-c-success-3: var(--palette-forge-cyan);
+ --vp-c-success-soft: rgba(0, 243, 255, 0.08);
+
+ /* Default (hover states) */
+ --vp-c-default-1: var(--palette-forge-metal-8);
+ --vp-c-default-2: var(--palette-forge-metal-6);
+ --vp-c-default-3: var(--palette-forge-metal-5);
+ --vp-c-default-soft: rgba(85, 85, 104, 0.12);
+
+ /* Sponsor */
+ --vp-c-sponsor: var(--palette-forge-magenta);
+
+ /* Shadows — deeper, tinted */
+ --vp-shadow-1: 0 1px 2px rgba(0, 0, 0, 0.3), 0 1px 2px rgba(0, 0, 0, 0.4);
+ --vp-shadow-2: 0 3px 12px rgba(0, 0, 0, 0.4), 0 1px 4px rgba(0, 0, 0, 0.3);
+ --vp-shadow-3: 0 12px 32px rgba(0, 0, 0, 0.5), 0 2px 6px rgba(0, 0, 0, 0.4);
+ --vp-shadow-4: 0 14px 44px rgba(0, 0, 0, 0.6), 0 3px 9px rgba(0, 0, 0, 0.5);
+ --vp-shadow-5: 0 18px 56px rgba(0, 0, 0, 0.7), 0 4px 12px rgba(0, 0, 0, 0.6);
+
+ /* Code */
+ --vp-code-color: var(--palette-forge-cyan);
+ --vp-code-link-color: var(--palette-forge-cyan);
+ --vp-code-link-hover-color: var(--palette-forge-magenta);
+ --vp-code-bg: rgba(0, 243, 255, 0.06);
+ --vp-code-block-color: var(--palette-forge-text-2);
+ --vp-code-block-bg: var(--palette-forge-metal-1);
+ --vp-code-block-divider-color: var(--palette-forge-metal-4);
+ --vp-code-lang-color: var(--palette-forge-text-3);
+ --vp-code-line-highlight-color: rgba(0, 243, 255, 0.06);
+ --vp-code-line-number-color: var(--palette-forge-text-3);
+ --vp-code-copy-code-border-color: var(--palette-forge-metal-5);
+ --vp-code-copy-code-bg: var(--palette-forge-metal-3);
+ --vp-code-copy-code-hover-border-color: var(--palette-forge-cyan);
+ --vp-code-copy-code-hover-bg: var(--palette-forge-metal-4);
+ --vp-code-copy-code-active-text: var(--palette-forge-cyan);
+ --vp-code-tab-divider: var(--palette-forge-metal-4);
+ --vp-code-tab-text-color: var(--palette-forge-text-2);
+ --vp-code-tab-bg: var(--palette-forge-metal-1);
+ --vp-code-tab-hover-text-color: var(--palette-forge-text-1);
+ --vp-code-tab-active-text-color: var(--palette-forge-cyan);
+ --vp-code-tab-active-bar-color: var(--palette-forge-cyan);
+
+ /* Buttons */
+ --vp-button-brand-border: var(--palette-forge-cyan);
+ --vp-button-brand-text: var(--palette-forge-void);
+ --vp-button-brand-bg: var(--palette-forge-cyan);
+ --vp-button-brand-hover-border: var(--palette-forge-magenta);
+ --vp-button-brand-hover-text: var(--palette-forge-white);
+ --vp-button-brand-hover-bg: var(--palette-forge-magenta);
+ --vp-button-brand-active-border: var(--palette-forge-magenta);
+ --vp-button-brand-active-text: var(--palette-forge-white);
+ --vp-button-brand-active-bg: var(--palette-forge-magenta);
+
+ --vp-button-alt-border: var(--palette-forge-metal-7);
+ --vp-button-alt-text: var(--palette-forge-text-1);
+ --vp-button-alt-bg: var(--palette-forge-metal-3);
+ --vp-button-alt-hover-border: var(--palette-forge-cyan);
+ --vp-button-alt-hover-text: var(--palette-forge-cyan);
+ --vp-button-alt-hover-bg: var(--palette-forge-metal-4);
+ --vp-button-alt-active-border: var(--palette-forge-cyan);
+ --vp-button-alt-active-text: var(--palette-forge-cyan);
+ --vp-button-alt-active-bg: var(--palette-forge-metal-5);
+
+ /* Custom blocks */
+ --vp-custom-block-info-border: var(--palette-forge-metal-5);
+ --vp-custom-block-info-text: var(--palette-forge-text-1);
+ --vp-custom-block-info-bg: var(--palette-forge-metal-2);
+ --vp-custom-block-info-code-bg: var(--palette-forge-metal-3);
+ --vp-custom-block-note-border: var(--palette-forge-metal-5);
+ --vp-custom-block-note-text: var(--palette-forge-text-1);
+ --vp-custom-block-note-bg: var(--palette-forge-metal-2);
+ --vp-custom-block-note-code-bg: var(--palette-forge-metal-3);
+ --vp-custom-block-tip-border: rgba(0, 243, 255, 0.3);
+ --vp-custom-block-tip-text: var(--palette-forge-text-1);
+ --vp-custom-block-tip-bg: rgba(0, 243, 255, 0.05);
+ --vp-custom-block-tip-code-bg: rgba(0, 243, 255, 0.08);
+ --vp-custom-block-important-border: rgba(255, 0, 160, 0.3);
+ --vp-custom-block-important-text: var(--palette-forge-text-1);
+ --vp-custom-block-important-bg: rgba(255, 0, 160, 0.06);
+ --vp-custom-block-important-code-bg: rgba(255, 0, 160, 0.08);
+ --vp-custom-block-warning-border: rgba(234, 179, 8, 0.3);
+ --vp-custom-block-warning-text: var(--palette-forge-text-1);
+ --vp-custom-block-warning-bg: rgba(234, 179, 8, 0.06);
+ --vp-custom-block-warning-code-bg: rgba(234, 179, 8, 0.08);
+ --vp-custom-block-danger-border: rgba(255, 0, 160, 0.3);
+ --vp-custom-block-danger-text: var(--palette-forge-text-1);
+ --vp-custom-block-danger-bg: rgba(255, 0, 160, 0.06);
+ --vp-custom-block-danger-code-bg: rgba(255, 0, 160, 0.08);
+ --vp-custom-block-caution-border: rgba(255, 0, 160, 0.3);
+ --vp-custom-block-caution-text: var(--palette-forge-text-1);
+ --vp-custom-block-caution-bg: rgba(255, 0, 160, 0.06);
+ --vp-custom-block-caution-code-bg: rgba(255, 0, 160, 0.08);
+
+ /* Input / search */
+ --vp-input-border-color: var(--palette-forge-metal-5);
+ --vp-input-bg-color: var(--palette-forge-metal-2);
+ --vp-input-switch-bg-color: var(--palette-forge-metal-4);
+
+ /* Nav */
+ --vp-nav-bg-color: rgba(3, 2, 6, 0.85);
+ --vp-nav-screen-bg-color: var(--palette-forge-void);
+ --vp-nav-logo-height: 28px;
+
+ /* Local nav */
+ --vp-local-nav-bg-color: rgba(3, 2, 6, 0.85);
+
+ /* Sidebar */
+ --vp-sidebar-bg-color: var(--palette-forge-metal-1);
+
+ /* Backdrop */
+ --vp-backdrop-bg-color: rgba(3, 2, 6, 0.7);
+
+ /* Home */
+ --vp-home-hero-name-color: transparent;
+ --vp-home-hero-name-background: linear-gradient(
+ 135deg,
+ var(--palette-forge-cyan) 0%,
+ var(--palette-forge-magenta) 100%
+ );
+ --vp-home-hero-image-background-image: radial-gradient(
+ circle at 50% 50%,
+ rgba(0, 243, 255, 0.15) 0%,
+ transparent 70%
+ );
+ --vp-home-hero-image-filter: none;
+
+ /* Search */
+ --vp-local-search-bg: var(--palette-forge-metal-1);
+ --vp-local-search-result-bg: var(--palette-forge-metal-2);
+ --vp-local-search-result-border: var(--palette-forge-metal-5);
+ --vp-local-search-result-selected-bg: var(--palette-forge-metal-3);
+ --vp-local-search-result-selected-border: var(--palette-forge-cyan);
+ --vp-local-search-highlight-bg: var(--palette-forge-cyan);
+ --vp-local-search-highlight-text: var(--palette-forge-void);
+
+ /* Badge */
+ --vp-badge-info-border: var(--palette-forge-metal-5);
+ --vp-badge-info-text: var(--palette-forge-text-2);
+ --vp-badge-info-bg: var(--palette-forge-metal-3);
+ --vp-badge-tip-border: rgba(0, 243, 255, 0.3);
+ --vp-badge-tip-text: var(--palette-forge-cyan);
+ --vp-badge-tip-bg: rgba(0, 243, 255, 0.1);
+ --vp-badge-warning-border: rgba(234, 179, 8, 0.3);
+ --vp-badge-warning-text: #f9b44e;
+ --vp-badge-warning-bg: rgba(234, 179, 8, 0.1);
+ --vp-badge-danger-border: rgba(255, 0, 160, 0.3);
+ --vp-badge-danger-text: var(--palette-forge-magenta);
+ --vp-badge-danger-bg: rgba(255, 0, 160, 0.1);
+
+ color-scheme: dark;
+}
+
+/* Force dark mode class — disable light mode entirely */
+.dark {
+ --vp-c-bg: var(--palette-forge-void);
+ --vp-c-bg-alt: var(--palette-forge-metal-1);
+ --vp-c-bg-elv: var(--palette-forge-metal-2);
+ --vp-c-bg-soft: var(--palette-forge-metal-2);
+}
+
+/* ----- Nav bar ----- */
+
+.VPNav > .VPNavBar {
+ background: transparent !important;
+}
+
+.VPNavBar {
+ border-bottom: 1px solid var(--palette-forge-metal-4) !important;
+ backdrop-filter: blur(16px);
+}
+
+.VPNavBar .title {
+ color: var(--palette-forge-cyan) !important;
+ font-weight: 700;
+ letter-spacing: 0.05em;
+ text-transform: uppercase;
+}
+
+.VPNavBarMenuLink {
+ color: var(--palette-forge-text-2) !important;
+ transition: color 0.2s;
+}
+
+.VPNavBarMenuLink:hover,
+.VPNavBarMenuLink.active {
+ color: var(--palette-forge-cyan) !important;
+}
+
+/* ----- Sidebar ----- */
+
+.VPSidebar {
+ border-right: 1px solid var(--palette-forge-metal-4) !important;
+}
+
+/* ----- Links ----- */
+
+.vp-doc a {
+ color: var(--palette-forge-cyan);
+ text-decoration-color: rgba(0, 243, 255, 0.3);
+ transition: color 0.2s, text-decoration-color 0.2s;
+}
+
+.vp-doc a:hover {
+ color: var(--palette-forge-magenta);
+ text-decoration-color: var(--palette-forge-magenta);
+}
+
+/* ----- Headings ----- */
+
+.vp-doc h1,
+.vp-doc h2,
+.vp-doc h3 {
+ color: var(--palette-forge-white);
+}
+
+.vp-doc h1 {
+ background: linear-gradient(
+ 90deg,
+ var(--palette-forge-cyan),
+ var(--palette-forge-magenta)
+ );
+ background-clip: text;
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+}
+
+.vp-doc h2 {
+ border-top: 1px solid var(--palette-forge-metal-4);
+}
+
+/* ----- Code blocks ----- */
+
+div[class*="language-"] {
+ border: 1px solid var(--palette-forge-metal-4);
+}
+
+.vp-doc :not(pre) > code {
+ color: var(--palette-forge-cyan);
+ background: rgba(0, 243, 255, 0.08);
+}
+
+/* ----- Home hero ----- */
+
+.VPHero .name {
+ font-weight: 900 !important;
+ letter-spacing: 0.04em;
+}
+
+.VPHero .text {
+ color: var(--palette-forge-text-1) !important;
+}
+
+.VPHero .tagline {
+ color: var(--palette-forge-text-2) !important;
+}
+
+/* ----- Feature cards ----- */
+
+.VPFeature {
+ background: var(--palette-forge-metal-2) !important;
+ border: 1px solid var(--palette-forge-metal-5) !important;
+ transition: border-color 0.3s, box-shadow 0.3s;
+}
+
+.VPFeature:hover {
+ border-color: var(--palette-forge-cyan) !important;
+ box-shadow: 0 0 20px rgba(0, 243, 255, 0.1);
+}
+
+.VPFeature .title {
+ color: var(--palette-forge-white) !important;
+}
+
+.VPFeature .details {
+ color: var(--palette-forge-text-2) !important;
+}
+
+/* ----- Footer ----- */
+
+.VPFooter {
+ border-top: 1px solid var(--palette-forge-metal-4) !important;
+ background: var(--palette-forge-metal-1) !important;
+}
+
+.VPFooter .message,
+.VPFooter .copyright {
+ color: var(--palette-forge-text-3) !important;
+}
+
+/* ----- Outline (right TOC) ----- */
+
+.VPDocAsideOutline .outline-link {
+ color: var(--palette-forge-text-3);
+ transition: color 0.2s;
+}
+
+.VPDocAsideOutline .outline-link:hover,
+.VPDocAsideOutline .outline-link.active {
+ color: var(--palette-forge-cyan);
+}
+
+.VPDocAsideOutline .outline-marker {
+ background-color: var(--palette-forge-cyan) !important;
+}
+
+/* ----- Doc footer (prev/next) ----- */
+
+.VPDocFooter .pager-link {
+ border: 1px solid var(--palette-forge-metal-5);
+ background: var(--palette-forge-metal-2);
+ transition: border-color 0.2s;
+}
+
+.VPDocFooter .pager-link:hover {
+ border-color: var(--palette-forge-cyan);
+}
+
+.VPDocFooter .pager-link .title {
+ color: var(--palette-forge-text-2);
+}
+
+.VPDocFooter .pager-link .desc {
+ color: var(--palette-forge-cyan);
+}
+
+/* ----- Scrollbar ----- */
+
+::-webkit-scrollbar {
+ width: 8px;
+ height: 8px;
+}
+
+::-webkit-scrollbar-track {
+ background: var(--palette-forge-metal-1);
+}
+
+::-webkit-scrollbar-thumb {
+ background: var(--palette-forge-metal-6);
+ border-radius: 4px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: var(--palette-forge-cyan);
+}
+
+/* ----- Selection ----- */
+
+::selection {
+ background: rgba(0, 243, 255, 0.25);
+ color: var(--palette-forge-white);
+}
+
+/* ----- Hide appearance toggle (always dark) ----- */
+
+.VPSwitchAppearance {
+ display: none !important;
+}
diff --git a/.vitepress/theme/index.ts b/.vitepress/theme/index.ts
new file mode 100644
index 0000000..73d6f75
--- /dev/null
+++ b/.vitepress/theme/index.ts
@@ -0,0 +1,13 @@
+import { h } from "vue";
+import DefaultTheme from "vitepress/theme-without-fonts";
+import AnvilAnimation from "./AnvilAnimation.vue";
+import "./custom.css";
+
+export default {
+ extends: DefaultTheme,
+ Layout() {
+ return h(DefaultTheme.Layout, null, {
+ "home-hero-image": () => h(AnvilAnimation),
+ });
+ },
+};
diff --git a/cssforge.config.ts b/cssforge.config.ts
new file mode 100644
index 0000000..8c769de
--- /dev/null
+++ b/cssforge.config.ts
@@ -0,0 +1,72 @@
+import { defineConfig } from "@hebilicious/cssforge";
+
+export default defineConfig({
+ colors: {
+ palette: {
+ value: {
+ forge: {
+ value: {
+ // Anvil neon accents
+ cyan: "#00f3ff",
+ magenta: "#ff00a0",
+
+ // Backgrounds
+ void: "#030206",
+ space: "#140d26",
+ "space-light": "#1c1333",
+
+ // Metal surfaces
+ "metal-1": "#08080c",
+ "metal-2": "#111118",
+ "metal-3": "#15151c",
+ "metal-4": "#1a1a24",
+ "metal-5": "#2a2a35",
+ "metal-6": "#2b2b3a",
+ "metal-7": "#3b3b4f",
+ "metal-8": "#44445c",
+ "metal-9": "#555568",
+ "metal-10": "#6a6a82",
+
+ // Text
+ white: "#ffffff",
+ "text-1": "#e0e0f0",
+ "text-2": "#8888aa",
+ "text-3": "#555570",
+ },
+ },
+ },
+ },
+ },
+ spacing: {
+ fluid: {
+ space: {
+ value: {
+ minSize: 4,
+ maxSize: 24,
+ minWidth: 320,
+ maxWidth: 1280,
+ negativeSteps: [0],
+ positiveSteps: [2, 3, 4, 5],
+ prefix: "space",
+ },
+ },
+ },
+ },
+ typography: {
+ fluid: {
+ docs: {
+ value: {
+ minWidth: 320,
+ minFontSize: 15,
+ minTypeScale: 1.2,
+ maxWidth: 1280,
+ maxFontSize: 18,
+ maxTypeScale: 1.25,
+ negativeSteps: 1,
+ positiveSteps: 3,
+ prefix: "text",
+ },
+ },
+ },
+ },
+});
diff --git a/index.md b/index.md
new file mode 100644
index 0000000..4b948a2
--- /dev/null
+++ b/index.md
@@ -0,0 +1,37 @@
+---
+layout: home
+hero:
+ name: CSS Forge
+ text: Design tokens for modern CSS
+ tagline: 0 runtime design tokens generator for modern style systems.
+ image:
+ light: /placeholder
+ dark: /placeholder
+ alt: CSS Forge Anvil
+ actions:
+ - theme: brand
+ text: Get Started
+ link: /docs#quick-start
+ - theme: alt
+ text: View on GitHub
+ link: https://github.com/Hebilicious/cssforge
+features:
+ - title: Colors
+ details: Create palettes, gradients and themes. Automatically convert to OKLCH.
+ icon: "\U0001F3A8"
+ - title: Typography
+ details: Generate fluid typography scales with clamp-based responsive sizing.
+ icon: "\U0001F4D0"
+ - title: Spacing
+ details: Organize spacing utilities with fluid and custom scales.
+ icon: "\U0001F4CF"
+ - title: Primitives
+ details: Define custom design tokens for any CSS property.
+ icon: "\U0001F4E6"
+ - title: Zero Runtime
+ details: All processing happens at build time. Ship raw CSS, TypeScript, or JSON.
+ icon: "\U0001F3AF"
+ - title: Framework Agnostic
+ details: Use with any CSS workflow — Tailwind, vanilla CSS, or your own system.
+ icon: "\U0001F50C"
+---
diff --git a/moon.yml b/moon.yml
new file mode 100644
index 0000000..f6fe19a
--- /dev/null
+++ b/moon.yml
@@ -0,0 +1,70 @@
+$schema: "https://moonrepo.dev/schemas/v2/project.json"
+
+language: "typescript"
+layer: "application"
+
+dependsOn:
+ - "cssforge"
+
+tasks:
+ sync-docs:
+ command: "tsx"
+ args: ["./scripts/sync-readme.ts"]
+ inputs:
+ - "scripts/sync-readme.ts"
+ - "/packages/cssforge/README.md"
+ outputs:
+ - "docs.md"
+ options:
+ runInCI: false
+
+ generate:
+ command: "tsx"
+ args:
+ - "../../packages/cssforge/src/cli.ts"
+ - "--prefix"
+ - "."
+ - "--config"
+ - "./cssforge.config.ts"
+ - "--mode"
+ - "css"
+ - "--css"
+ - "./.cssforge/output.css"
+ deps:
+ - "^:build"
+ inputs:
+ - "cssforge.config.ts"
+ outputs:
+ - ".cssforge/output.css"
+ options:
+ runInCI: false
+
+ dev:
+ command: "vitepress"
+ args: ["dev"]
+ deps:
+ - "~:generate"
+ - "~:sync-docs"
+ preset: "server"
+ options:
+ runInCI: false
+
+ build:
+ command: "vitepress"
+ args: ["build"]
+ deps:
+ - "~:generate"
+ - "~:sync-docs"
+ outputs:
+ - ".vitepress/dist"
+ options:
+ runInCI: false
+
+ preview:
+ command: "vitepress"
+ args: ["preview"]
+ deps:
+ - "~:build"
+ preset: "server"
+ options:
+ runInCI: false
diff --git a/package.json b/package.json
index 7af13f1..c7fa648 100644
--- a/package.json
+++ b/package.json
@@ -1,8 +1,11 @@
{
- "name": "@hebilicious/cssforge",
- "version": "0.4.1",
+ "name": "cssforge-docs",
+ "private": true,
"type": "module",
- "scripts": {
- "version": "npx @changesets/cli version && node scripts/sync-version.js"
+ "devDependencies": {
+ "@hebilicious/cssforge": "workspace:*",
+ "tsx": "4.20.6",
+ "vitepress": "1.6.3",
+ "vue": "3.5.17"
}
}
diff --git a/scripts/sync-readme.ts b/scripts/sync-readme.ts
new file mode 100644
index 0000000..6ac861f
--- /dev/null
+++ b/scripts/sync-readme.ts
@@ -0,0 +1,44 @@
+import { readFileSync, writeFileSync } from "node:fs";
+import { resolve } from "node:path";
+
+const root = resolve(import.meta.dirname, "../../..");
+const readmePath = resolve(root, "packages/cssforge/README.md");
+const outputPath = resolve(root, "packages/docs/docs.md");
+
+const readme = readFileSync(readmePath, "utf-8");
+
+const GITHUB_BASE =
+ "https://github.com/Hebilicious/cssforge/tree/main";
+
+let content = readme;
+
+// Transform GitHub-flavored alerts to VitePress containers
+content = content.replace(
+ /^> \[!(NOTE|TIP|IMPORTANT|WARNING|CAUTION)\]\n((?:> .*\n?)*)/gm,
+ (_match, type: string, body: string) => {
+ const containerType = type.toLowerCase();
+ const text = body
+ .split("\n")
+ .map((line: string) => line.replace(/^> ?/, ""))
+ .join("\n")
+ .trim();
+ return `::: ${containerType}\n${text}\n:::\n`;
+ },
+);
+
+// Replace relative links like ./example/ with GitHub URLs
+content = content.replace(
+ /\]\(\.\/([\w/.-]+)\)/g,
+ `](${GITHUB_BASE}/$1)`,
+);
+
+// Prepend VitePress frontmatter
+const frontmatter = `---
+title: Documentation
+outline: [2, 3]
+---
+
+`;
+
+writeFileSync(outputPath, frontmatter + content, "utf-8");
+console.log(`Synced README → ${outputPath}`);
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..f4391f1
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,19 @@
+{
+ "extends": "../../tsconfig.base.json",
+ "compilerOptions": {
+ "lib": [
+ "ES2023",
+ "DOM"
+ ]
+ },
+ "include": [
+ "scripts/**/*.ts",
+ "cssforge.config.ts",
+ ".vitepress/**/*.ts"
+ ],
+ "references": [
+ {
+ "path": "../cssforge"
+ }
+ ]
+}