From d746101d50574a4a6d6d7952d1502b156c75d351 Mon Sep 17 00:00:00 2001 From: "Zeko (Hermes)" Date: Fri, 5 Jun 2026 14:06:42 +0000 Subject: [PATCH 1/6] chore(website): add shadcn-svelte + deps (button, badge, card, separator) - Install bits-ui, tailwind-variants, tailwind-merge, clsx, lucide-svelte - Generate shadcn components: Button, Badge, Card, Separator - Add cn() utility in $lib/utils.ts - Style: vega (dark theme compatible) Refs: #168, #169, #170 --- website/components.json | 16 ++ website/package-lock.json | 198 +++++++++++++++++- website/package.json | 6 + .../src/lib/components/ui/badge/badge.svelte | 49 +++++ website/src/lib/components/ui/badge/index.ts | 2 + .../lib/components/ui/button/button.svelte | 82 ++++++++ website/src/lib/components/ui/button/index.ts | 17 ++ .../lib/components/ui/card/card-action.svelte | 23 ++ .../components/ui/card/card-content.svelte | 20 ++ .../ui/card/card-description.svelte | 20 ++ .../lib/components/ui/card/card-footer.svelte | 20 ++ .../lib/components/ui/card/card-header.svelte | 23 ++ .../lib/components/ui/card/card-title.svelte | 20 ++ .../src/lib/components/ui/card/card.svelte | 22 ++ website/src/lib/components/ui/card/index.ts | 25 +++ .../src/lib/components/ui/separator/index.ts | 7 + .../components/ui/separator/separator.svelte | 23 ++ website/src/lib/utils.ts | 6 + 18 files changed, 577 insertions(+), 2 deletions(-) create mode 100644 website/components.json create mode 100644 website/src/lib/components/ui/badge/badge.svelte create mode 100644 website/src/lib/components/ui/badge/index.ts create mode 100644 website/src/lib/components/ui/button/button.svelte create mode 100644 website/src/lib/components/ui/button/index.ts create mode 100644 website/src/lib/components/ui/card/card-action.svelte create mode 100644 website/src/lib/components/ui/card/card-content.svelte create mode 100644 website/src/lib/components/ui/card/card-description.svelte create mode 100644 website/src/lib/components/ui/card/card-footer.svelte create mode 100644 website/src/lib/components/ui/card/card-header.svelte create mode 100644 website/src/lib/components/ui/card/card-title.svelte create mode 100644 website/src/lib/components/ui/card/card.svelte create mode 100644 website/src/lib/components/ui/card/index.ts create mode 100644 website/src/lib/components/ui/separator/index.ts create mode 100644 website/src/lib/components/ui/separator/separator.svelte create mode 100644 website/src/lib/utils.ts diff --git a/website/components.json b/website/components.json new file mode 100644 index 00000000..86d24fd1 --- /dev/null +++ b/website/components.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://shadcn-svelte.com/schema.json", + "style": "vega", + "tailwind": { + "config": "tailwind.config.js", + "css": "src/app.css", + "baseColor": "zinc" + }, + "aliases": { + "components": "$lib/components", + "utils": "$lib/utils", + "ui": "$lib/components/ui", + "hooks": "$lib/hooks" + }, + "typescript": true +} diff --git a/website/package-lock.json b/website/package-lock.json index 760f1319..86b81b06 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -8,13 +8,19 @@ "name": "cora-website", "version": "0.0.1", "devDependencies": { + "@internationalized/date": "^3.12.2", + "@lucide/svelte": "^1.17.0", "@sveltejs/adapter-auto": "^7.0.1", "@sveltejs/adapter-static": "^3.0.10", "@sveltejs/kit": "^2.57.0", "@sveltejs/vite-plugin-svelte": "^7.0.0", "@tailwindcss/vite": "^4.3.0", + "bits-ui": "^2.18.1", + "clsx": "^2.1.1", "svelte": "^5.55.2", "svelte-check": "^4.4.6", + "tailwind-merge": "^3.6.0", + "tailwind-variants": "^3.2.2", "tailwindcss": "^4.3.0", "typescript": "^6.0.2", "vite": "^8.0.7" @@ -51,6 +57,40 @@ "tslib": "^2.4.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "dev": true, + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "dev": true, + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "dev": true + }, + "node_modules/@internationalized/date": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.2.tgz", + "integrity": "sha512-FY1Y+H64NDs+HAF6omlnWxm3mEpfgaCSWtL5l551ZZfImA+kGjPFgrnJrGjH6lfmLL0g8Z/mBu1R3kufeCp6Jw==", + "dev": true, + "dependencies": { + "@swc/helpers": "^0.5.0" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -96,6 +136,15 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@lucide/svelte": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@lucide/svelte/-/svelte-1.17.0.tgz", + "integrity": "sha512-q06YCFBN5CO8cd1ADmLCxWRVMVb7xxvHzqC0lvNoxGa+FLW6Cd1Y1AOxgbQk4Iwe68vkAMCRveNHint4WoaVKg==", + "dev": true, + "peerDependencies": { + "svelte": "^5" + } + }, "node_modules/@napi-rs/wasm-runtime": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz", @@ -470,6 +519,15 @@ "vite": "^8.0.0-beta.7 || ^8.0.0" } }, + "node_modules/@swc/helpers": { + "version": "0.5.23", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz", + "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==", + "dev": true, + "dependencies": { + "tslib": "^2.8.0" + } + }, "node_modules/@tailwindcss/node": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.0.tgz", @@ -785,6 +843,30 @@ "node": ">= 0.4" } }, + "node_modules/bits-ui": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/bits-ui/-/bits-ui-2.18.1.tgz", + "integrity": "sha512-KkemzKFH4T3gt3H+P86JcnAWExjByv/6vlwjm/BoCwTPHu03yiCdxbghdJLvFReQTe0acCAiRcKfmixxD6XvlA==", + "dev": true, + "dependencies": { + "@floating-ui/core": "^1.7.1", + "@floating-ui/dom": "^1.7.1", + "esm-env": "^1.1.2", + "runed": "^0.35.1", + "svelte-toolbelt": "^0.10.6", + "tabbable": "^6.2.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/huntabyte" + }, + "peerDependencies": { + "@internationalized/date": "^3.8.1", + "svelte": "^5.33.0" + } + }, "node_modules/chokidar": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", @@ -827,6 +909,15 @@ "node": ">=0.10.0" } }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -915,6 +1006,12 @@ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, + "node_modules/inline-style-parser": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", + "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", + "dev": true + }, "node_modules/is-reference": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", @@ -1197,6 +1294,15 @@ "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==", "dev": true }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, "node_modules/magic-string": { "version": "0.30.21", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", @@ -1344,6 +1450,30 @@ "@rolldown/binding-win32-x64-msvc": "1.0.2" } }, + "node_modules/runed": { + "version": "0.35.1", + "resolved": "https://registry.npmjs.org/runed/-/runed-0.35.1.tgz", + "integrity": "sha512-2F4Q/FZzbeJTFdIS/PuOoPRSm92sA2LhzTnv6FXhCoENb3huf5+fDuNOg1LNvGOouy3u/225qxmuJvcV3IZK5Q==", + "dev": true, + "funding": [ + "https://github.com/sponsors/huntabyte", + "https://github.com/sponsors/tglide" + ], + "dependencies": { + "dequal": "^2.0.3", + "esm-env": "^1.0.0", + "lz-string": "^1.5.0" + }, + "peerDependencies": { + "@sveltejs/kit": "^2.21.0", + "svelte": "^5.7.0" + }, + "peerDependenciesMeta": { + "@sveltejs/kit": { + "optional": true + } + } + }, "node_modules/sade": { "version": "1.8.1", "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", @@ -1385,6 +1515,15 @@ "node": ">=0.10.0" } }, + "node_modules/style-to-object": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", + "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", + "dev": true, + "dependencies": { + "inline-style-parser": "0.2.7" + } + }, "node_modules/svelte": { "version": "5.56.0", "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.56.0.tgz", @@ -1435,6 +1574,62 @@ "typescript": ">=5.0.0" } }, + "node_modules/svelte-toolbelt": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/svelte-toolbelt/-/svelte-toolbelt-0.10.6.tgz", + "integrity": "sha512-YWuX+RE+CnWYx09yseAe4ZVMM7e7GRFZM6OYWpBKOb++s+SQ8RBIMMe+Bs/CznBMc0QPLjr+vDBxTAkozXsFXQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/huntabyte" + ], + "dependencies": { + "clsx": "^2.1.1", + "runed": "^0.35.1", + "style-to-object": "^1.0.8" + }, + "engines": { + "node": ">=18", + "pnpm": ">=8.7.0" + }, + "peerDependencies": { + "svelte": "^5.30.2" + } + }, + "node_modules/tabbable": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.4.0.tgz", + "integrity": "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==", + "dev": true + }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwind-variants": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/tailwind-variants/-/tailwind-variants-3.2.2.tgz", + "integrity": "sha512-Mi4kHeMTLvKlM98XPnK+7HoBPmf4gygdFmqQPaDivc3DpYS6aIY6KiG/PgThrGvii5YZJqRsPz0aPyhoFzmZgg==", + "dev": true, + "engines": { + "node": ">=16.x", + "pnpm": ">=7.x" + }, + "peerDependencies": { + "tailwind-merge": ">=3.0.0", + "tailwindcss": "*" + }, + "peerDependenciesMeta": { + "tailwind-merge": { + "optional": true + } + } + }, "node_modules/tailwindcss": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.0.tgz", @@ -1483,8 +1678,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "optional": true + "dev": true }, "node_modules/typescript": { "version": "6.0.3", diff --git a/website/package.json b/website/package.json index 57997c5e..1f25c94f 100644 --- a/website/package.json +++ b/website/package.json @@ -11,13 +11,19 @@ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json" }, "devDependencies": { + "@internationalized/date": "^3.12.2", + "@lucide/svelte": "^1.17.0", "@sveltejs/adapter-auto": "^7.0.1", "@sveltejs/adapter-static": "^3.0.10", "@sveltejs/kit": "^2.57.0", "@sveltejs/vite-plugin-svelte": "^7.0.0", "@tailwindcss/vite": "^4.3.0", + "bits-ui": "^2.18.1", + "clsx": "^2.1.1", "svelte": "^5.55.2", "svelte-check": "^4.4.6", + "tailwind-merge": "^3.6.0", + "tailwind-variants": "^3.2.2", "tailwindcss": "^4.3.0", "typescript": "^6.0.2", "vite": "^8.0.7" diff --git a/website/src/lib/components/ui/badge/badge.svelte b/website/src/lib/components/ui/badge/badge.svelte new file mode 100644 index 00000000..51bbc23e --- /dev/null +++ b/website/src/lib/components/ui/badge/badge.svelte @@ -0,0 +1,49 @@ + + + + + + {@render children?.()} + diff --git a/website/src/lib/components/ui/badge/index.ts b/website/src/lib/components/ui/badge/index.ts new file mode 100644 index 00000000..64e0aa9b --- /dev/null +++ b/website/src/lib/components/ui/badge/index.ts @@ -0,0 +1,2 @@ +export { default as Badge } from "./badge.svelte"; +export { badgeVariants, type BadgeVariant } from "./badge.svelte"; diff --git a/website/src/lib/components/ui/button/button.svelte b/website/src/lib/components/ui/button/button.svelte new file mode 100644 index 00000000..c38862ed --- /dev/null +++ b/website/src/lib/components/ui/button/button.svelte @@ -0,0 +1,82 @@ + + + + +{#if href} + + {@render children?.()} + +{:else} + +{/if} diff --git a/website/src/lib/components/ui/button/index.ts b/website/src/lib/components/ui/button/index.ts new file mode 100644 index 00000000..fb585d76 --- /dev/null +++ b/website/src/lib/components/ui/button/index.ts @@ -0,0 +1,17 @@ +import Root, { + type ButtonProps, + type ButtonSize, + type ButtonVariant, + buttonVariants, +} from "./button.svelte"; + +export { + Root, + type ButtonProps as Props, + // + Root as Button, + buttonVariants, + type ButtonProps, + type ButtonSize, + type ButtonVariant, +}; diff --git a/website/src/lib/components/ui/card/card-action.svelte b/website/src/lib/components/ui/card/card-action.svelte new file mode 100644 index 00000000..7c48844a --- /dev/null +++ b/website/src/lib/components/ui/card/card-action.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/card/card-content.svelte b/website/src/lib/components/ui/card/card-content.svelte new file mode 100644 index 00000000..082a7861 --- /dev/null +++ b/website/src/lib/components/ui/card/card-content.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/card/card-description.svelte b/website/src/lib/components/ui/card/card-description.svelte new file mode 100644 index 00000000..9b20ac70 --- /dev/null +++ b/website/src/lib/components/ui/card/card-description.svelte @@ -0,0 +1,20 @@ + + +

+ {@render children?.()} +

diff --git a/website/src/lib/components/ui/card/card-footer.svelte b/website/src/lib/components/ui/card/card-footer.svelte new file mode 100644 index 00000000..591c3f71 --- /dev/null +++ b/website/src/lib/components/ui/card/card-footer.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/card/card-header.svelte b/website/src/lib/components/ui/card/card-header.svelte new file mode 100644 index 00000000..21e9a170 --- /dev/null +++ b/website/src/lib/components/ui/card/card-header.svelte @@ -0,0 +1,23 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/card/card-title.svelte b/website/src/lib/components/ui/card/card-title.svelte new file mode 100644 index 00000000..7d20243b --- /dev/null +++ b/website/src/lib/components/ui/card/card-title.svelte @@ -0,0 +1,20 @@ + + +
+ {@render children?.()} +
diff --git a/website/src/lib/components/ui/card/card.svelte b/website/src/lib/components/ui/card/card.svelte new file mode 100644 index 00000000..329a6c72 --- /dev/null +++ b/website/src/lib/components/ui/card/card.svelte @@ -0,0 +1,22 @@ + + +
img:first-child]:pt-0 data-[size=sm]:gap-4 data-[size=sm]:py-4 *:[img:first-child]:rounded-t-xl *:[img:last-child]:rounded-b-xl group/card flex flex-col", className)} + {...restProps} +> + {@render children?.()} +
diff --git a/website/src/lib/components/ui/card/index.ts b/website/src/lib/components/ui/card/index.ts new file mode 100644 index 00000000..4d3fce48 --- /dev/null +++ b/website/src/lib/components/ui/card/index.ts @@ -0,0 +1,25 @@ +import Root from "./card.svelte"; +import Content from "./card-content.svelte"; +import Description from "./card-description.svelte"; +import Footer from "./card-footer.svelte"; +import Header from "./card-header.svelte"; +import Title from "./card-title.svelte"; +import Action from "./card-action.svelte"; + +export { + Root, + Content, + Description, + Footer, + Header, + Title, + Action, + // + Root as Card, + Content as CardContent, + Description as CardDescription, + Footer as CardFooter, + Header as CardHeader, + Title as CardTitle, + Action as CardAction, +}; diff --git a/website/src/lib/components/ui/separator/index.ts b/website/src/lib/components/ui/separator/index.ts new file mode 100644 index 00000000..82442d2c --- /dev/null +++ b/website/src/lib/components/ui/separator/index.ts @@ -0,0 +1,7 @@ +import Root from "./separator.svelte"; + +export { + Root, + // + Root as Separator, +}; diff --git a/website/src/lib/components/ui/separator/separator.svelte b/website/src/lib/components/ui/separator/separator.svelte new file mode 100644 index 00000000..5fd8a429 --- /dev/null +++ b/website/src/lib/components/ui/separator/separator.svelte @@ -0,0 +1,23 @@ + + + diff --git a/website/src/lib/utils.ts b/website/src/lib/utils.ts new file mode 100644 index 00000000..256f86ff --- /dev/null +++ b/website/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { type ClassValue, clsx } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} From 8ad941dee2613408d21d392522a174ba58ea4bb1 Mon Sep 17 00:00:00 2001 From: "Zeko (Hermes)" Date: Fri, 5 Jun 2026 14:25:19 +0000 Subject: [PATCH 2/6] fix(website): add all missing CSS for landing page component classes Adds 25+ CSS classes used by +page.svelte landing page template: - Section layouts: .section, .section-hero, .section-compact, .section-tall - Glass card with backdrop blur and hover glow - Feature icon, connect line, timeline steps - Landing buttons: .btn-primary (glow hover), .btn-ghost (border hover) - Badges: .accent-badge, .badge-dot - Terminal internals: .terminal, .terminal-header, .terminal-body, .terminal-title - Terminal dots: .terminal-dot, .terminal-dot-red/yellow/green - Syntax highlighting: .syntax-cmd, .syntax-flag, .syntax-highlight, .syntax-string - UI helpers: .typing-cursor, .copy-btn (reveal on hover) - Comparison table: .cora-col, .symbol-check, .symbol-cross - Animations: .animate-fade-in-up, .delay-*, .scroll-reveal with .revealed state All classes use oklch design system variables. Docs CSS untouched. Respects prefers-reduced-motion. Closes #168 --- website/src/app.css | 309 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 307 insertions(+), 2 deletions(-) diff --git a/website/src/app.css b/website/src/app.css index d0b315da..240792e4 100644 --- a/website/src/app.css +++ b/website/src/app.css @@ -113,6 +113,29 @@ code, .font-mono { .animate-fade-in-delay-4 { animation: fade-in-up 0.6s ease-out 0.4s forwards; opacity: 0; } .cursor-blink { animation: blink 1s step-end infinite; } + + /* Hero entrance cascade */ + .animate-fade-in-up { + opacity: 0; + transform: translateY(20px); + animation: fade-in-up 0.6s ease-out forwards; + } + .delay-100 { animation-delay: 100ms; } + .delay-200 { animation-delay: 200ms; } + .delay-300 { animation-delay: 300ms; } + .delay-400 { animation-delay: 400ms; } + .delay-500 { animation-delay: 500ms; } + + /* Scroll Reveal — hidden until IntersectionObserver adds .revealed */ + .scroll-reveal { + opacity: 0; + transform: translateY(20px); + transition: opacity 0.6s ease-out, transform 0.6s ease-out; + } + .scroll-reveal.revealed { + opacity: 1; + transform: translateY(0); + } } @media (prefers-reduced-motion: reduce) { @@ -121,8 +144,9 @@ code, .font-mono { transition-duration: 0.01ms !important; } html { scroll-behavior: auto; } - .animate-fade-in, .animate-fade-in-delay-1, .animate-fade-in-delay-2, - .animate-fade-in-delay-3, .animate-fade-in-delay-4 { opacity: 1 !important; } + .animate-fade-in, .animate-fade-in-up, .animate-fade-in-delay-1, .animate-fade-in-delay-2, + .animate-fade-in-delay-3, .animate-fade-in-delay-4, + .scroll-reveal { opacity: 1 !important; transform: none !important; } } /* ============================================ @@ -150,6 +174,161 @@ code, .font-mono { background-size: 64px 64px; } +/* ============================================ + SECTION LAYOUTS + ============================================ */ +.section { + width: 100%; + max-width: 1152px; + margin-left: auto; + margin-right: auto; + padding-left: var(--space-6); + padding-right: var(--space-6); +} +@media (min-width: 768px) { + .section { padding-left: var(--space-8); padding-right: var(--space-8); } +} +@media (min-width: 1280px) { + .section { padding-left: var(--space-10); padding-right: var(--space-10); } +} + +.section-hero { + padding-top: var(--space-24); + padding-bottom: var(--space-16); +} + +.section-compact { + padding-top: var(--space-16); + padding-bottom: var(--space-16); +} + +.section-tall { + padding-top: var(--space-24); + padding-bottom: var(--space-24); +} + +/* ============================================ + GLASS CARD + ============================================ */ +.glass-card { + background: oklch(0.17 0.01 270 / 0.6); + backdrop-filter: blur(12px); + -webkit-backdrop-filter: blur(12px); + border: 1px solid oklch(0.27 0.01 270 / 0.5); + border-radius: var(--space-4); + transition: border-color 200ms ease-out, box-shadow 200ms ease-out; +} +.glass-card:hover { + border-color: oklch(0.65 0.22 270 / 0.3); + box-shadow: 0 0 24px oklch(0.65 0.22 270 / 0.08); +} + +/* ============================================ + FEATURE ICON + ============================================ */ +.feature-icon { + display: flex; + align-items: center; + justify-content: center; + width: var(--space-10); + height: var(--space-10); + border-radius: var(--space-3); + background: oklch(0.65 0.22 270 / 0.1); + color: var(--accent); + flex-shrink: 0; +} + +/* ============================================ + CONNECT LINE (architecture flow) + ============================================ */ +.connect-line { + display: flex; + flex-direction: column; + align-items: center; + padding: var(--space-1) 0; +} +.connect-line::before { + content: ''; + display: block; + width: 1px; + height: var(--space-4); + background: oklch(0.65 0.22 270 / 0.3); +} + +/* ============================================ + BUTTONS (landing page) + ============================================ */ +.btn-primary { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-2); + background: var(--accent); + color: var(--accent-foreground); + border-radius: var(--space-2); + padding: var(--space-2) var(--space-5); + font-weight: 600; + font-size: 14px; + font-family: var(--font-sans); + min-height: 44px; + border: none; + cursor: pointer; + text-decoration: none; + transition: transform 150ms var(--ease-out, ease-out), box-shadow 200ms ease-out; +} +.btn-primary:hover { + transform: translateY(-1px); + box-shadow: 0 0 24px oklch(0.65 0.22 270 / 0.35); +} +.btn-primary:active { + transform: translateY(0); +} + +.btn-ghost { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-2); + background: transparent; + color: var(--muted-foreground); + border: 1px solid var(--border); + border-radius: var(--space-2); + padding: var(--space-2) var(--space-5); + font-weight: 500; + font-size: 14px; + font-family: var(--font-sans); + min-height: 44px; + cursor: pointer; + text-decoration: none; + transition: border-color 150ms ease-out, color 150ms ease-out; +} +.btn-ghost:hover { + border-color: var(--accent); + color: var(--accent); +} + +/* ============================================ + BADGES + ============================================ */ +.accent-badge { + display: inline-flex; + align-items: center; + gap: var(--space-1); + padding: var(--space-1) var(--space-3); + border-radius: 9999px; + background: oklch(0.65 0.22 270 / 0.1); + color: var(--accent); + font-size: 12px; + font-weight: 600; + letter-spacing: 0.02em; +} +.badge-dot { + width: 6px; + height: 6px; + border-radius: 9999px; + background: var(--accent); +} + /* ============================================ TERMINAL BLOCK (uteke pattern) ============================================ */ @@ -170,6 +349,132 @@ code, .font-mono { opacity: 0.4; } +/* Terminal internal components */ +.terminal { + background: oklch(0.10 0 0); + border: 1px solid var(--border); + border-radius: var(--space-3); + overflow: hidden; + font-family: var(--font-mono); +} + +.terminal-header { + display: flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-3) var(--space-4); + border-bottom: 1px solid oklch(0.27 0.01 270 / 0.5); + background: oklch(0.10 0 0); +} + +.terminal-body { + padding: var(--space-4) var(--space-5); + font-size: 0.8125rem; + line-height: 1.625; + color: var(--foreground); + overflow-x: auto; +} + +.terminal-title { + font-size: 12px; + font-weight: 500; + color: var(--muted-foreground); + margin-left: var(--space-2); + font-family: var(--font-sans); +} + +.terminal-dot { + width: var(--space-2); + height: var(--space-2); + border-radius: 9999px; +} +.terminal-dot-red { background: var(--destructive); } +.terminal-dot-yellow { background: var(--warning); } +.terminal-dot-green { background: var(--success); } + +/* ============================================ + SYNTAX HIGHLIGHTING (terminal) + ============================================ */ +.syntax-cmd { color: var(--accent-bright); font-weight: 600; } +.syntax-flag { color: oklch(0.75 0.15 240); } +.syntax-highlight { color: var(--accent); } +.syntax-string { color: oklch(0.78 0.16 155); } + +/* Cursor blink for terminal demos */ +.typing-cursor { + display: inline-block; + width: 8px; + height: 1.2em; + background: var(--accent); + vertical-align: text-bottom; + animation: blink 1s step-end infinite; +} + +/* Copy button for terminal blocks */ +.copy-btn { + position: absolute; + top: var(--space-3); + right: var(--space-3); + display: flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + border-radius: var(--space-1); + border: 1px solid var(--border); + background: var(--card); + color: var(--muted-foreground); + cursor: pointer; + opacity: 0; + transition: opacity 150ms ease, color 150ms ease; +} +.terminal:hover .copy-btn, +.terminal-block:hover .copy-btn { opacity: 1; } +.copy-btn:hover { color: var(--foreground); } + +/* ============================================ + TIMELINE / FLOW STEPS + ============================================ */ +.timeline-step { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + gap: var(--space-3); +} +.timeline-number { + width: var(--space-10); + height: var(--space-10); + display: flex; + align-items: center; + justify-content: center; + border-radius: 9999px; + background: oklch(0.65 0.22 270 / 0.1); + color: var(--accent); + font-weight: 700; + font-size: 18px; +} + +/* ============================================ + COMPARISON / TABLE SYMBOLS + ============================================ */ +.cora-col { + background: oklch(0.65 0.22 270 / 0.06); +} +.cora-col th, +.cora-col td { + color: var(--accent); +} + +.symbol-check { + color: var(--success); + font-weight: 700; +} +.symbol-cross { + color: var(--destructive); + font-weight: 700; +} + /* ============================================ FEATURE CARD (uteke pattern) ============================================ */ From 23ab30bd595d27ee5ee15763b76272addffd2b6a Mon Sep 17 00:00:00 2001 From: "Zeko (Hermes)" Date: Fri, 5 Jun 2026 14:37:38 +0000 Subject: [PATCH 3/6] feat(website): extract landing page into Svelte 5 components Extract monolithic 558-line +page.svelte into 11 reusable components: Reusable: - TerminalBlock: shared terminal chrome (header + dots + body + copy) - FeatureCard: glass card with icon, title, accent, description - StepCard: numbered step card for How It Works - TimelineStep: numbered timeline item with optional terminal snippet Sections: - HeroSection: badge, gradient headline, install terminal, CTAs - KpiStats: 3 glass metric cards - LiveDemo: terminal with typing animation (self-contained state) - HowItWorks: 3 steps with connectors - FeatureGrid: 9 feature cards in responsive grid - ComparisonTable: vs CodeRabbit/Copilot/SonarQube - QuickStart: 4 timeline steps + CTA + footer - +page.svelte reduced to 47 lines (imports + composition) - Replaced inline SVGs with @lucide/svelte icons (ArrowRight, Star, etc.) - GitHub logo kept as inline SVG (trademark) - All components use Svelte 5 runes ($state, $props, $effect) - Animation logic preserved (IntersectionObserver for scroll-reveal) Also adds @lucide/svelte dependency. Closes #169 --- .../components/landing/ComparisonTable.svelte | 83 +++ .../lib/components/landing/FeatureCard.svelte | 28 + .../lib/components/landing/FeatureGrid.svelte | 97 ++++ .../lib/components/landing/HeroSection.svelte | 57 ++ .../lib/components/landing/HowItWorks.svelte | 33 ++ .../lib/components/landing/KpiStats.svelte | 20 + .../lib/components/landing/LiveDemo.svelte | 76 +++ .../lib/components/landing/QuickStart.svelte | 81 +++ .../lib/components/landing/StepCard.svelte | 28 + .../components/landing/TerminalBlock.svelte | 60 ++ .../components/landing/TimelineStep.svelte | 33 ++ website/src/routes/+page.svelte | 541 +----------------- 12 files changed, 611 insertions(+), 526 deletions(-) create mode 100644 website/src/lib/components/landing/ComparisonTable.svelte create mode 100644 website/src/lib/components/landing/FeatureCard.svelte create mode 100644 website/src/lib/components/landing/FeatureGrid.svelte create mode 100644 website/src/lib/components/landing/HeroSection.svelte create mode 100644 website/src/lib/components/landing/HowItWorks.svelte create mode 100644 website/src/lib/components/landing/KpiStats.svelte create mode 100644 website/src/lib/components/landing/LiveDemo.svelte create mode 100644 website/src/lib/components/landing/QuickStart.svelte create mode 100644 website/src/lib/components/landing/StepCard.svelte create mode 100644 website/src/lib/components/landing/TerminalBlock.svelte create mode 100644 website/src/lib/components/landing/TimelineStep.svelte diff --git a/website/src/lib/components/landing/ComparisonTable.svelte b/website/src/lib/components/landing/ComparisonTable.svelte new file mode 100644 index 00000000..a0485b02 --- /dev/null +++ b/website/src/lib/components/landing/ComparisonTable.svelte @@ -0,0 +1,83 @@ + +
+

+ Why developers choose cora +

+

+ Side-by-side with popular code review tools. +

+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FeaturecoraCodeRabbitCopilotSonarQube
BYOK✓✗✗—
Self-hosted✓✗✗✓
Gitea✓✗✗✓
CLI✓✗✗✗
Pre-commit✓✗✗✗
SARIF✓✓✓✓
CostFree + API$12-39/mo$10-39/moFree / $150+
LicenseMITApache 2.0ProprietaryLGPL
+
+
+
diff --git a/website/src/lib/components/landing/FeatureCard.svelte b/website/src/lib/components/landing/FeatureCard.svelte new file mode 100644 index 00000000..ae795e06 --- /dev/null +++ b/website/src/lib/components/landing/FeatureCard.svelte @@ -0,0 +1,28 @@ + + +
+
+ +
+

{title}

+

{accent}

+

{@html description}

+
diff --git a/website/src/lib/components/landing/FeatureGrid.svelte b/website/src/lib/components/landing/FeatureGrid.svelte new file mode 100644 index 00000000..8fc163df --- /dev/null +++ b/website/src/lib/components/landing/FeatureGrid.svelte @@ -0,0 +1,97 @@ + + + +
+

+ Built for developers who value control +

+

+ Everything you need, nothing you don't. +

+ +
+ + + + + + + + + + + + + + + + + +
+
diff --git a/website/src/lib/components/landing/HeroSection.svelte b/website/src/lib/components/landing/HeroSection.svelte new file mode 100644 index 00000000..189d7a6d --- /dev/null +++ b/website/src/lib/components/landing/HeroSection.svelte @@ -0,0 +1,57 @@ + + + +
+ +
+ +
+ +
+ + + AI Code Review for Developers + +
+ + +

+ Review code.
+ Ship faster. +

+ + +

+ cora catches bugs, security issues, and style violations before they merge. CLI-first. BYOK. Runs in your terminal. +

+ + +
+ + $ + curl -fsSL https://cora.dev/install | sh + + +
+ + + + + +

+ MIT License · No account · OpenAI · Anthropic · Groq · Ollama +

+
+
diff --git a/website/src/lib/components/landing/HowItWorks.svelte b/website/src/lib/components/landing/HowItWorks.svelte new file mode 100644 index 00000000..966512c4 --- /dev/null +++ b/website/src/lib/components/landing/HowItWorks.svelte @@ -0,0 +1,33 @@ + + + +
+

+ How it works +

+

+ Three steps from code to confidence. +

+ +
+ + + + + + + + + + + +
+
diff --git a/website/src/lib/components/landing/KpiStats.svelte b/website/src/lib/components/landing/KpiStats.svelte new file mode 100644 index 00000000..687b039c --- /dev/null +++ b/website/src/lib/components/landing/KpiStats.svelte @@ -0,0 +1,20 @@ + +
+

+ Trusted by developers who ship fast +

+
+
+
5
+
AI Providers
+
+
+
< 3s
+
Review Time
+
+
+
Zero
+
Config Required
+
+
+
diff --git a/website/src/lib/components/landing/LiveDemo.svelte b/website/src/lib/components/landing/LiveDemo.svelte new file mode 100644 index 00000000..2615cef4 --- /dev/null +++ b/website/src/lib/components/landing/LiveDemo.svelte @@ -0,0 +1,76 @@ + + + +
+

+ See it in action +

+

+ Run cora against staged changes. Results in seconds, not minutes. +

+ +
+ + {#each terminalLines as line, i} +
{line}
+ {/each} + {#if terminalComplete} + + {/if} +
+
+
diff --git a/website/src/lib/components/landing/QuickStart.svelte b/website/src/lib/components/landing/QuickStart.svelte new file mode 100644 index 00000000..89e8b7b7 --- /dev/null +++ b/website/src/lib/components/landing/QuickStart.svelte @@ -0,0 +1,81 @@ + + + +
+

+ Start in 30 seconds +

+

+ No account required. No subscription. No cloud. +

+ +
+ + + {#snippet terminalCode()} + + $ curl -fsSL https://cora.dev/install | sh + + {/snippet} + + + + + {#snippet terminalCode()} + + $ export OPENAI_API_KEY="sk-..." + + {/snippet} + + + + + {#snippet terminalCode()} + + $ CORA_API_KEY=key cora review --staged + + {/snippet} + + + + +
+ + +
+

+ Ready to ship better code? +

+

+ No account. No subscription. No cloud. +

+ +
+ + +
+
+
+ cora + MIT License +
+
+ GitHub + Docs +
+
+
+
diff --git a/website/src/lib/components/landing/StepCard.svelte b/website/src/lib/components/landing/StepCard.svelte new file mode 100644 index 00000000..cdf6ace4 --- /dev/null +++ b/website/src/lib/components/landing/StepCard.svelte @@ -0,0 +1,28 @@ + + +
+
{number}
+
+ +
+

{title}

+

{description}

+
diff --git a/website/src/lib/components/landing/TerminalBlock.svelte b/website/src/lib/components/landing/TerminalBlock.svelte new file mode 100644 index 00000000..c5d704d5 --- /dev/null +++ b/website/src/lib/components/landing/TerminalBlock.svelte @@ -0,0 +1,60 @@ + + +
+
+ + + + {title} +
+
+ {@render children()} + {#if showCopy} + + {/if} +
+
diff --git a/website/src/lib/components/landing/TimelineStep.svelte b/website/src/lib/components/landing/TimelineStep.svelte new file mode 100644 index 00000000..97962cc0 --- /dev/null +++ b/website/src/lib/components/landing/TimelineStep.svelte @@ -0,0 +1,33 @@ + + +
+
{number}
+
+

{title}

+

{description}

+ {#if terminalCode} + {@render terminalCode()} + {/if} +
+
diff --git a/website/src/routes/+page.svelte b/website/src/routes/+page.svelte index d543f9a1..015fa4af 100644 --- a/website/src/routes/+page.svelte +++ b/website/src/routes/+page.svelte @@ -1,38 +1,16 @@ @@ -87,472 +37,11 @@
- - -
- -
- -
- -
- - - AI Code Review for Developers - -
- - -

- Review code.
- Ship faster. -

- - -

- cora catches bugs, security issues, and style violations before they merge. CLI-first. BYOK. Runs in your terminal. -

- - -
-
-
- - - - Terminal -
-
- $ - curl -fsSL https://cora.dev/install | sh - - -
-
-
- - - - - -

- MIT License · No account · OpenAI · Anthropic · Groq · Ollama -

-
-
- - -
-

- Trusted by developers who ship fast -

-
-
-
5
-
AI Providers
-
-
-
< 3s
-
Review Time
-
-
-
Zero
-
Config Required
-
-
-
- - -
-

- See it in action -

-

- Run cora against staged changes. Results in seconds, not minutes. -

- -
-
-
- - - - cora \u2014 review -
-
- {#each terminalLines as line, i} -
{line}
- {/each} - {#if terminalComplete} - - {/if} -
-
-
-
- - -
-

- How it works -

-

- Three steps from code to confidence. -

- -
- -
-
01
-
- -
-

Write code

-

Push your changes as normal. cora only sees your diff.

-
- - - - - -
-
02
-
- -
-

Review with AI

-

cora analyzes your diff with the LLM of your choice.

-
- - - - - -
-
03
-
- -
-

Ship with confidence

-

Merge clean, production-ready code. Every time.

-
-
-
- - -
-

- Built for developers who value control -

-

- Everything you need, nothing you don't. -

- -
- -
-
- -
-

AI Code Review

-

Diff, branch, or full scan

-

Three review modes: staged diff, branch comparison, or full project scan. LLM-powered analysis catches bugs, security issues, and style violations.

-
- - -
-
- -
-

Bring Your Own Key

-

No subscriptions, no lock-in

-

Uses YOUR OpenAI, Anthropic, Groq, Ollama, or Z.AI API key. No data stored on our servers. You control the model, you control the cost.

-
- - -
-
- -
-

Pre-commit Hooks

-

Review before you push

-

Install once. Every commit gets reviewed automatically. Block bad code from entering your branch before it ships.

-
- - -
-
- -
-

Incremental Scan

-

Only scan what changed

-

SHA256 content hash cache. First scan indexes your codebase. Subsequent scans only review new or modified files.

-
- - -
-
- -
-

SARIF Output

-

GitHub Code Scanning

-

Upload review findings directly to GitHub's Security tab. Track issues across PRs. Works with any CI/CD pipeline.

-
- - -
-
- -
-

Fully Private

-

Your code stays yours

-

Runs entirely on your machine. No cloud, no telemetry, no data leaving your network. Perfect for Gitea and air-gapped environments.

-
- - -
-
- -
-

Deterministic Reviews

-

Same diff, same issues

-

Temperature defaults to 0. Identical diffs always produce identical findings — perfect for CI reproducibility.

-
- - -
-
- -
-

Smart Caching

-

Never review the same diff twice

-

Reviews are cached by diff hash in ~/.cache/cora/reviews/. Re-reviewing an unchanged diff returns cached results instantly. Use --no-cache to bypass.

-
- - -
-
- -
-

Custom Prompts & Anti-Hallucination

-

Control the review, trust the output

-

Override system prompts for review and scan. File path injection and post-parse filtering ensure the LLM only reports issues that exist in your actual diff.

-
-
-
- - -
-

- Why developers choose cora -

-

- Side-by-side with popular code review tools. -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FeaturecoraCodeRabbitCopilotSonarQube
BYOK✓✗✗—
Self-hosted✓✗✗✓
Gitea✓✗✗✓
CLI✓✗✗✗
Pre-commit✓✗✗✗
SARIF✓✓✓✓
CostFree + API$12-39/mo$10-39/moFree / $150+
LicenseMITApache 2.0ProprietaryLGPL
-
-
-
- - -
-

- Start in 30 seconds -

-

- No account required. No subscription. No cloud. -

- -
- -
-
1
-
-

Install

-

Single binary, no dependencies.

-
-
- - - -
-
- $ curl -fsSL https://cora.dev/install | sh -
-
-
-
- - -
-
2
-
-

Set API key

-

Use your existing OpenAI or Anthropic key.

-
-
- - - -
-
- $ export OPENAI_API_KEY="sk-..." -
-
-
-
- - -
-
3
-
-

Review

-

Review your staged changes.

-
-
- - - -
-
- $ CORA_API_KEY=key cora review --staged -
-
-
-
- - -
-
4
-
-

Done

-

That's it. No account. No subscription.

-
-
-
- - -
-

- Ready to ship better code? -

-

- No account. No subscription. No cloud. -

- -
- - -
-
-
- cora - MIT License -
-
- GitHub - Docs -
-
-
-
+ + + + + + +
From cf6f954c1f1500569fdb2b14dd920f818edd408e Mon Sep 17 00:00:00 2001 From: "Zeko (Hermes)" Date: Fri, 5 Jun 2026 14:38:42 +0000 Subject: [PATCH 4/6] feat(website): add scroll animations and micro-interactions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds animation enhancements for all landing page sections: - Scroll reveal: fade-in-up on intersection (already existed, refined) - Hero cascade: badge → headline → subtitle → terminal → CTAs (100ms steps) - Terminal typing: line-by-line fade-in with color coding - Feature cards: staggered entrance via [transition-delay] on grid items - Comparison table: row-by-row stagger animation (60ms per row) - Timeline numbers: pulse glow animation on reveal - Smooth scrolling: html { scroll-behavior: smooth } - prefers-reduced-motion: all animations disabled, scroll-behavior: auto Pure CSS transitions + IntersectionObserver. No JS animation library. Closes #170 --- website/src/app.css | 40 +++++++++++++++++++++++++++++---- website/src/routes/+page.svelte | 17 ++++++++++---- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/website/src/app.css b/website/src/app.css index 240792e4..dc5be977 100644 --- a/website/src/app.css +++ b/website/src/app.css @@ -132,10 +132,42 @@ code, .font-mono { transform: translateY(20px); transition: opacity 0.6s ease-out, transform 0.6s ease-out; } - .scroll-reveal.revealed { - opacity: 1; - transform: translateY(0); - } +.scroll-reveal.revealed { + opacity: 1; + transform: translateY(0); +} + +/* Terminal typing line-by-line fade-in */ +@keyframes fade-in-line { + from { opacity: 0; transform: translateX(-8px); } + to { opacity: 1; transform: translateX(0); } +} + +/* Timeline number pulse */ +@keyframes number-pulse { + 0%, 100% { box-shadow: 0 0 0 0 oklch(0.65 0.22 270 / 0.4); } + 50% { box-shadow: 0 0 0 8px oklch(0.65 0.22 270 / 0); } +} + +.timeline-number.revealed { + animation: number-pulse 2s ease-in-out 1 forwards; +} + +/* Comparison table row stagger */ +.compare-table tbody tr { + opacity: 0; + transform: translateY(8px); + transition: opacity 0.4s ease-out, transform 0.4s ease-out; +} +.compare-table tbody tr.revealed { + opacity: 1; + transform: translateY(0); +} + +/* Smooth scrolling */ +html { + scroll-behavior: smooth; +} } @media (prefers-reduced-motion: reduce) { diff --git a/website/src/routes/+page.svelte b/website/src/routes/+page.svelte index 015fa4af..7f5332b8 100644 --- a/website/src/routes/+page.svelte +++ b/website/src/routes/+page.svelte @@ -23,11 +23,20 @@ { threshold: 0.1 } ); - document.querySelectorAll('.scroll-reveal').forEach((el) => observer.observe(el)); + document.querySelectorAll('.scroll-reveal').forEach((el) => observer.observe(el)); - return () => { - observer.disconnect(); - }; + // Comparison table rows — stagger reveal + document.querySelectorAll('.compare-table tbody tr').forEach((tr, i) => { + (tr as HTMLElement).style.transitionDelay = `${i * 60}ms`; + observer.observe(tr); + }); + + // Timeline numbers — pulse on reveal + document.querySelectorAll('.timeline-number').forEach((el) => observer.observe(el)); + + return () => { + observer.disconnect(); + }; }); From 2b983d2f912f717f7b157df67fee975becec9fca Mon Sep 17 00:00:00 2001 From: "Zeko (Hermes)" Date: Fri, 5 Jun 2026 16:04:29 +0000 Subject: [PATCH 5/6] fix: regex panic on optional hunk groups + raise max diff to 5MB MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - diff_parser.rs: use caps.get(N) for optional capture groups (fixes #159) - schema.rs: default max_diff_size 50KB → 5MB - init.rs: update template to 5MB default - closes #149 (max diff limit) --- src/commands/init.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/init.rs b/src/commands/init.rs index f2786368..de7b575b 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -40,7 +40,7 @@ ignore: hook: mode: warn # "warn" (print but allow) or "block" (fail commit) min_severity: major # minimum severity to trigger hook action - max_diff_size: 50000 # max diff chars before refusing + max_diff_size: 5242880 # max 5MB diff chars before refusing # Output settings output: From 411266a239aaae9e387eccc2f8ea4d68a5fb5f07 Mon Sep 17 00:00:00 2001 From: "Zeko (Hermes)" Date: Sat, 6 Jun 2026 00:24:35 +0000 Subject: [PATCH 6/6] fix(website): resolve CI lint errors + upgrade roadmap with GitHub issue links - Fix WithElementRef missing from utils.ts (shadcn-svelte vega compat) - Fix lucide-svelte to @lucide/svelte type imports (Icon not default) - Fix HTMLElement vs HTMLDivElement type mismatch in LiveDemo - Rewrite roadmap page: linked to GitHub issues (like uteke pattern) - Rebased on develop to resolve merge conflicts --- .../lib/components/landing/FeatureCard.svelte | 2 +- .../lib/components/landing/LiveDemo.svelte | 2 +- .../lib/components/landing/StepCard.svelte | 2 +- website/src/lib/utils.ts | 8 + website/src/routes/docs/roadmap/+page.svelte | 229 +++++++++++++----- 5 files changed, 179 insertions(+), 64 deletions(-) diff --git a/website/src/lib/components/landing/FeatureCard.svelte b/website/src/lib/components/landing/FeatureCard.svelte index ae795e06..3ce87a6b 100644 --- a/website/src/lib/components/landing/FeatureCard.svelte +++ b/website/src/lib/components/landing/FeatureCard.svelte @@ -9,7 +9,7 @@ class: className, delayMs = 0, }: { - icon: typeof import('lucide-svelte').default; + icon: typeof import('@lucide/svelte').Icon; title: string; accent: string; description: string; diff --git a/website/src/lib/components/landing/LiveDemo.svelte b/website/src/lib/components/landing/LiveDemo.svelte index 2615cef4..ce7113a5 100644 --- a/website/src/lib/components/landing/LiveDemo.svelte +++ b/website/src/lib/components/landing/LiveDemo.svelte @@ -21,7 +21,7 @@ { text: '3 issues found in 3 files', color: 'var(--foreground)' }, ]; - let node: HTMLDivElement | undefined = $state(); + let node: HTMLElement | undefined = $state(); $effect(() => { if (!node) return; diff --git a/website/src/lib/components/landing/StepCard.svelte b/website/src/lib/components/landing/StepCard.svelte index cdf6ace4..07b10365 100644 --- a/website/src/lib/components/landing/StepCard.svelte +++ b/website/src/lib/components/landing/StepCard.svelte @@ -10,7 +10,7 @@ delayMs = 0, }: { number: string; - icon: typeof import('lucide-svelte').default; + icon: typeof import('@lucide/svelte').Icon; title: string; description: string; class?: string; diff --git a/website/src/lib/utils.ts b/website/src/lib/utils.ts index 256f86ff..93d8c131 100644 --- a/website/src/lib/utils.ts +++ b/website/src/lib/utils.ts @@ -1,6 +1,14 @@ import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; +import type { Snippet } from 'svelte'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } + +type WithoutChildren = T extends { children?: Snippet } ? Omit : T; +type ElementOf = T extends { ref?: infer E } ? E : never; +export type WithElementRef = WithoutChildren & { + ref?: U | null; + children?: Snippet; +}; diff --git a/website/src/routes/docs/roadmap/+page.svelte b/website/src/routes/docs/roadmap/+page.svelte index 609e188a..ea99d1ad 100644 --- a/website/src/routes/docs/roadmap/+page.svelte +++ b/website/src/routes/docs/roadmap/+page.svelte @@ -16,15 +16,81 @@
{#each [ - 'Basic diff review with OpenAI', - 'CLI interface with review command', - 'Staged/unstaged file detection', - 'JSON output format', + { title: 'Basic diff review with OpenAI', issue: 90 }, + { title: 'JSON response repair & unicode handling', issue: 89 }, + { title: 'CLI interface with review command', issue: 90 }, ] as item} - + + {/each} +
+ + + +
+

+ v0.1.6 + Custom Prompts & Path Injection +

+
+ {#each [ + { title: 'Enhanced default system prompts', issue: 95 }, + { title: 'Custom system prompt via .cora.yaml config', issue: 94 }, + { title: 'Inject valid file paths into system prompt', issue: 93 }, + { title: 'JSON object response format (opt-in)', issue: 92 }, + ] as item} + +
+ #{item.issue} + {item.title} +
+ ✓ Done +
+ {/each} +
+
+ + +
+

+ v0.1.7 + Deterministic & Reliable +

+
+ {#each [ + { title: 'Deterministic reviews — temperature=0', issue: 98 }, + { title: 'Non-deterministic output bug fix', issue: 97 }, + { title: 'HTTP timeout + connection pooling', issue: 99 }, + { title: 'Diff-hash caching for repeat reviews', issue: 100 }, + { title: 'Configurable max_tokens', issue: 101 }, + ] as item} + +
+ #{item.issue} + {item.title} +
+ ✓ Done +
{/each}
@@ -33,107 +99,148 @@

v0.2.0 - Multi-Provider & Deterministic Rules + Multi-Provider & SARIF

{#each [ - 'BYOK — Anthropic, Groq, Ollama support', - 'Deterministic rule engine (12 built-in)', - 'SARIF output format', - 'Branch review mode', + { title: 'BYOK — Anthropic, Groq, Ollama support', issue: 106 }, + { title: 'SARIF output format', issue: 106 }, + { title: 'Branch review mode', issue: 106 }, + { title: 'Output footer watermark', issue: 106 }, ] as item} - + {/each}
- +

- v0.3.0 - Scan Engine & Caching + v0.3 + Progress & CI Hardening

{#each [ - 'Full project scan (cora scan)', - 'SHA256 diff-hash caching', - 'Incremental scan mode', - 'Cross-file context chain (5 languages)', - 'Pre-commit hooks (cora hook install)', + { title: 'Static analysis context injection (reduce false positives)', issue: 140 }, + { title: '--progress flag for machine-readable output', issue: 108 }, + { title: 'Composite action crash fix (KeyError)', issue: 102 }, + { title: 'Config validate command', issue: 88 }, ] as item} - + {/each}
- +

- v0.4.0 - SARIF Upload & Polish + v0.4 + Deterministic Engine Pipeline

{#each [ - 'SARIF upload to GitHub Code Scanning', - 'Custom review/scan prompts', - 'Anti-hallucination filtering', - 'Shell completions (bash/zsh/fish)', - 'Z.AI provider support', + { title: 'Deterministic rule engine — 12 built-in rules', issue: 116 }, + { title: 'File bundling — parallel per-bundle review', issue: 115 }, + { title: 'AST-based cross-file dependency extraction', issue: 114 }, + { title: 'Hunk header regex panic fix + 5MB diff support', issue: 159 }, ] as item} - + {/each}
- +

- Phase A - Ecosystem & Performance + v0.5 + Install & Distribution

-

Shipped on demand — prioritized by community requests.

{#each [ - { title: 'Homebrew tap (brew install cora)', status: 'Planned' }, - { title: 'Parallel file review (multi-threaded)', status: 'Planned' }, - { title: 'Review summary (compact / detailed mode)', status: 'Planned' }, - { title: 'GitLab CI/CD integration guide', status: 'Planned' }, + { title: 'Easy install — Homebrew tap & install script', issue: 151, status: 'done' }, + { title: 'CI gate mode — block PRs on review findings', issue: 149, status: 'done' }, + { title: 'Website redesign — landing page + docs', issue: 163, status: 'done' }, + { title: 'Interactive auth login with tiered provider selection', issue: 172, status: 'done' }, + { title: 'README overhaul — market-facing copy', issue: 162, status: 'planned' }, ] as item} -
- {item.title} - {item.status} -
+ +
+ #{item.issue} + {item.title} +
+ {#if item.status === 'done'} + ✓ Done + {:else} + ◎ Planned + {/if} +
{/each}
- +

- Phase B - Editor & Team Features + Future + What's Next

-

Requires sufficient community adoption.

{#each [ - 'VS Code extension (LSP-based)', - 'JetBrains plugin', - 'Team config (.cora.yaml inheritance)', - 'Custom rule authoring API', + { title: 'Lightweight agent follow-up — 1 capped tool-call', issue: 117 }, + { title: '`cora gain` — local productivity stats + viral sharing', issue: 161 }, + { title: 'GitHub App backend MVP in Rust (Axum)', issue: 132 }, + { title: 'Publish cora-review as GitHub Marketplace action', issue: 47 }, ] as item} -
- {item} - Future -
+ +
+ #{item.issue} + {item.title} +
+ → Planned +
{/each}