@naeil/ui 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +60 -21
  2. package/dist/chunk-JBTDRVZ7.js +46 -0
  3. package/dist/chunk-SYI3IKIC.js +355 -0
  4. package/dist/components/index.d.ts +87 -0
  5. package/dist/components/index.js +832 -0
  6. package/dist/components/ui/index.d.ts +83 -0
  7. package/dist/components/ui/index.js +481 -0
  8. package/dist/lib/utils.d.ts +5 -0
  9. package/dist/lib/utils.js +7 -0
  10. package/package.json +52 -11
  11. package/src/app/globals.css +1 -1
  12. package/src/styles/theme.css +206 -0
  13. package/postcss.config.mjs +0 -7
  14. package/src/app/[locale]/(content)/baby-agent/page.tsx +0 -30
  15. package/src/app/[locale]/(content)/blog/page.tsx +0 -68
  16. package/src/app/[locale]/(content)/cc/page.tsx +0 -216
  17. package/src/app/[locale]/(content)/design/page.tsx +0 -703
  18. package/src/app/[locale]/(content)/layout.tsx +0 -7
  19. package/src/app/[locale]/(content)/pkm/page.tsx +0 -31
  20. package/src/app/[locale]/(content)/projects/page.tsx +0 -100
  21. package/src/app/[locale]/(content)/sa/page.tsx +0 -179
  22. package/src/app/[locale]/(landing)/page.tsx +0 -157
  23. package/src/app/[locale]/layout.tsx +0 -72
  24. package/src/app/[locale]/login/actions.ts +0 -10
  25. package/src/app/[locale]/login/oauth-buttons.tsx +0 -78
  26. package/src/app/[locale]/login/page.tsx +0 -85
  27. package/src/app/auth/callback/route.ts +0 -78
  28. package/src/app/favicon.ico +0 -0
  29. package/src/app/layout.tsx +0 -22
  30. package/src/app/sitemap.ts +0 -26
  31. package/src/components/accent-picker.tsx +0 -62
  32. package/src/components/auth-slot.tsx +0 -96
  33. package/src/components/footer-wrapper.tsx +0 -8
  34. package/src/components/footer.tsx +0 -193
  35. package/src/components/hero-scene.tsx +0 -948
  36. package/src/components/hero-section.tsx +0 -57
  37. package/src/components/locale-switcher.tsx +0 -74
  38. package/src/components/logo.tsx +0 -51
  39. package/src/components/nav-server-wrapper.tsx +0 -22
  40. package/src/components/nav-wrapper.tsx +0 -45
  41. package/src/components/nav.tsx +0 -550
  42. package/src/components/paraglider-cursor.tsx +0 -112
  43. package/src/components/project-layout.tsx +0 -194
  44. package/src/components/theme-provider.tsx +0 -10
  45. package/src/components/theme-toggle-icon.tsx +0 -62
  46. package/src/components/theme-toggle.tsx +0 -39
  47. package/src/components/typography.tsx +0 -27
  48. package/src/components/ui/avatar.tsx +0 -109
  49. package/src/components/ui/badge.tsx +0 -47
  50. package/src/components/ui/button.tsx +0 -65
  51. package/src/components/ui/card.tsx +0 -106
  52. package/src/components/ui/dialog.tsx +0 -158
  53. package/src/components/ui/dropdown-menu.tsx +0 -257
  54. package/src/components/ui/input.tsx +0 -21
  55. package/src/components/ui/sonner.tsx +0 -54
  56. package/src/components/workflow-diagram.tsx +0 -414
  57. package/src/i18n/config.ts +0 -8
  58. package/src/i18n/request.ts +0 -16
  59. package/src/i18n/routing.ts +0 -12
  60. package/src/lib/supabase/client.ts +0 -18
  61. package/src/lib/supabase/middleware.ts +0 -42
  62. package/src/lib/supabase/server.ts +0 -37
  63. package/src/lib/utils.ts +0 -6
  64. package/src/proxy.ts +0 -62
  65. package/src/tokens/.gitkeep +0 -0
  66. package/src/tokens/color.json +0 -56
  67. package/src/tokens/radius.json +0 -9
  68. package/src/tokens/semantic.json +0 -81
  69. package/src/tokens/shadow.json +0 -7
  70. package/src/tokens/spacing.json +0 -16
  71. package/src/tokens/typography.json +0 -34
  72. package/src/types/i18n.d.ts +0 -6
  73. package/src/utils/.gitkeep +0 -0
package/package.json CHANGED
@@ -1,7 +1,24 @@
1
1
  {
2
2
  "name": "@naeil/ui",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
+ "type": "module",
5
+ "license": "MIT",
6
+ "sideEffects": false,
4
7
  "exports": {
8
+ ".": {
9
+ "import": "./dist/components/index.js",
10
+ "types": "./dist/components/index.d.ts"
11
+ },
12
+ "./ui": {
13
+ "import": "./dist/components/ui/index.js",
14
+ "types": "./dist/components/ui/index.d.ts"
15
+ },
16
+ "./utils": {
17
+ "import": "./dist/lib/utils.js",
18
+ "types": "./dist/lib/utils.d.ts"
19
+ },
20
+ "./theme.css": "./src/styles/theme.css",
21
+ "./globals.css": "./src/app/globals.css",
5
22
  "./components/*": "./src/components/*.tsx",
6
23
  "./lib/*": "./src/lib/*.ts",
7
24
  "./i18n/*": "./src/i18n/*.ts"
@@ -9,11 +26,21 @@
9
26
  "scripts": {
10
27
  "dev": "next dev",
11
28
  "build": "next build",
29
+ "build:pkg": "tsup",
12
30
  "start": "next start",
13
31
  "lint": "eslint",
32
+ "test": "vitest run",
14
33
  "build:tokens": "tsx scripts/build-tokens.ts",
15
34
  "check:contrast": "tsx scripts/check-contrast.ts"
16
35
  },
36
+ "peerDependencies": {
37
+ "react": "^19",
38
+ "react-dom": "^19",
39
+ "next": "^15 || ^16",
40
+ "next-intl": "^4",
41
+ "next-themes": "^0.4",
42
+ "tailwind-merge": "^3"
43
+ },
17
44
  "dependencies": {
18
45
  "@react-three/drei": "^10.7.7",
19
46
  "@react-three/fiber": "^9.5.0",
@@ -22,7 +49,7 @@
22
49
  "class-variance-authority": "^0.7.1",
23
50
  "clsx": "^2.1.1",
24
51
  "lucide-react": "^0.575.0",
25
- "next": "16.1.6",
52
+ "next": "16.1.7",
26
53
  "next-intl": "^4.8.3",
27
54
  "next-themes": "^0.4.6",
28
55
  "pretendard": "^1.3.9",
@@ -34,22 +61,31 @@
34
61
  "three": "^0.183.2"
35
62
  },
36
63
  "devDependencies": {
64
+ "@axe-core/react": "^4.11.1",
37
65
  "@tailwindcss/postcss": "^4",
38
66
  "@types/node": "^20",
39
67
  "@types/react": "^19",
40
68
  "@types/react-dom": "^19",
41
69
  "@types/three": "^0.183.1",
42
70
  "eslint": "^9",
43
- "eslint-config-next": "16.1.6",
71
+ "eslint-config-next": "16.1.7",
44
72
  "eslint-config-prettier": "^10.1.8",
45
73
  "prettier": "^3.8.1",
46
74
  "shadcn": "^3.8.5",
47
75
  "style-dictionary": "^4.4.0",
48
76
  "tailwindcss": "^4",
77
+ "tsup": "^8.5.1",
49
78
  "tsx": "^4.21.0",
50
79
  "tw-animate-css": "^1.4.0",
51
- "typescript": "^5"
80
+ "typescript": "^5",
81
+ "vitest": "^4.1.0"
52
82
  },
83
+ "files": [
84
+ "dist/",
85
+ "src/styles/",
86
+ "src/app/globals.css",
87
+ "messages/"
88
+ ],
53
89
  "pnpm": {
54
90
  "onlyBuiltDependencies": [
55
91
  "esbuild",
@@ -57,17 +93,22 @@
57
93
  "@bundled-es-modules/glob"
58
94
  ]
59
95
  },
60
- "files": [
61
- "src/",
62
- "messages/",
63
- "tailwind.config.*",
64
- "postcss.config.*"
65
- ],
66
96
  "publishConfig": {
67
97
  "access": "public"
68
98
  },
69
99
  "repository": {
70
100
  "type": "git",
71
101
  "url": "https://github.com/naeil-dev/design-system"
72
- }
102
+ },
103
+ "description": "Design system for naeil.dev — React components, design tokens, and i18n support built with Next.js, Radix UI, and Tailwind CSS.",
104
+ "keywords": [
105
+ "design-system",
106
+ "react",
107
+ "components",
108
+ "tailwindcss",
109
+ "radix-ui",
110
+ "next.js",
111
+ "i18n"
112
+ ],
113
+ "homepage": "https://naeil.dev"
73
114
  }
@@ -1,7 +1,7 @@
1
1
  @import "tailwindcss";
2
2
  @import "tw-animate-css";
3
3
  @import "shadcn/tailwind.css";
4
- @import "../../dist/theme.css";
4
+ @import "../styles/theme.css";
5
5
 
6
6
  @custom-variant dark (&:is(.dark *));
7
7
 
@@ -0,0 +1,206 @@
1
+ @theme inline {
2
+ --color-background: var(--background);
3
+ --color-foreground: var(--foreground);
4
+ --color-card: var(--card);
5
+ --color-card-elevated: var(--card-elevated);
6
+ --color-card-foreground: var(--card-foreground);
7
+ --color-popover: var(--popover);
8
+ --color-popover-foreground: var(--popover-foreground);
9
+ --color-primary: var(--primary);
10
+ --color-primary-foreground: var(--primary-foreground);
11
+ --color-secondary: var(--secondary);
12
+ --color-secondary-foreground: var(--secondary-foreground);
13
+ --color-muted: var(--muted);
14
+ --color-muted-foreground: var(--muted-foreground);
15
+ --color-accent: var(--accent);
16
+ --color-accent-foreground: var(--accent-foreground);
17
+ --color-destructive: var(--destructive);
18
+ --color-destructive-foreground: var(--destructive-foreground);
19
+ --color-border: var(--border);
20
+ --color-border-subtle: var(--border-subtle);
21
+ --color-border-subtle-hover: var(--border-subtle-hover);
22
+ --color-surface-subtle: var(--surface-subtle);
23
+ --color-input: var(--input);
24
+ --color-ring: var(--ring);
25
+ --color-chart-1: var(--chart-1);
26
+ --color-chart-2: var(--chart-2);
27
+ --color-chart-3: var(--chart-3);
28
+ --color-chart-4: var(--chart-4);
29
+ --color-chart-5: var(--chart-5);
30
+ --color-sidebar: var(--sidebar);
31
+ --color-sidebar-foreground: var(--sidebar-foreground);
32
+ --color-sidebar-primary: var(--sidebar-primary);
33
+ --color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
34
+ --color-sidebar-accent: var(--sidebar-accent);
35
+ --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
36
+ --color-sidebar-border: var(--sidebar-border);
37
+ --color-sidebar-ring: var(--sidebar-ring);
38
+
39
+ --color-project-cc: var(--project-cc);
40
+ --color-project-sa: var(--project-sa);
41
+ --color-project-pkm: var(--project-pkm);
42
+ --color-project-naeilUi: var(--project-naeilUi);
43
+ --color-project-baby: var(--project-baby);
44
+
45
+ --font-sans: 'Pretendard Variable', Pretendard, -apple-system, system-ui, sans-serif;
46
+ --font-mono: 'JetBrains Mono', 'Geist Mono', ui-monospace, monospace;
47
+
48
+ --radius-none: var(--radius-none-value);
49
+ --radius-sm: var(--radius-sm-value);
50
+ --radius-md: var(--radius-md-value);
51
+ --radius-lg: var(--radius-lg-value);
52
+
53
+ --spacing-0: var(--spacing-0-value);
54
+ --spacing-1: var(--spacing-1-value);
55
+ --spacing-2: var(--spacing-2-value);
56
+ --spacing-3: var(--spacing-3-value);
57
+ --spacing-4: var(--spacing-4-value);
58
+ --spacing-5: var(--spacing-5-value);
59
+ --spacing-6: var(--spacing-6-value);
60
+ --spacing-8: var(--spacing-8-value);
61
+ --spacing-10: var(--spacing-10-value);
62
+ --spacing-12: var(--spacing-12-value);
63
+ --spacing-16: var(--spacing-16-value);
64
+ }
65
+
66
+ :root {
67
+ --background: oklch(1 0 0);
68
+ --foreground: oklch(0.145 0 0);
69
+ --card: oklch(1 0 0);
70
+ --card-elevated: oklch(1 0 0);
71
+ --card-foreground: oklch(0.145 0 0);
72
+ --popover: oklch(1 0 0);
73
+ --popover-foreground: oklch(0.145 0 0);
74
+ --primary: oklch(0.205 0 0);
75
+ --primary-foreground: oklch(0.985 0 0);
76
+ --secondary: oklch(0.970 0 0);
77
+ --secondary-foreground: oklch(0.205 0 0);
78
+ --muted: oklch(0.970 0 0);
79
+ --muted-foreground: oklch(0.556 0 0);
80
+ --accent: oklch(0.970 0 0);
81
+ --accent-foreground: oklch(0.205 0 0);
82
+ --destructive: oklch(0.577 0.245 27.325);
83
+ --destructive-foreground: oklch(0.985 0 0);
84
+ --border: oklch(0.922 0 0);
85
+ --border-subtle: oklch(0 0 0 / 6%);
86
+ --border-subtle-hover: oklch(0 0 0 / 12%);
87
+ --surface-subtle: oklch(0 0 0 / 2%);
88
+ --input: oklch(0.922 0 0);
89
+ --ring: oklch(0.708 0 0);
90
+ --chart-1: oklch(0.646 0.222 41.116);
91
+ --chart-2: oklch(0.6 0.118 184.704);
92
+ --chart-3: oklch(0.398 0.07 227.392);
93
+ --chart-4: oklch(0.828 0.189 84.429);
94
+ --chart-5: oklch(0.769 0.188 70.08);
95
+ --sidebar: oklch(0.985 0 0);
96
+ --sidebar-foreground: oklch(0.145 0 0);
97
+ --sidebar-primary: oklch(0.205 0 0);
98
+ --sidebar-primary-foreground: oklch(0.985 0 0);
99
+ --sidebar-accent: oklch(0.970 0 0);
100
+ --sidebar-accent-foreground: oklch(0.205 0 0);
101
+ --sidebar-border: oklch(0.922 0 0);
102
+ --sidebar-ring: oklch(0.708 0 0);
103
+
104
+ --project-cc: oklch(0.704 0.140 181);
105
+ --project-sa: oklch(0.723 0.219 149);
106
+ --project-pkm: oklch(0.627 0.265 303);
107
+ --project-naeilUi: oklch(0.623 0.214 259);
108
+ --project-baby: oklch(0.769 0.188 70.08);
109
+
110
+ --radius-none-value: 0px;
111
+ --radius-sm-value: 2px;
112
+ --radius-md-value: 4px;
113
+ --radius-lg-value: 8px;
114
+
115
+ --spacing-0-value: 0px;
116
+ --spacing-1-value: 4px;
117
+ --spacing-2-value: 8px;
118
+ --spacing-3-value: 12px;
119
+ --spacing-4-value: 16px;
120
+ --spacing-5-value: 20px;
121
+ --spacing-6-value: 24px;
122
+ --spacing-8-value: 32px;
123
+ --spacing-10-value: 40px;
124
+ --spacing-12-value: 48px;
125
+ --spacing-16-value: 64px;
126
+ }
127
+
128
+ .dark {
129
+ --background: oklch(0.145 0 0);
130
+ --foreground: oklch(0.985 0 0);
131
+ --card: oklch(0.205 0 0);
132
+ --card-elevated: oklch(0.18 0 0);
133
+ --card-foreground: oklch(0.985 0 0);
134
+ --popover: oklch(0.205 0 0);
135
+ --popover-foreground: oklch(0.985 0 0);
136
+ --primary: oklch(0.922 0 0);
137
+ --primary-foreground: oklch(0.205 0 0);
138
+ --secondary: oklch(0.269 0 0);
139
+ --secondary-foreground: oklch(0.985 0 0);
140
+ --muted: oklch(0.269 0 0);
141
+ --muted-foreground: oklch(0.708 0 0);
142
+ --accent: oklch(0.269 0 0);
143
+ --accent-foreground: oklch(0.985 0 0);
144
+ --destructive: oklch(0.577 0.245 27.325);
145
+ --destructive-foreground: oklch(0.985 0 0);
146
+ --border: oklch(1 0 0 / 10%);
147
+ --border-subtle: oklch(1 0 0 / 6%);
148
+ --border-subtle-hover: oklch(1 0 0 / 12%);
149
+ --surface-subtle: oklch(1 0 0 / 3%);
150
+ --input: oklch(1 0 0 / 15%);
151
+ --ring: oklch(0.556 0 0);
152
+ --chart-1: oklch(0.488 0.243 264.376);
153
+ --chart-2: oklch(0.696 0.17 162.48);
154
+ --chart-3: oklch(0.769 0.188 70.08);
155
+ --chart-4: oklch(0.627 0.265 303.9);
156
+ --chart-5: oklch(0.645 0.246 16.439);
157
+ --sidebar: oklch(0.205 0 0);
158
+ --sidebar-foreground: oklch(0.985 0 0);
159
+ --sidebar-primary: oklch(0.488 0.243 264.376);
160
+ --sidebar-primary-foreground: oklch(0.985 0 0);
161
+ --sidebar-accent: oklch(0.269 0 0);
162
+ --sidebar-accent-foreground: oklch(0.985 0 0);
163
+ --sidebar-border: oklch(1 0 0 / 10%);
164
+ --sidebar-ring: oklch(0.556 0 0);
165
+ }
166
+
167
+ @media (prefers-color-scheme: dark) {
168
+ :root:not(.light) {
169
+ --background: oklch(0.145 0 0);
170
+ --foreground: oklch(0.985 0 0);
171
+ --card: oklch(0.205 0 0);
172
+ --card-elevated: oklch(0.18 0 0);
173
+ --card-foreground: oklch(0.985 0 0);
174
+ --popover: oklch(0.205 0 0);
175
+ --popover-foreground: oklch(0.985 0 0);
176
+ --primary: oklch(0.922 0 0);
177
+ --primary-foreground: oklch(0.205 0 0);
178
+ --secondary: oklch(0.269 0 0);
179
+ --secondary-foreground: oklch(0.985 0 0);
180
+ --muted: oklch(0.269 0 0);
181
+ --muted-foreground: oklch(0.708 0 0);
182
+ --accent: oklch(0.269 0 0);
183
+ --accent-foreground: oklch(0.985 0 0);
184
+ --destructive: oklch(0.577 0.245 27.325);
185
+ --destructive-foreground: oklch(0.985 0 0);
186
+ --border: oklch(1 0 0 / 10%);
187
+ --border-subtle: oklch(1 0 0 / 6%);
188
+ --border-subtle-hover: oklch(1 0 0 / 12%);
189
+ --surface-subtle: oklch(1 0 0 / 3%);
190
+ --input: oklch(1 0 0 / 15%);
191
+ --ring: oklch(0.556 0 0);
192
+ --chart-1: oklch(0.488 0.243 264.376);
193
+ --chart-2: oklch(0.696 0.17 162.48);
194
+ --chart-3: oklch(0.769 0.188 70.08);
195
+ --chart-4: oklch(0.627 0.265 303.9);
196
+ --chart-5: oklch(0.645 0.246 16.439);
197
+ --sidebar: oklch(0.205 0 0);
198
+ --sidebar-foreground: oklch(0.985 0 0);
199
+ --sidebar-primary: oklch(0.488 0.243 264.376);
200
+ --sidebar-primary-foreground: oklch(0.985 0 0);
201
+ --sidebar-accent: oklch(0.269 0 0);
202
+ --sidebar-accent-foreground: oklch(0.985 0 0);
203
+ --sidebar-border: oklch(1 0 0 / 10%);
204
+ --sidebar-ring: oklch(0.556 0 0);
205
+ }
206
+ }
@@ -1,7 +0,0 @@
1
- const config = {
2
- plugins: {
3
- "@tailwindcss/postcss": {},
4
- },
5
- };
6
-
7
- export default config;
@@ -1,30 +0,0 @@
1
- import { setRequestLocale } from "next-intl/server";
2
- import { useTranslations } from "next-intl";
3
- import { ProjectLayout } from "@/components/project-layout";
4
- import type { ProjectData } from "@/components/project-layout";
5
-
6
- export default async function BabyAgentPage({
7
- params,
8
- }: {
9
- params: Promise<{ locale: string }>;
10
- }) {
11
- const { locale } = await params;
12
- setRequestLocale(locale);
13
-
14
- return <BabyAgentContent />;
15
- }
16
-
17
- function BabyAgentContent() {
18
- const t = useTranslations("babyAgent");
19
-
20
- const data: ProjectData = {
21
- icon: "/images/turtle.png",
22
- name: t("name"),
23
- description: t("description"),
24
- accent: "oklch(0.769 0.188 70.08)",
25
- tags: ["OpenClaw", "LINE", "AI Agent"],
26
- comingSoon: true,
27
- };
28
-
29
- return <ProjectLayout data={data} />;
30
- }
@@ -1,68 +0,0 @@
1
- import { setRequestLocale } from "next-intl/server";
2
- import { useTranslations } from "next-intl";
3
- import { PageTitle } from "@/components/typography";
4
- import Image from "next/image";
5
-
6
- export default async function BlogPage({
7
- params,
8
- }: {
9
- params: Promise<{ locale: string }>;
10
- }) {
11
- const { locale } = await params;
12
- setRequestLocale(locale);
13
-
14
- return <BlogContent />;
15
- }
16
-
17
- function BlogContent() {
18
- const t = useTranslations("blogPage");
19
-
20
- return (
21
- <>
22
- <section className="mx-auto max-w-4xl px-6 pb-16">
23
- <div className="flex flex-col-reverse items-start gap-8 md:flex-row md:items-start md:justify-between">
24
- <div className="flex-1">
25
- <PageTitle className="mb-3">{t("title")}</PageTitle>
26
- <p className="text-muted-foreground mb-5 max-w-lg text-lg leading-relaxed">
27
- {t("subtitle")}
28
- </p>
29
- <div className="mb-6 flex flex-wrap gap-2">
30
- {[
31
- "Deep Dive",
32
- "Research",
33
- "Build Logs",
34
- ].map((tag) => (
35
- <span
36
- key={tag}
37
- className="rounded-full border border-border-subtle px-2.5 py-1 text-[11px] text-zinc-400"
38
- >
39
- {tag}
40
- </span>
41
- ))}
42
- </div>
43
- </div>
44
-
45
- <div className="flex-shrink-0">
46
- <Image
47
- src="/images/diver.png"
48
- alt=""
49
- width={220}
50
- height={220}
51
- className="animate-float object-contain"
52
- style={{
53
- filter:
54
- "drop-shadow(0 4px 12px color-mix(in oklch, var(--project-naeilUi) 15%, transparent))",
55
- }}
56
- />
57
- </div>
58
- </div>
59
- </section>
60
-
61
- <section className="mx-auto max-w-4xl px-6 pb-24">
62
- <div className="rounded-2xl border border-dashed border-border-subtle p-12 text-center">
63
- <p className="text-muted-foreground text-sm">{t("comingSoon")}</p>
64
- </div>
65
- </section>
66
- </>
67
- );
68
- }
@@ -1,216 +0,0 @@
1
- import { setRequestLocale } from "next-intl/server";
2
- import { useTranslations } from "next-intl";
3
- import { ProjectLayout } from "@/components/project-layout";
4
- import type { ProjectData } from "@/components/project-layout";
5
-
6
- export default async function CCPage({
7
- params,
8
- }: {
9
- params: Promise<{ locale: string }>;
10
- }) {
11
- const { locale } = await params;
12
- setRequestLocale(locale);
13
-
14
- return <CCContent />;
15
- }
16
-
17
- function CCContent() {
18
- const t = useTranslations("cc");
19
-
20
- const data: ProjectData = {
21
- icon: "/images/coral.png",
22
- name: t("name"),
23
- description: t("description"),
24
- accent: "oklch(0.704 0.140 181)",
25
- tags: ["Python", "PostgreSQL", "Ollama", "Gemini", "LINE"],
26
- github: "https://github.com/naeil-dev/content-collector",
27
-
28
- overview: t("overview"),
29
-
30
- features: [
31
- {
32
- icon: "📡",
33
- title: t("features.collect.title"),
34
- description: t("features.collect.desc"),
35
- },
36
- {
37
- icon: "🤖",
38
- title: t("features.classify.title"),
39
- description: t("features.classify.desc"),
40
- },
41
- {
42
- icon: "🧲",
43
- title: t("features.embed.title"),
44
- description: t("features.embed.desc"),
45
- },
46
- {
47
- icon: "📊",
48
- title: t("features.digest.title"),
49
- description: t("features.digest.desc"),
50
- },
51
- {
52
- icon: "⚡",
53
- title: t("features.zeroCost.title"),
54
- description: t("features.zeroCost.desc"),
55
- },
56
- {
57
- icon: "🔔",
58
- title: t("features.alerts.title"),
59
- description: t("features.alerts.desc"),
60
- },
61
- ],
62
-
63
- workflow: {
64
- nodes: [
65
- {
66
- id: "github",
67
- label: "GitHub RSS",
68
- type: "source",
69
- position: { x: 20, y: 5 },
70
- detail: {
71
- description: t("workflow.github.desc"),
72
- tech: ["feedparser", "httpx"],
73
- meta: t("workflow.github.meta"),
74
- },
75
- },
76
- {
77
- id: "reddit",
78
- label: "Reddit",
79
- type: "source",
80
- position: { x: 50, y: 5 },
81
- detail: {
82
- description: t("workflow.reddit.desc"),
83
- tech: ["RSS", "JSON API"],
84
- meta: t("workflow.reddit.meta"),
85
- },
86
- },
87
- {
88
- id: "threads",
89
- label: "Threads",
90
- type: "source",
91
- position: { x: 80, y: 5 },
92
- detail: {
93
- description: t("workflow.threads.desc"),
94
- tech: ["Playwright", "httpx"],
95
- meta: t("workflow.threads.meta"),
96
- },
97
- },
98
- {
99
- id: "collector",
100
- label: "Collector",
101
- type: "process",
102
- position: { x: 50, y: 22 },
103
- detail: {
104
- description: t("workflow.collector.desc"),
105
- tech: ["Python", "LaunchAgent"],
106
- meta: t("workflow.collector.meta"),
107
- },
108
- },
109
- {
110
- id: "postgres",
111
- label: "PostgreSQL",
112
- type: "storage",
113
- position: { x: 50, y: 38 },
114
- detail: {
115
- description: t("workflow.postgres.desc"),
116
- tech: ["PostgreSQL 17", "pgvector", "Docker"],
117
- },
118
- },
119
- {
120
- id: "embed",
121
- label: "BGE-M3",
122
- type: "ai",
123
- position: { x: 25, y: 53 },
124
- detail: {
125
- description: t("workflow.embed.desc"),
126
- tech: ["Ollama", "BGE-M3"],
127
- meta: t("workflow.embed.meta"),
128
- },
129
- },
130
- {
131
- id: "classify",
132
- label: "Qwen3 14B",
133
- type: "ai",
134
- position: { x: 75, y: 53 },
135
- detail: {
136
- description: t("workflow.classify.desc"),
137
- tech: ["Ollama", "Qwen3 14B"],
138
- meta: t("workflow.classify.meta"),
139
- },
140
- },
141
- {
142
- id: "cluster",
143
- label: "Cluster + Score",
144
- type: "process",
145
- position: { x: 50, y: 68 },
146
- detail: {
147
- description: t("workflow.cluster.desc"),
148
- tech: ["pgvector", "cosine similarity"],
149
- },
150
- },
151
- {
152
- id: "digest",
153
- label: "Gemini Flash",
154
- type: "ai",
155
- position: { x: 50, y: 82 },
156
- detail: {
157
- description: t("workflow.digest.desc"),
158
- tech: ["Gemini 2.5 Flash", "Jinja2"],
159
- meta: t("workflow.digest.meta"),
160
- },
161
- },
162
- {
163
- id: "line",
164
- label: "LINE Summary",
165
- type: "output",
166
- position: { x: 30, y: 95 },
167
- detail: {
168
- description: t("workflow.line.desc"),
169
- tech: ["LINE Push API"],
170
- },
171
- },
172
- {
173
- id: "html",
174
- label: "HTML Digest",
175
- type: "output",
176
- position: { x: 70, y: 95 },
177
- detail: {
178
- description: t("workflow.html.desc"),
179
- tech: ["Jinja2", "HTML"],
180
- meta: "digest.naeil.dev",
181
- },
182
- },
183
- ],
184
- edges: [
185
- { from: "github", to: "collector" },
186
- { from: "reddit", to: "collector" },
187
- { from: "threads", to: "collector" },
188
- { from: "collector", to: "postgres" },
189
- { from: "postgres", to: "embed" },
190
- { from: "postgres", to: "classify" },
191
- { from: "embed", to: "cluster" },
192
- { from: "classify", to: "cluster" },
193
- { from: "cluster", to: "digest" },
194
- { from: "digest", to: "line" },
195
- { from: "digest", to: "html" },
196
- ],
197
- },
198
-
199
- stack: [
200
- { icon: "🐍", name: "Python 3.12" },
201
- { icon: "🐘", name: "PostgreSQL 17" },
202
- { icon: "🧮", name: "pgvector" },
203
- { icon: "🦙", name: "Ollama" },
204
- { icon: "🤖", name: "Qwen3 14B" },
205
- { icon: "🔤", name: "BGE-M3" },
206
- { icon: "✨", name: "Gemini 2.5 Flash" },
207
- { icon: "📱", name: "LINE API" },
208
- { icon: "🤖", name: "Telegram Bot API" },
209
- { icon: "🐳", name: "Docker Compose" },
210
- { icon: "⏰", name: "LaunchAgent" },
211
- { icon: "🎭", name: "Playwright" },
212
- ],
213
- };
214
-
215
- return <ProjectLayout data={data} />;
216
- }