@programinglive/dev-workflow-mcp-server 1.8.0 → 1.9.1

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 (106) hide show
  1. package/.env.example +21 -1
  2. package/AGENTS.md +25 -0
  3. package/README.md +257 -664
  4. package/index.js +5 -4
  5. package/package.json +11 -6
  6. package/scripts/bootstrap-unix.sh +55 -0
  7. package/scripts/bootstrap-windows.ps1 +75 -0
  8. package/scripts/install-husky.js +43 -0
  9. package/scripts/setup-stack.js +436 -0
  10. package/tools/definitions.js +19 -0
  11. package/tools/handler-modules/commit-handlers.js +2 -1
  12. package/tools/handler-modules/index.js +13 -7
  13. package/tools/handler-modules/shared.js +7 -41
  14. package/tools/handler-modules/status-handlers.js +3 -1
  15. package/tools/handler-modules/workflow-handlers.js +26 -8
  16. package/workflow-state.js +10 -0
  17. package/.agent/workflows/dev-workflow-bugfix.md +0 -250
  18. package/.agent/workflows/dev-workflow-feature.md +0 -201
  19. package/.agent/workflows/dev-workflow-full-cycle.md +0 -400
  20. package/.agent/workflows/dev-workflow-refactor.md +0 -238
  21. package/.env.production +0 -16
  22. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -34
  23. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -25
  24. package/.github/pull_request_template.md +0 -22
  25. package/.github/workflows/github-release.yml +0 -131
  26. package/.husky/commit-msg +0 -3
  27. package/.husky/pre-commit +0 -2
  28. package/CHANGELOG.md +0 -1137
  29. package/docs/GCP_DEPLOYMENT.md +0 -298
  30. package/docs/NETLIFY_DEPLOYMENT.md +0 -125
  31. package/docs/PLESK_DEPLOYMENT.md +0 -170
  32. package/docs/PRD.md +0 -83
  33. package/docs/WORKFLOW-BEST-PRACTICES.md +0 -58
  34. package/docs/antigravity/EXAMPLES.md +0 -535
  35. package/docs/antigravity/GETTING-STARTED.md +0 -292
  36. package/docs/antigravity/TROUBLESHOOTING.md +0 -742
  37. package/docs/antigravity/WALKTHROUGH.md +0 -25
  38. package/docs/antigravity/WORKFLOW-TEMPLATES.md +0 -670
  39. package/docs/release-notes/RELEASE_NOTES.md +0 -516
  40. package/docs/web-dashboard.md +0 -175
  41. package/tailwind.config.js +0 -8
  42. package/tests/build.test.js +0 -74
  43. package/tests/db-adapters.test.js +0 -108
  44. package/tests/env-support.test.js +0 -46
  45. package/tests/exec.test.js +0 -35
  46. package/tests/handlers-commit.test.js +0 -174
  47. package/tests/handlers-release.test.js +0 -212
  48. package/tests/handlers-workflow.test.js +0 -68
  49. package/tests/handlers.test.js +0 -1142
  50. package/tests/hello-world.test.js +0 -13
  51. package/tests/mcpRegistry.test.js +0 -65
  52. package/tests/patch-release.test.js +0 -7
  53. package/tests/release-wrapper.test.js +0 -107
  54. package/tests/startup-resilience.test.js +0 -73
  55. package/tests/test-helpers.js +0 -50
  56. package/tests/workflowState.test.js +0 -520
  57. package/web/Dockerfile.api +0 -25
  58. package/web/README.md +0 -133
  59. package/web/__tests__/api/workflow-history.test.js +0 -63
  60. package/web/api-server.js +0 -211
  61. package/web/app/docs/page.tsx +0 -202
  62. package/web/app/favicon.ico +0 -0
  63. package/web/app/globals.css +0 -91
  64. package/web/app/history/page.tsx +0 -220
  65. package/web/app/layout.tsx +0 -39
  66. package/web/app/login/page.tsx +0 -142
  67. package/web/app/page.tsx +0 -13
  68. package/web/components/ApiReference.tsx +0 -20
  69. package/web/components/Features.tsx +0 -61
  70. package/web/components/Footer.tsx +0 -9
  71. package/web/components/Hero.tsx +0 -96
  72. package/web/components/History.tsx +0 -175
  73. package/web/components/Navbar.tsx +0 -208
  74. package/web/components/Terminal.tsx +0 -114
  75. package/web/components/ThemeProvider.tsx +0 -58
  76. package/web/eslint.config.mjs +0 -18
  77. package/web/lib/api-client.ts +0 -123
  78. package/web/lib/auth.js +0 -75
  79. package/web/lib/db.js +0 -131
  80. package/web/lib/docs.js +0 -73
  81. package/web/middleware/auth.js +0 -26
  82. package/web/netlify.toml +0 -8
  83. package/web/next.config.ts +0 -19
  84. package/web/package-lock.json +0 -10911
  85. package/web/package.json +0 -42
  86. package/web/postcss.config.mjs +0 -9
  87. package/web/public/assets/android-chrome-192x192.png +0 -0
  88. package/web/public/assets/android-chrome-512x512.png +0 -0
  89. package/web/public/assets/apple-touch-icon.png +0 -0
  90. package/web/public/assets/favicon-16x16.png +0 -0
  91. package/web/public/assets/favicon-32x32.png +0 -0
  92. package/web/public/assets/favicon.ico +0 -0
  93. package/web/public/assets/favicon.png +0 -0
  94. package/web/public/assets/logo.png +0 -0
  95. package/web/public/assets/og-preview.png +0 -0
  96. package/web/public/assets/site.webmanifest +0 -1
  97. package/web/public/file.svg +0 -1
  98. package/web/public/globe.svg +0 -1
  99. package/web/public/next.svg +0 -1
  100. package/web/public/vercel.svg +0 -1
  101. package/web/public/window.svg +0 -1
  102. package/web/scripts/db-query-history.js +0 -120
  103. package/web/scripts/smoke-test.js +0 -30
  104. package/web/server.js +0 -184
  105. package/web/tailwind.config.ts +0 -20
  106. package/web/tsconfig.json +0 -42
@@ -1,220 +0,0 @@
1
- 'use client';
2
-
3
- import { useEffect, useState, useMemo } from 'react';
4
- import { useRouter } from 'next/navigation';
5
- import { apiClient } from '@/lib/api-client';
6
- import {
7
- CheckCircle,
8
- XCircle,
9
- AlertTriangle,
10
- GitCommit,
11
- FileText,
12
- Activity,
13
- Search,
14
- Filter,
15
- Calendar,
16
- BarChart3
17
- } from 'lucide-react';
18
-
19
- interface WorkflowHistoryItem {
20
- id: number;
21
- task_type: string;
22
- description: string;
23
- commit_message: string;
24
- completed_at: string;
25
- tests_passed: boolean;
26
- documentation_type: string;
27
- }
28
-
29
- export default function HistoryPage() {
30
- const [isAuthenticated, setIsAuthenticated] = useState(false);
31
- const [loading, setLoading] = useState(true);
32
- const [history, setHistory] = useState<WorkflowHistoryItem[]>([]);
33
- const [searchQuery, setSearchQuery] = useState('');
34
- const [typeFilter, setTypeFilter] = useState<string>('all');
35
- const router = useRouter();
36
-
37
- useEffect(() => {
38
- const loadData = async () => {
39
- try {
40
- // Verify auth
41
- const user = await apiClient.getCurrentUser();
42
- if (!user) {
43
- throw new Error('Not authenticated');
44
- }
45
-
46
- setIsAuthenticated(true);
47
- // Sync auth state
48
- localStorage.setItem('isLoggedIn', 'true');
49
- window.dispatchEvent(new Event('authUpdate'));
50
-
51
- // Fetch history
52
- const result = await apiClient.getHistory();
53
- if (result?.history) {
54
- setHistory(result.history);
55
- }
56
- } catch (error) {
57
- console.error('History load error:', error);
58
- router.push('/login');
59
- } finally {
60
- setLoading(false);
61
- }
62
- };
63
-
64
- loadData();
65
- }, [router]);
66
-
67
- const stats = useMemo(() => {
68
- const total = history.length;
69
- const features = history.filter(h => h.task_type === 'feature').length;
70
- const bugs = history.filter(h => h.task_type === 'bugfix').length;
71
- const passedTests = history.filter(h => h.tests_passed).length;
72
- const successRate = total > 0 ? Math.round((passedTests / total) * 100) : 0;
73
-
74
- return { total, features, bugs, successRate };
75
- }, [history]);
76
-
77
- const filteredHistory = useMemo(() => {
78
- return history.filter(item => {
79
- const matchesSearch = item.description.toLowerCase().includes(searchQuery.toLowerCase()) ||
80
- item.commit_message.toLowerCase().includes(searchQuery.toLowerCase());
81
- const matchesType = typeFilter === 'all' || item.task_type === typeFilter;
82
- return matchesSearch && matchesType;
83
- });
84
- }, [history, searchQuery, typeFilter]);
85
-
86
- if (loading) {
87
- return (
88
- <div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-[#0a0a0f]">
89
- <div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-indigo-500"></div>
90
- </div>
91
- );
92
- }
93
-
94
- if (!isAuthenticated) return null;
95
-
96
- return (
97
- <div className="min-h-screen pt-24 pb-12 px-4 sm:px-6 lg:px-8 bg-gray-50 dark:bg-[#0a0a0f] transition-colors duration-300">
98
- <div className="max-w-7xl mx-auto space-y-8">
99
- {/* Header */}
100
- <div>
101
- <h1 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-2">Workflow Insights</h1>
102
- <p className="text-gray-600 dark:text-gray-400">Track and analyze your development velocity and quality.</p>
103
- </div>
104
-
105
- {/* Stats Grid */}
106
- <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
107
- <StatCard icon={<Activity className="w-5 h-5 text-indigo-500" />} label="Total Tasks" value={stats.total} />
108
- <StatCard icon={<CheckCircle className="w-5 h-5 text-green-500" />} label="Success Rate" value={`${stats.successRate}%`} />
109
- <StatCard icon={<BarChart3 className="w-5 h-5 text-blue-500" />} label="Features Built" value={stats.features} />
110
- <StatCard icon={<AlertTriangle className="w-5 h-5 text-red-500" />} label="Bugs Fixed" value={stats.bugs} />
111
- </div>
112
-
113
- {/* Controls */}
114
- <div className="flex flex-col sm:flex-row gap-4 items-center justify-between bg-white dark:bg-white/5 p-4 rounded-xl border border-gray-200 dark:border-white/10">
115
- <div className="relative w-full sm:w-96">
116
- <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-gray-400" />
117
- <input
118
- type="text"
119
- placeholder="Search tasks, commits..."
120
- value={searchQuery}
121
- onChange={(e) => setSearchQuery(e.target.value)}
122
- className="w-full pl-10 pr-4 py-2 bg-gray-100 dark:bg-black/20 border border-gray-200 dark:border-white/10 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 text-gray-900 dark:text-white placeholder-gray-500"
123
- />
124
- </div>
125
- <div className="flex gap-2 w-full sm:w-auto">
126
- <select
127
- value={typeFilter}
128
- onChange={(e) => setTypeFilter(e.target.value)}
129
- className="px-4 py-2 bg-gray-100 dark:bg-black/20 border border-gray-200 dark:border-white/10 rounded-lg focus:outline-none focus:ring-2 focus:ring-indigo-500 text-gray-900 dark:text-white"
130
- >
131
- <option value="all">All Types</option>
132
- <option value="feature">Features</option>
133
- <option value="bugfix">Bug Fixes</option>
134
- <option value="refactor">Refactors</option>
135
- </select>
136
- </div>
137
- </div>
138
-
139
- {/* Timeline */}
140
- <div className="space-y-6 relative before:absolute before:inset-0 before:ml-5 before:-translate-x-px md:before:mx-auto md:before:translate-x-0 before:h-full before:w-0.5 before:bg-gradient-to-b before:from-transparent before:via-gray-300 before:dark:via-white/20 before:to-transparent">
141
- {filteredHistory.length === 0 ? (
142
- <div className="text-center py-12">
143
- <p className="text-gray-500 dark:text-gray-400">No workflow history found.</p>
144
- </div>
145
- ) : (
146
- filteredHistory.map((item, index) => (
147
- <div key={item.id} className="relative flex items-center justify-between md:justify-normal md:odd:flex-row-reverse group is-active">
148
- {/* Icon */}
149
- <div className="flex items-center justify-center w-10 h-10 rounded-full border border-white dark:border-[#0a0a0f] bg-gray-100 dark:bg-white/10 shadow shrink-0 md:order-1 md:group-odd:-translate-x-1/2 md:group-even:translate-x-1/2 z-10">
150
- {getTaskIcon(item.task_type)}
151
- </div>
152
-
153
- {/* Card */}
154
- <div className="w-[calc(100%-4rem)] md:w-[calc(50%-2.5rem)] bg-white dark:bg-white/5 p-6 rounded-xl border border-gray-200 dark:border-white/10 shadow-sm hover:shadow-md transition-all duration-300">
155
- <div className="flex items-center justify-between mb-3">
156
- <span className={`px-2.5 py-0.5 rounded-full text-xs font-medium uppercase tracking-wide ${getTypeColor(item.task_type)}`}>
157
- {item.task_type}
158
- </span>
159
- <time className="text-xs text-gray-500 dark:text-gray-400 font-mono">
160
- {new Date(item.completed_at).toLocaleDateString()}
161
- </time>
162
- </div>
163
- <h3 className="text-lg font-bold text-gray-900 dark:text-white mb-2">{item.description}</h3>
164
- <div className="flex items-center gap-2 text-sm text-gray-600 dark:text-gray-400 mb-4 bg-gray-50 dark:bg-black/20 p-2 rounded-lg break-all font-mono">
165
- <GitCommit className="w-4 h-4 shrink-0" />
166
- {item.commit_message}
167
- </div>
168
- <div className="flex flex-wrap items-center gap-3 pt-3 border-t border-gray-100 dark:border-white/10">
169
- <div className={`flex items-center gap-1.5 text-xs font-medium ${item.tests_passed ? 'text-green-600 dark:text-green-400' : 'text-yellow-600 dark:text-yellow-400'}`}>
170
- {item.tests_passed ? <CheckCircle className="w-3.5 h-3.5" /> : <AlertTriangle className="w-3.5 h-3.5" />}
171
- {item.tests_passed ? 'Tests Passed' : 'Tests Skipped'}
172
- </div>
173
- {item.documentation_type && (
174
- <div className="flex items-center gap-1.5 text-xs font-medium text-blue-600 dark:text-blue-400">
175
- <FileText className="w-3.5 h-3.5" />
176
- {item.documentation_type}
177
- </div>
178
- )}
179
- </div>
180
- </div>
181
- </div>
182
- ))
183
- )}
184
- </div>
185
- </div>
186
- </div>
187
- );
188
- }
189
-
190
- function StatCard({ icon, label, value }: { icon: React.ReactNode, label: string, value: string | number }) {
191
- return (
192
- <div className="bg-white dark:bg-white/5 p-6 rounded-xl border border-gray-200 dark:border-white/10 shadow-sm">
193
- <div className="flex items-center gap-4">
194
- <div className="p-3 bg-gray-50 dark:bg-white/5 rounded-lg">
195
- {icon}
196
- </div>
197
- <div>
198
- <p className="text-sm font-medium text-gray-500 dark:text-gray-400">{label}</p>
199
- <p className="text-2xl font-bold text-gray-900 dark:text-white">{value}</p>
200
- </div>
201
- </div>
202
- </div>
203
- );
204
- }
205
-
206
- function getTaskIcon(type: string) {
207
- switch (type) {
208
- case 'feature': return <CheckCircle className="w-5 h-5 text-blue-500" />;
209
- case 'bugfix': return <XCircle className="w-5 h-5 text-red-500" />;
210
- default: return <Activity className="w-5 h-5 text-gray-500" />;
211
- }
212
- }
213
-
214
- function getTypeColor(type: string) {
215
- switch (type) {
216
- case 'feature': return 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300';
217
- case 'bugfix': return 'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-300';
218
- default: return 'bg-gray-100 text-gray-800 dark:bg-gray-800/50 dark:text-gray-300';
219
- }
220
- }
@@ -1,39 +0,0 @@
1
- import type { Metadata } from "next";
2
- import "./globals.css";
3
- import Navbar from "@/components/Navbar";
4
- import Footer from "@/components/Footer";
5
- import { ThemeProvider } from "@/components/ThemeProvider";
6
-
7
- export const metadata: Metadata = {
8
- title: "Dev Workflow Dashboard",
9
- description: "Enforce development discipline and best practices",
10
- icons: {
11
- icon: [
12
- { url: "/assets/favicon-16x16.png", sizes: "16x16", type: "image/png" },
13
- { url: "/assets/favicon-32x32.png", sizes: "32x32", type: "image/png" },
14
- { url: "/assets/favicon.ico" },
15
- ],
16
- apple: [
17
- { url: "/assets/apple-touch-icon.png", sizes: "180x180", type: "image/png" },
18
- ],
19
- },
20
- manifest: "/assets/site.webmanifest",
21
- };
22
-
23
- export default function RootLayout({
24
- children,
25
- }: Readonly<{
26
- children: React.ReactNode;
27
- }>) {
28
- return (
29
- <html lang="en" className="scroll-smooth" data-scroll-behavior="smooth">
30
- <body className="antialiased bg-white dark:bg-[#0a0a0f] text-gray-900 dark:text-white transition-colors duration-300">
31
- <ThemeProvider>
32
- <Navbar />
33
- {children}
34
- <Footer />
35
- </ThemeProvider>
36
- </body>
37
- </html>
38
- );
39
- }
@@ -1,142 +0,0 @@
1
- 'use client';
2
-
3
- import { useState, useEffect } from 'react';
4
- import { useRouter } from 'next/navigation';
5
- import Image from 'next/image';
6
- import { Lock, User } from 'lucide-react';
7
- import { apiClient } from '@/lib/api-client';
8
-
9
- export default function LoginPage() {
10
- const [username, setUsername] = useState('');
11
- const [password, setPassword] = useState('');
12
- const [error, setError] = useState('');
13
- const [loading, setLoading] = useState(false);
14
- const [authChecking, setAuthChecking] = useState(true);
15
- const router = useRouter();
16
-
17
- useEffect(() => {
18
- // Check if already logged in
19
- const mightBeLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
20
- if (!mightBeLoggedIn) {
21
- setAuthChecking(false);
22
- return;
23
- }
24
-
25
- apiClient.getCurrentUser()
26
- .then(user => {
27
- if (user) {
28
- router.push('/history');
29
- }
30
- })
31
- .catch(() => { })
32
- .finally(() => setAuthChecking(false));
33
- }, [router]);
34
-
35
- const handleSubmit = async (e: React.FormEvent) => {
36
- e.preventDefault();
37
- setError('');
38
- setLoading(true);
39
-
40
- try {
41
- const data = await apiClient.login(username, password);
42
-
43
- if (data.success) {
44
- localStorage.setItem('isLoggedIn', 'true');
45
- window.dispatchEvent(new Event('authUpdate'));
46
- router.push('/history');
47
- } else {
48
- setError('Login failed');
49
- }
50
- } catch (err: any) {
51
- setError(err.message || 'Network error. Please try again.');
52
- } finally {
53
- setLoading(false);
54
- }
55
- };
56
-
57
- if (authChecking) {
58
- return null; // Or a loading spinner
59
- }
60
-
61
- return (
62
- <div className="min-h-screen flex items-center justify-center bg-gray-50 dark:bg-[#0a0a0f] px-4 transition-colors duration-300">
63
- <div className="max-w-md w-full space-y-8 bg-white dark:bg-white/5 p-8 rounded-2xl shadow-xl border border-gray-100 dark:border-white/10">
64
- <div className="text-center">
65
- <div className="mx-auto h-12 w-12 relative mb-4">
66
- <div className="absolute inset-0 bg-blue-500 rounded-xl blur opacity-20 dark:opacity-40"></div>
67
- <Image src="/assets/logo.png" alt="Logo" width={48} height={48} className="relative rounded-xl" />
68
- </div>
69
- <h2 className="text-3xl font-bold text-gray-900 dark:text-white tracking-tight">
70
- Welcome Back
71
- </h2>
72
- <p className="mt-2 text-sm text-gray-500 dark:text-gray-400">
73
- Sign in to access your workflow history
74
- </p>
75
- <p className="mt-1 text-xs text-gray-400 font-mono">
76
- v1.7.15
77
- </p>
78
- </div>
79
-
80
- <form className="mt-8 space-y-6" onSubmit={handleSubmit}>
81
- {error && (
82
- <div className="rounded-lg bg-red-50 dark:bg-red-900/20 p-4 border border-red-200 dark:border-red-900/50">
83
- <p className="text-sm text-red-600 dark:text-red-400 text-center font-medium">{error}</p>
84
- </div>
85
- )}
86
-
87
- <div className="space-y-4">
88
- <div className="relative">
89
- <label htmlFor="username" className="sr-only">Username</label>
90
- <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
91
- <User className="h-5 w-5 text-gray-400" />
92
- </div>
93
- <input
94
- id="username"
95
- name="username"
96
- type="text"
97
- required
98
- className="appearance-none block w-full pl-10 pr-3 py-3 border border-gray-300 dark:border-white/10 rounded-xl placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white dark:bg-black/20 text-gray-900 dark:text-white sm:text-sm transition-all"
99
- placeholder="Username"
100
- value={username}
101
- onChange={(e) => setUsername(e.target.value)}
102
- disabled={loading}
103
- />
104
- </div>
105
- <div className="relative">
106
- <label htmlFor="password" className="sr-only">Password</label>
107
- <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
108
- <Lock className="h-5 w-5 text-gray-400" />
109
- </div>
110
- <input
111
- id="password"
112
- name="password"
113
- type="password"
114
- required
115
- className="appearance-none block w-full pl-10 pr-3 py-3 border border-gray-300 dark:border-white/10 rounded-xl placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent bg-white dark:bg-black/20 text-gray-900 dark:text-white sm:text-sm transition-all"
116
- placeholder="Password"
117
- value={password}
118
- onChange={(e) => setPassword(e.target.value)}
119
- disabled={loading}
120
- />
121
- </div>
122
- </div>
123
-
124
- <div>
125
- <button
126
- type="submit"
127
- disabled={loading}
128
- className="group relative w-full flex justify-center py-3 px-4 border border-transparent text-sm font-semibold rounded-xl text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-all shadow-lg shadow-blue-500/30 hover:shadow-blue-500/40"
129
- >
130
- {loading ? (
131
- <svg className="animate-spin -ml-1 mr-3 h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
132
- <circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
133
- <path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
134
- </svg>
135
- ) : 'Sign in'}
136
- </button>
137
- </div>
138
- </form>
139
- </div>
140
- </div>
141
- );
142
- }
package/web/app/page.tsx DELETED
@@ -1,13 +0,0 @@
1
- import Hero from "@/components/Hero";
2
- import Features from "@/components/Features";
3
- import ApiReference from "@/components/ApiReference";
4
-
5
- export default function Home() {
6
- return (
7
- <main>
8
- <Hero />
9
- <Features />
10
- <ApiReference />
11
- </main>
12
- );
13
- }
@@ -1,20 +0,0 @@
1
- export default function ApiReference() {
2
- return (
3
- <section id="api" className="py-20 px-4">
4
- <div className="max-w-7xl mx-auto">
5
- <h2 className="text-3xl md:text-4xl font-bold mb-8">API Reference</h2>
6
- <p className="text-gray-400 mb-12">Query workflow data programmatically with our JSON API.</p>
7
- <div className="grid md:grid-cols-2 gap-6">
8
- <div className="p-6 rounded-xl bg-white/5 border border-white/10">
9
- <code className="text-indigo-400 font-mono text-sm">GET /api/history</code>
10
- <p className="text-gray-400 mt-2">Retrieve paginated task history entries.</p>
11
- </div>
12
- <div className="p-6 rounded-xl bg-white/5 border border-white/10">
13
- <code className="text-indigo-400 font-mono text-sm">GET /api/summary</code>
14
- <p className="text-gray-400 mt-2">Get project health stats and recent tasks.</p>
15
- </div>
16
- </div>
17
- </div>
18
- </section>
19
- );
20
- }
@@ -1,61 +0,0 @@
1
- import { ShieldCheck, TestTube, FileText, GitBranch, History, Zap } from "lucide-react";
2
-
3
- export default function Features() {
4
- return (
5
- <section id="features" className="py-12 sm:py-16 lg:py-20 px-3 sm:px-4 bg-gray-50 dark:bg-transparent transition-colors duration-300">
6
- <div className="max-w-7xl mx-auto">
7
- <h2 className="text-2xl sm:text-3xl md:text-4xl font-bold text-center mb-8 sm:mb-12 lg:mb-16 text-gray-900 dark:text-white">Your Coding Conscience</h2>
8
- <div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4 sm:gap-6">
9
- <FeatureCard
10
- icon={<ShieldCheck className="w-6 h-6 text-indigo-400" />}
11
- title="Enforced Discipline"
12
- description="Won't let you skip important steps. Follows a strict, proven development workflow."
13
- bg="bg-indigo-500/20"
14
- />
15
- <FeatureCard
16
- icon={<TestTube className="w-6 h-6 text-purple-400" />}
17
- title="Test-Driven"
18
- description="Blocks commits if tests fail. Encourages writing tests before marking tasks complete."
19
- bg="bg-purple-500/20"
20
- />
21
- <FeatureCard
22
- icon={<FileText className="w-6 h-6 text-emerald-400" />}
23
- title="Documentation"
24
- description="Reminds you to update documentation (README, docs, changelog) for every change."
25
- bg="bg-emerald-500/20"
26
- />
27
- <FeatureCard
28
- icon={<GitBranch className="w-6 h-6 text-orange-400" />}
29
- title="State Tracking"
30
- description="Remembers exactly where you are in the workflow, even across sessions."
31
- bg="bg-orange-500/20"
32
- />
33
- <FeatureCard
34
- icon={<History className="w-6 h-6 text-blue-400" />}
35
- title="Task History"
36
- description="Keeps a detailed log of all completed tasks, commits, and releases."
37
- bg="bg-blue-500/20"
38
- />
39
- <FeatureCard
40
- icon={<Zap className="w-6 h-6 text-pink-400" />}
41
- title="Smart Prompts"
42
- description="Provides quick reminders and guidance on best practices as you work."
43
- bg="bg-pink-500/20"
44
- />
45
- </div>
46
- </div>
47
- </section>
48
- );
49
- }
50
-
51
- function FeatureCard({ icon, title, description, bg }: { icon: React.ReactNode, title: string, description: string, bg: string }) {
52
- return (
53
- <div className="p-6 rounded-xl bg-white dark:bg-white/5 border border-gray-200 dark:border-white/10 hover:bg-gray-100 dark:hover:bg-white/10 transition">
54
- <div className={`w-12 h-12 rounded-lg ${bg} flex items-center justify-center mb-4`}>
55
- {icon}
56
- </div>
57
- <h3 className="text-xl font-semibold mb-2 text-gray-900 dark:text-white">{title}</h3>
58
- <p className="text-gray-600 dark:text-gray-400">{description}</p>
59
- </div>
60
- );
61
- }
@@ -1,9 +0,0 @@
1
- export default function Footer() {
2
- return (
3
- <footer className="py-12 px-4 border-t border-gray-200 dark:border-white/10 bg-white dark:bg-transparent transition-colors duration-300">
4
- <div className="max-w-7xl mx-auto text-center text-gray-600 dark:text-gray-400">
5
- <p>Built with ❤️ for developers who care about quality</p>
6
- </div>
7
- </footer>
8
- );
9
- }
@@ -1,96 +0,0 @@
1
- "use client";
2
-
3
- import Link from "next/link";
4
- import { ArrowRight } from "lucide-react";
5
- import Terminal from "./Terminal";
6
- import { useEffect, useState } from "react";
7
-
8
- export default function Hero() {
9
- const [downloads, setDownloads] = useState<number | null>(null);
10
- const [version, setVersion] = useState<string | null>(null);
11
-
12
- useEffect(() => {
13
- // Fetch npm downloads directly from npm API
14
- fetch("https://api.npmjs.org/downloads/point/last-month/@programinglive/dev-workflow-mcp-server")
15
- .then(res => res.json())
16
- .then(data => setDownloads(data.downloads || 0))
17
- .catch(() => setDownloads(null));
18
-
19
- // Version is hardcoded for static export
20
- setVersion("1.7.15");
21
- }, []);
22
-
23
- const formatDownloads = (num: number) => {
24
- if (num >= 1000000) return `${(num / 1000000).toFixed(1)}M`;
25
- if (num >= 1000) return `${(num / 1000).toFixed(1)}K`;
26
- return num.toString();
27
- };
28
-
29
- return (
30
- <section className="min-h-screen flex items-center justify-center px-3 sm:px-4 pt-16 relative overflow-hidden bg-white dark:bg-transparent transition-colors duration-300">
31
- <div className="absolute inset-0 bg-gradient-to-br from-indigo-500/5 dark:from-indigo-500/10 via-purple-500/5 dark:via-purple-500/10 to-pink-500/5 dark:to-pink-500/10"></div>
32
- <div className="max-w-7xl mx-auto grid xl:grid-cols-2 gap-6 sm:gap-8 lg:gap-12 items-center relative z-10">
33
- {/* Left Column - Content */}
34
- <div>
35
- <div className="animate-fade-in-up" style={{ animationDelay: "0.1s" }}>
36
- <div className="inline-flex items-center gap-2 px-3 py-1.5 rounded-full bg-emerald-500/10 border border-emerald-500/20 text-emerald-400 text-sm mb-8">
37
- <span className="w-1.5 h-1.5 rounded-full bg-emerald-500 animate-pulse"></span>
38
- <span>v{version ?? "..."} - Active</span>
39
- </div>
40
- </div>
41
-
42
- <h1 className="text-3xl sm:text-4xl md:text-5xl lg:text-6xl xl:text-7xl font-bold mb-4 sm:mb-6 leading-tight animate-fade-in-up" style={{ animationDelay: "0.2s" }}>
43
- Master Your<br />
44
- <span className="bg-gradient-to-r from-indigo-400 via-purple-400 to-pink-400 bg-clip-text text-transparent">Workflow</span>
45
- </h1>
46
- <p className="text-base sm:text-lg md:text-xl text-gray-600 dark:text-gray-400 mb-6 sm:mb-8 max-w-xl animate-fade-in-up" style={{ animationDelay: "0.3s" }}>
47
- An MCP server that acts as your coding conscience. Enforce test-driven development, ensure documentation, and never skip a step in your release process.
48
- </p>
49
- <div className="flex flex-col sm:flex-row gap-4 mb-8 animate-fade-in-up" style={{ animationDelay: "0.4s" }}>
50
- <Link href="#history" className="px-6 py-3 bg-gradient-to-r from-indigo-600 to-purple-600 rounded-lg font-semibold hover:shadow-lg hover:shadow-indigo-500/50 transition inline-flex items-center justify-center gap-2 text-white">
51
- View History <ArrowRight className="w-4 h-4" />
52
- </Link>
53
- <Link href="/docs" className="px-6 py-3 bg-gray-200 dark:bg-white/5 border border-gray-300 dark:border-white/10 rounded-lg font-semibold hover:bg-gray-300 dark:hover:bg-white/10 transition text-center text-gray-900 dark:text-white">
54
- Documentation
55
- </Link>
56
- </div>
57
- <div className="flex flex-wrap gap-4 sm:gap-6 lg:gap-8 text-xs sm:text-sm animate-fade-in-up" style={{ animationDelay: "0.5s" }}>
58
- <div>
59
- <div className="text-xl sm:text-2xl font-bold text-gray-900 dark:text-white">{version ?? "..."}</div>
60
- <div className="text-gray-600 dark:text-gray-500">Latest Version</div>
61
- </div>
62
- <div>
63
- <div className="text-xl sm:text-2xl font-bold text-gray-900 dark:text-white">MIT</div>
64
- <div className="text-gray-600 dark:text-gray-500">License</div>
65
- </div>
66
- <div>
67
- <div className="text-xl sm:text-2xl font-bold text-gray-900 dark:text-white">Node 18+</div>
68
- <div className="text-gray-600 dark:text-gray-500">Compatibility</div>
69
- </div>
70
- {downloads !== null && (
71
- <div>
72
- <div className="text-xl sm:text-2xl font-bold text-gray-900 dark:text-white">{formatDownloads(downloads)}</div>
73
- <div className="text-gray-600 dark:text-gray-500">Downloads/mo</div>
74
- </div>
75
- )}
76
- </div>
77
- </div>
78
- {/* Right Column - Terminal */}
79
- <div className="hidden xl:block">
80
- <div className="relative">
81
- <div className="absolute inset-0 bg-gradient-to-r from-indigo-500/20 to-purple-500/20 blur-3xl"></div>
82
- <div className="relative bg-[#1a1a24] rounded-xl border border-white/10 p-4 sm:p-6 shadow-2xl">
83
- <div className="flex items-center gap-2 mb-4">
84
- <div className="w-3 h-3 rounded-full bg-red-500"></div>
85
- <div className="w-3 h-3 rounded-full bg-yellow-500"></div>
86
- <div className="w-3 h-3 rounded-full bg-green-500"></div>
87
- <span className="ml-auto text-xs text-gray-500">terminal</span>
88
- </div>
89
- <Terminal />
90
- </div>
91
- </div>
92
- </div>
93
- </div>
94
- </section>
95
- );
96
- }