@programinglive/dev-workflow-mcp-server 1.8.1 → 1.10.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 (114) hide show
  1. package/.env.example +21 -1
  2. package/AGENTS.md +25 -0
  3. package/README.md +372 -649
  4. package/factory-client.js +554 -0
  5. package/git-facade.js +35 -0
  6. package/index.js +9 -34
  7. package/package.json +21 -20
  8. package/scripts/bootstrap-unix.sh +55 -0
  9. package/scripts/bootstrap-windows.ps1 +75 -0
  10. package/scripts/install-husky.js +43 -0
  11. package/scripts/setup-stack.js +436 -0
  12. package/scripts/setup-test-dbs.sh +61 -0
  13. package/scripts/test-db-adapters.sh +71 -0
  14. package/scripts/verify-bundle.mjs +92 -0
  15. package/tools/definitions.js +143 -0
  16. package/tools/handler-modules/commit-handlers.js +2 -1
  17. package/tools/handler-modules/factory-handlers.js +276 -0
  18. package/tools/handler-modules/index.js +24 -7
  19. package/tools/handler-modules/shared.js +7 -41
  20. package/tools/handler-modules/status-handlers.js +25 -3
  21. package/tools/handler-modules/workflow-handlers.js +57 -10
  22. package/vite.config.js +6 -0
  23. package/workflow-state.js +176 -2
  24. package/.agent/workflows/dev-workflow-bugfix.md +0 -250
  25. package/.agent/workflows/dev-workflow-feature.md +0 -201
  26. package/.agent/workflows/dev-workflow-full-cycle.md +0 -400
  27. package/.agent/workflows/dev-workflow-refactor.md +0 -238
  28. package/.env.production +0 -16
  29. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -34
  30. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -25
  31. package/.github/pull_request_template.md +0 -22
  32. package/.github/workflows/github-release.yml +0 -131
  33. package/.husky/commit-msg +0 -3
  34. package/.husky/pre-commit +0 -2
  35. package/CHANGELOG.md +0 -1145
  36. package/docs/GCP_DEPLOYMENT.md +0 -298
  37. package/docs/NETLIFY_DEPLOYMENT.md +0 -125
  38. package/docs/PLESK_DEPLOYMENT.md +0 -170
  39. package/docs/PRD.md +0 -86
  40. package/docs/WORKFLOW-BEST-PRACTICES.md +0 -58
  41. package/docs/antigravity/EXAMPLES.md +0 -535
  42. package/docs/antigravity/GETTING-STARTED.md +0 -292
  43. package/docs/antigravity/TROUBLESHOOTING.md +0 -742
  44. package/docs/antigravity/WALKTHROUGH.md +0 -25
  45. package/docs/antigravity/WORKFLOW-TEMPLATES.md +0 -670
  46. package/docs/release-notes/RELEASE_NOTES.md +0 -524
  47. package/docs/web-dashboard.md +0 -175
  48. package/scripts/test-auth-flow.js +0 -75
  49. package/tailwind.config.js +0 -8
  50. package/tests/build.test.js +0 -74
  51. package/tests/db-adapters.test.js +0 -108
  52. package/tests/env-support.test.js +0 -46
  53. package/tests/exec.test.js +0 -35
  54. package/tests/handlers-commit.test.js +0 -174
  55. package/tests/handlers-release.test.js +0 -212
  56. package/tests/handlers-workflow.test.js +0 -68
  57. package/tests/handlers.test.js +0 -1142
  58. package/tests/hello-world.test.js +0 -13
  59. package/tests/mcpRegistry.test.js +0 -65
  60. package/tests/patch-release.test.js +0 -7
  61. package/tests/release-wrapper.test.js +0 -107
  62. package/tests/startup-resilience.test.js +0 -73
  63. package/tests/test-helpers.js +0 -50
  64. package/tests/workflowState.test.js +0 -520
  65. package/web/Dockerfile.api +0 -25
  66. package/web/README.md +0 -133
  67. package/web/__tests__/api/workflow-history.test.js +0 -63
  68. package/web/api-server.js +0 -211
  69. package/web/app/docs/page.tsx +0 -202
  70. package/web/app/favicon.ico +0 -0
  71. package/web/app/globals.css +0 -91
  72. package/web/app/history/page.tsx +0 -220
  73. package/web/app/layout.tsx +0 -39
  74. package/web/app/login/page.tsx +0 -142
  75. package/web/app/page.tsx +0 -13
  76. package/web/components/ApiReference.tsx +0 -20
  77. package/web/components/Features.tsx +0 -61
  78. package/web/components/Footer.tsx +0 -9
  79. package/web/components/Hero.tsx +0 -96
  80. package/web/components/History.tsx +0 -175
  81. package/web/components/Navbar.tsx +0 -208
  82. package/web/components/Terminal.tsx +0 -114
  83. package/web/components/ThemeProvider.tsx +0 -58
  84. package/web/eslint.config.mjs +0 -18
  85. package/web/lib/api-client.ts +0 -123
  86. package/web/lib/auth.js +0 -75
  87. package/web/lib/db.js +0 -131
  88. package/web/lib/docs.js +0 -73
  89. package/web/middleware/auth.js +0 -26
  90. package/web/netlify.toml +0 -8
  91. package/web/next.config.ts +0 -19
  92. package/web/package-lock.json +0 -10911
  93. package/web/package.json +0 -42
  94. package/web/postcss.config.mjs +0 -9
  95. package/web/public/assets/android-chrome-192x192.png +0 -0
  96. package/web/public/assets/android-chrome-512x512.png +0 -0
  97. package/web/public/assets/apple-touch-icon.png +0 -0
  98. package/web/public/assets/favicon-16x16.png +0 -0
  99. package/web/public/assets/favicon-32x32.png +0 -0
  100. package/web/public/assets/favicon.ico +0 -0
  101. package/web/public/assets/favicon.png +0 -0
  102. package/web/public/assets/logo.png +0 -0
  103. package/web/public/assets/og-preview.png +0 -0
  104. package/web/public/assets/site.webmanifest +0 -1
  105. package/web/public/file.svg +0 -1
  106. package/web/public/globe.svg +0 -1
  107. package/web/public/next.svg +0 -1
  108. package/web/public/vercel.svg +0 -1
  109. package/web/public/window.svg +0 -1
  110. package/web/scripts/db-query-history.js +0 -120
  111. package/web/scripts/smoke-test.js +0 -30
  112. package/web/server.js +0 -184
  113. package/web/tailwind.config.ts +0 -20
  114. 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
- }