kalhdrawi commited on
Commit
b0e750c
·
1 Parent(s): a51c5c9

Reupload OmniDev clean version

Browse files
components/new/scaffold.tsx CHANGED
@@ -5,19 +5,54 @@ import { useAi } from "@/hooks/useAi";
5
  import { useRouter } from "next/navigation";
6
  import { Button } from "@/components/ui/button";
7
  import { toast } from "sonner";
 
 
8
 
9
- const DEFAULT_INSTRUCTION = `Initialize a complete full-stack web project with the following structure and runnable code:
 
 
 
 
 
 
 
 
10
 
11
  Requirements:
12
- - Frontend under /frontend using React + Vite (JavaScript), TailwindCSS preconfigured.
13
- - Backend under /backend using Express (JavaScript, ESM), with basic routes (GET /, GET /health) and CORS enabled.
14
- - Add a minimal README.md at root.
 
15
  - Provide package.json in both /frontend and /backend with scripts to start dev/prod.
16
- - Provide /frontend/index.html and /frontend/src/main.jsx, /frontend/src/App.jsx.
17
- - Provide /backend/server.js.
18
  - Use ports 5173 for frontend and 3000 for backend.
19
  - Keep everything simple and runnable.
20
- - Return JSON strictly as file updates (no markdown), paths rooted from repo, e.g. /frontend/..., /backend/...`;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  export default function ScaffoldNew() {
23
  const { user, openLoginWindow } = useUser();
@@ -26,6 +61,10 @@ export default function ScaffoldNew() {
26
  const [loading, setLoading] = useState(false);
27
  const [error, setError] = useState<string | null>(null);
28
  const [logs, setLogs] = useState<string[]>([]);
 
 
 
 
29
 
30
  async function runScaffold() {
31
  if (!user) {
@@ -37,14 +76,15 @@ export default function ScaffoldNew() {
37
  setLogs(["Starting scaffold via Augment..."]);
38
  try {
39
  // 1) Call augment to generate full-stack files
 
40
  const aug = await fetch('/api/augment', {
41
  method: 'POST',
42
  headers: { 'Content-Type': 'application/json' },
43
  body: JSON.stringify({
44
  context: '/ (empty project)',
45
- instruction: DEFAULT_INSTRUCTION,
46
- language: 'javascript',
47
- framework: 'express-react',
48
  response_type: 'file_updates',
49
  model,
50
  provider,
@@ -56,11 +96,10 @@ export default function ScaffoldNew() {
56
  setLogs(prev => [...prev, `Augment produced ${aug.files.length} files`]);
57
 
58
  // 2) Create space with initial files
59
- const title = 'OmniDev Full-Stack Project';
60
  const created = await fetch('/api/me/projects', {
61
  method: 'POST',
62
  headers: { 'Content-Type': 'application/json' },
63
- body: JSON.stringify({ title, initialFiles: aug.files.map((f: any) => ({ path: f.path, content: f.content })) })
64
  }).then(r => r.json());
65
  if (!created?.space?.project?.space_id) {
66
  throw new Error(created?.error || 'Failed to create project');
@@ -75,24 +114,49 @@ export default function ScaffoldNew() {
75
  }
76
  }
77
 
78
- useEffect(() => {
79
- // Auto-run once when visiting /new
80
- runScaffold();
81
- // eslint-disable-next-line react-hooks/exhaustive-deps
82
- }, []);
83
 
84
  return (
85
- <section className="max-w-2xl mx-auto p-6 text-neutral-200">
86
- <h1 className="text-2xl font-semibold mb-2">Initializing Full-Stack Project...</h1>
87
- <p className="text-sm text-neutral-400 mb-4">OmniDev is generating a complete frontend + backend project. This may take a moment.</p>
88
- {error && <p className="text-red-400 text-sm mb-2">{error}</p>}
89
- <ul className="text-sm text-neutral-400 space-y-1">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  {logs.map((l, i) => (<li key={i}>• {l}</li>))}
91
  </ul>
92
- <div className="mt-4">
93
- <Button size="sm" onClick={runScaffold} disabled={loading}>{loading ? 'Working...' : 'Retry'}</Button>
94
  </div>
95
  </section>
96
  );
97
  }
98
-
 
5
  import { useRouter } from "next/navigation";
6
  import { Button } from "@/components/ui/button";
7
  import { toast } from "sonner";
8
+ import { NEW_STACKS, NewStackId } from "@/lib/new-stacks";
9
+ import { HERO_STYLES } from "@/lib/hero-presets";
10
 
11
+ function buildInstruction(stack: NewStackId, lang: "js" | "ts", hero: string, title?: string) {
12
+ const jsOrTs = lang === 'ts' ? 'TypeScript' : 'JavaScript';
13
+ const reactEntry = lang === 'ts' ? "/frontend/src/main.tsx and /frontend/src/App.tsx" : "/frontend/src/main.jsx and /frontend/src/App.jsx";
14
+
15
+ switch (stack) {
16
+ case 'express-react':
17
+ return `Initialize a complete full-stack web project with the following structure and runnable code.
18
+
19
+ Title: ${title || 'OmniDev Full-Stack App'}
20
 
21
  Requirements:
22
+ - Frontend under /frontend using React + Vite (${jsOrTs}), TailwindCSS preconfigured.
23
+ - Backend under /backend using Express (${jsOrTs}, ESM), with basic routes (GET /, GET /health) and CORS enabled.
24
+ - Use a Hero section with style: ${hero}. Keep it performant and accessible.
25
+ - Add a minimal README.md at root with start instructions.
26
  - Provide package.json in both /frontend and /backend with scripts to start dev/prod.
27
+ - Provide /frontend/index.html and ${reactEntry}.
28
+ - Provide /backend/server.${lang === 'ts' ? 'ts' : 'js'}.
29
  - Use ports 5173 for frontend and 3000 for backend.
30
  - Keep everything simple and runnable.
31
+ - Return STRICT JSON ONLY as file updates (no markdown), paths rooted from repo (e.g., /frontend/..., /backend/...).`;
32
+ case 'nextjs':
33
+ return `Scaffold a full-stack Next.js 15 App Router project.
34
+
35
+ Title: ${title || 'OmniDev Next App'}
36
+
37
+ Requirements:
38
+ - Next.js (${jsOrTs}), App Router, TailwindCSS.
39
+ - Implement a landing page with a Hero section style: ${hero}.
40
+ - Add /api/health route that returns { ok: true }.
41
+ - Provide package.json with dev/build scripts.
42
+ - Keep it simple and runnable with \'next dev\'.
43
+ - Return STRICT JSON ONLY as file updates (no markdown), paths rooted from repo (e.g., /app/page.${lang === 'ts' ? 'tsx' : 'jsx'}, /app/api/health/route.${lang === 'ts' ? 'ts' : 'js'}).`;
44
+ case 'nestjs-react':
45
+ return `Initialize a NestJS backend and React (Vite) frontend.
46
+
47
+ Title: ${title || 'OmniDev Nest + React'}
48
+
49
+ Requirements:
50
+ - Backend under /backend using NestJS (${jsOrTs}). Generate AppModule, AppController with GET / and GET /health. Enable CORS.
51
+ - Frontend under /frontend using React + Vite (${jsOrTs}), TailwindCSS with a modern Hero section style: ${hero}.
52
+ - Provide package.json in both apps with start/build scripts.
53
+ - Return STRICT JSON ONLY as file updates (no markdown), paths rooted from repo.`;
54
+ }
55
+ }
56
 
57
  export default function ScaffoldNew() {
58
  const { user, openLoginWindow } = useUser();
 
61
  const [loading, setLoading] = useState(false);
62
  const [error, setError] = useState<string | null>(null);
63
  const [logs, setLogs] = useState<string[]>([]);
64
+ const [stack, setStack] = useState<NewStackId>("express-react");
65
+ const [lang, setLang] = useState<"js" | "ts">("js");
66
+ const [hero, setHero] = useState<string>(HERO_STYLES[0].id);
67
+ const [title, setTitle] = useState<string>("");
68
 
69
  async function runScaffold() {
70
  if (!user) {
 
76
  setLogs(["Starting scaffold via Augment..."]);
77
  try {
78
  // 1) Call augment to generate full-stack files
79
+ const instruction = buildInstruction(stack, lang, hero, title);
80
  const aug = await fetch('/api/augment', {
81
  method: 'POST',
82
  headers: { 'Content-Type': 'application/json' },
83
  body: JSON.stringify({
84
  context: '/ (empty project)',
85
+ instruction,
86
+ language: lang === 'ts' ? 'typescript' : 'javascript',
87
+ framework: stack,
88
  response_type: 'file_updates',
89
  model,
90
  provider,
 
96
  setLogs(prev => [...prev, `Augment produced ${aug.files.length} files`]);
97
 
98
  // 2) Create space with initial files
 
99
  const created = await fetch('/api/me/projects', {
100
  method: 'POST',
101
  headers: { 'Content-Type': 'application/json' },
102
+ body: JSON.stringify({ title: title || 'OmniDev Project', initialFiles: aug.files.map((f: any) => ({ path: f.path, content: f.content })) })
103
  }).then(r => r.json());
104
  if (!created?.space?.project?.space_id) {
105
  throw new Error(created?.error || 'Failed to create project');
 
114
  }
115
  }
116
 
117
+ // Removed auto-run; wait for user selection
 
 
 
 
118
 
119
  return (
120
+ <section className="max-w-3xl mx-auto p-6 text-neutral-200">
121
+ <h1 className="text-2xl font-semibold mb-1">Create New Project</h1>
122
+ <p className="text-sm text-neutral-400 mb-4">Choose your stack and hero style, then OmniDev will scaffold a complete project.</p>
123
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
124
+ <div>
125
+ <label className="text-sm block mb-1">Project Title</label>
126
+ <input className="w-full bg-neutral-800 rounded p-2 text-sm" placeholder="OmniDev Project" value={title} onChange={(e) => setTitle(e.target.value)} />
127
+ </div>
128
+ <div>
129
+ <label className="text-sm block mb-1">Language</label>
130
+ <select className="w-full bg-neutral-800 rounded p-2 text-sm" value={lang} onChange={(e) => setLang(e.target.value as any)}>
131
+ <option value="js">JavaScript</option>
132
+ <option value="ts">TypeScript</option>
133
+ </select>
134
+ </div>
135
+ <div>
136
+ <label className="text-sm block mb-1">Stack</label>
137
+ <select className="w-full bg-neutral-800 rounded p-2 text-sm" value={stack} onChange={(e) => setStack(e.target.value as NewStackId)}>
138
+ {NEW_STACKS.map(s => (
139
+ <option key={s.id} value={s.id}>{s.label}</option>
140
+ ))}
141
+ </select>
142
+ <p className="text-xs text-neutral-500 mt-1">{NEW_STACKS.find(s => s.id === stack)?.description}</p>
143
+ </div>
144
+ <div>
145
+ <label className="text-sm block mb-1">Hero Style</label>
146
+ <select className="w-full bg-neutral-800 rounded p-2 text-sm" value={hero} onChange={(e) => setHero(e.target.value)}>
147
+ {HERO_STYLES.map(h => (
148
+ <option key={h.id} value={h.id}>{h.label}</option>
149
+ ))}
150
+ </select>
151
+ </div>
152
+ </div>
153
+ {error && <p className="text-red-400 text-sm mt-3">{error}</p>}
154
+ <ul className="text-sm text-neutral-400 space-y-1 mt-3">
155
  {logs.map((l, i) => (<li key={i}>• {l}</li>))}
156
  </ul>
157
+ <div className="mt-5">
158
+ <Button size="sm" onClick={runScaffold} disabled={loading}>{loading ? 'Working...' : 'Create Project'}</Button>
159
  </div>
160
  </section>
161
  );
162
  }
 
lib/hero-presets.ts ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export const HERO_STYLES = [
2
+ { id: "animated-gradient", label: "Animated Gradient" },
3
+ { id: "particles", label: "Particles" },
4
+ { id: "waves", label: "Waves" },
5
+ { id: "noise", label: "Noise Overlay" },
6
+ { id: "parallax", label: "Parallax Layers" },
7
+ { id: "vanta-globe", label: "Vanta Globe" },
8
+ { id: "morphing-blobs", label: "Morphing Blobs" },
9
+ { id: "rays", label: "Rays / Aurora" },
10
+ { id: "grid", label: "Animated Grid" },
11
+ { id: "shapes", label: "Floating Shapes" },
12
+ { id: "lines", label: "Moving Lines" },
13
+ { id: "orbits", label: "Orbits" },
14
+ ];
15
+
lib/new-stacks.ts ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export type NewStackId = "express-react" | "nextjs" | "nestjs-react";
2
+
3
+ export interface NewStack {
4
+ id: NewStackId;
5
+ label: string;
6
+ description: string;
7
+ frameworkHint: string; // sent to /api/augment as framework
8
+ }
9
+
10
+ export const NEW_STACKS: NewStack[] = [
11
+ {
12
+ id: "express-react",
13
+ label: "Express + React (Vite)",
14
+ description: "React (Vite + Tailwind) for frontend and Express (ESM) for backend.",
15
+ frameworkHint: "express-react",
16
+ },
17
+ {
18
+ id: "nextjs",
19
+ label: "Next.js (App Router)",
20
+ description: "Full-stack Next.js 15 (App Router) with Tailwind and an /api route.",
21
+ frameworkHint: "nextjs",
22
+ },
23
+ {
24
+ id: "nestjs-react",
25
+ label: "NestJS + React",
26
+ description: "NestJS backend + React (Vite + Tailwind) frontend.",
27
+ frameworkHint: "nestjs-react",
28
+ },
29
+ ];
30
+