06_nextjs_app_generator/
06_nextjs_app_generator.rs

1//! Next.js App Generator Example
2//!
3//! This example demonstrates how to use a Ceylon Agent to:
4//! - Create a goal-based task for generating a Next.js application
5//! - Use tools to interact with the file system and run commands
6//! - Extract structured output from the agent's work
7//! - Display generated code and configuration
8//!
9//! The agent will:
10//! 1. Analyze the requirements for a Next.js app
11//! 2. Generate project structure and configuration files
12//! 3. Create essential components and pages
13//! 4. Output the complete generated code
14//!
15//! Run with: cargo run --example 06_nextjs_app_generator --manifest-path ceylon/Cargo.toml
16
17use ceylon_next::agent::Agent;
18use ceylon_next::goal::{Goal, GoalStatus};
19use ceylon_next::tasks::{OutputData, TaskRequest};
20use std::collections::HashMap;
21
22// ============================================
23// Helper: Extract task output
24// ============================================
25
26fn extract_output_text(output: &OutputData) -> String {
27    match output {
28        OutputData::Text(text) => text.clone(),
29        OutputData::File(bytes) => String::from_utf8_lossy(bytes).to_string(),
30        _ => "No text output available".to_string(),
31    }
32}
33
34// ============================================
35// Example 1: Basic Next.js App Generation
36// ============================================
37
38async fn example_1_basic_nextjs_app() {
39    println!("=== Example 1: Generate a Basic Next.js App ===\n");
40
41    // Create an agent that will generate the app
42    let mut agent = Agent::new("NextJsGenerator", "ollama::gemma3:latest");
43
44    // Create a goal for generating a Next.js app
45    let mut goal = Goal::new(
46        "Generate a Next.js web application with essential structure".to_string()
47    );
48
49    // Define success criteria
50    goal.add_criterion("package.json created with dependencies".to_string());
51    goal.add_criterion("next.config.js configuration file generated".to_string());
52    goal.add_criterion("pages directory with index and api route created".to_string());
53    goal.add_criterion("styles directory with global CSS".to_string());
54    goal.add_criterion("README.md with setup instructions".to_string());
55
56    // Define sub-goals (steps to generate the app)
57    goal.add_sub_goal("Analyze Next.js requirements and best practices".to_string(), 0);
58    goal.add_sub_goal("Generate package.json with required dependencies".to_string(), 1);
59    goal.add_sub_goal("Create next.config.js configuration".to_string(), 2);
60    goal.add_sub_goal("Generate pages (index.tsx, _app.tsx, _document.tsx)".to_string(), 3);
61    goal.add_sub_goal("Create API route examples".to_string(), 4);
62    goal.add_sub_goal("Generate styling setup (global.css, utilities)".to_string(), 5);
63    goal.add_sub_goal("Create components directory with example components".to_string(), 6);
64    goal.add_sub_goal("Generate README with setup and usage instructions".to_string(), 7);
65
66    goal.status = GoalStatus::InProgress;
67    agent.set_goal(goal.clone());
68
69    // Create a task to generate a Next.js app
70    let task = TaskRequest::new(
71        "Generate a modern Next.js 14 application with TypeScript, Tailwind CSS, and best practices. \
72         Include package.json, next.config.js, sample pages, API routes, and components. \
73         The app should be production-ready and follow Next.js conventions."
74    );
75
76    println!("šŸ“ Task: Generate a Next.js application\n");
77    println!("šŸŽÆ Success Criteria:");
78    for criterion in &goal.success_criteria {
79        println!("  • {}", criterion.description);
80    }
81
82    println!("\nā³ Agent is generating the Next.js app...\n");
83    let response = agent.run(task).await;
84
85    // Extract and display the output
86    let output = extract_output_text(&response.result());
87    println!("šŸ“„ Generated Output:\n");
88    println!("{}\n", output);
89
90    // Show progress
91    println!("šŸ“Š Goal Progress: {}%", goal.get_progress());
92    println!("Status: {:?}", goal.status);
93
94    println!("\nāœ… Example 1 completed!\n");
95}
96
97// ============================================
98// Example 2: E-Commerce Next.js App
99// ============================================
100
101async fn example_2_ecommerce_app() {
102    println!("\n=== Example 2: Generate E-Commerce Next.js App ===\n");
103
104    let mut agent = Agent::new("EcommerceGenerator", "ollama::gemma3:latest");
105
106    let mut goal = Goal::new(
107        "Generate a complete e-commerce Next.js application".to_string()
108    );
109
110    // Success criteria for e-commerce
111    goal.add_criterion("Product listing page with filtering and sorting".to_string());
112    goal.add_criterion("Product detail pages with dynamic routes".to_string());
113    goal.add_criterion("Shopping cart functionality".to_string());
114    goal.add_criterion("User authentication setup".to_string());
115    goal.add_criterion("Payment integration structure".to_string());
116    goal.add_criterion("Database models and API endpoints".to_string());
117    goal.add_criterion("Admin dashboard layout".to_string());
118
119    // Sub-goals
120    goal.add_sub_goal("Design database schema for products and orders".to_string(), 0);
121    goal.add_sub_goal("Create product API endpoints".to_string(), 1);
122    goal.add_sub_goal("Build product listing and search components".to_string(), 2);
123    goal.add_sub_goal("Implement product detail pages".to_string(), 3);
124    goal.add_sub_goal("Create shopping cart context and management".to_string(), 4);
125    goal.add_sub_goal("Build checkout flow pages".to_string(), 5);
126    goal.add_sub_goal("Integrate payment gateway API".to_string(), 6);
127    goal.add_sub_goal("Create admin dashboard pages".to_string(), 7);
128    goal.add_sub_goal("Add authentication middleware".to_string(), 8);
129
130    goal.status = GoalStatus::InProgress;
131    agent.set_goal(goal.clone());
132
133    let task = TaskRequest::new(
134        "Generate a complete e-commerce Next.js application with: \
135         1. Product management system (listing, search, filters)\n\
136         2. Shopping cart with add/remove/update functionality\n\
137         3. User authentication and profile pages\n\
138         4. Payment integration endpoints\n\
139         5. Order history and tracking\n\
140         6. Admin dashboard for managing products and orders\n\
141         7. Database models for PostgreSQL or MongoDB\n\
142         8. RESTful API endpoints\n\
143         Use TypeScript, Tailwind CSS, and modern React patterns."
144    );
145
146    println!("šŸ“ Task: Generate E-Commerce Next.js Application\n");
147    println!("šŸŽÆ Features to Generate:");
148    for criterion in &goal.success_criteria {
149        println!("  āœ“ {}", criterion.description);
150    }
151
152    println!("\nā³ Agent is generating e-commerce app...\n");
153    let response = agent.run(task).await;
154
155    let output = extract_output_text(&response.result());
156    println!("šŸ“„ Generated Output:\n");
157    println!("{}\n", output);
158
159    println!("šŸ“Š Goal Progress: {}%", goal.get_progress());
160    println!("\nāœ… Example 2 completed!\n");
161}
162
163// ============================================
164// Example 3: SaaS Dashboard App
165// ============================================
166
167async fn example_3_saas_dashboard() {
168    println!("\n=== Example 3: Generate SaaS Dashboard Next.js App ===\n");
169
170    let mut agent = Agent::new("SaasDashboardGenerator", "ollama::gemma3:latest");
171
172    let mut goal = Goal::new(
173        "Generate a SaaS dashboard application with user management".to_string()
174    );
175
176    goal.add_criterion("User authentication and authorization".to_string());
177    goal.add_criterion("Multi-tenant database structure".to_string());
178    goal.add_criterion("Dashboard with analytics and metrics".to_string());
179    goal.add_criterion("User and team management pages".to_string());
180    goal.add_criterion("Settings and preferences pages".to_string());
181    goal.add_criterion("Billing and subscription management".to_string());
182    goal.add_criterion("API for data collection and reporting".to_string());
183
184    goal.add_sub_goal("Design multi-tenant database schema".to_string(), 0);
185    goal.add_sub_goal("Implement OAuth authentication".to_string(), 1);
186    goal.add_sub_goal("Create dashboard with charts and metrics".to_string(), 2);
187    goal.add_sub_goal("Build team and user management interfaces".to_string(), 3);
188    goal.add_sub_goal("Create settings pages for users and organization".to_string(), 4);
189    goal.add_sub_goal("Implement billing API integration".to_string(), 5);
190    goal.add_sub_goal("Create analytics and reporting system".to_string(), 6);
191    goal.add_sub_goal("Add email notification templates".to_string(), 7);
192
193    goal.status = GoalStatus::InProgress;
194    agent.set_goal(goal.clone());
195
196    let task = TaskRequest::new(
197        "Generate a complete SaaS dashboard Next.js application with:\n\
198         1. Multi-tenant authentication (OAuth + JWT)\n\
199         2. Organization and team management\n\
200         3. Comprehensive dashboard with charts and analytics\n\
201         4. User permission and role management\n\
202         5. Billing integration with Stripe\n\
203         6. Settings pages for users and teams\n\
204         7. Email notifications system\n\
205         8. API logging and activity tracking\n\
206         9. Dark mode support\n\
207         10. Mobile responsive design\n\
208         Include TypeScript, Tailwind CSS, Recharts for visualizations, \
209         and PostgreSQL database models."
210    );
211
212    println!("šŸ“ Task: Generate SaaS Dashboard Application\n");
213    println!("šŸŽÆ Dashboard Features:");
214    for criterion in &goal.success_criteria {
215        println!("  āœ“ {}", criterion.description);
216    }
217
218    println!("\nā³ Agent is generating SaaS dashboard...\n");
219    let response = agent.run(task).await;
220
221    let output = extract_output_text(&response.result());
222    println!("šŸ“„ Generated Output:\n");
223    println!("{}\n", output);
224
225    println!("šŸ“Š Goal Progress: {}%", goal.get_progress());
226    println!("\nāœ… Example 3 completed!\n");
227}
228
229// ============================================
230// Example 4: Blog Platform with CMS
231// ============================================
232
233async fn example_4_blog_platform() {
234    println!("\n=== Example 4: Generate Blog Platform with CMS ===\n");
235
236    let mut agent = Agent::new("BlogCMSGenerator", "ollama::gemma3:latest");
237
238    let mut goal = Goal::new(
239        "Generate a comprehensive blog platform with CMS".to_string()
240    );
241
242    goal.add_criterion("Blog post management system".to_string());
243    goal.add_criterion("Rich text editor with markdown support".to_string());
244    goal.add_criterion("Category and tag system".to_string());
245    goal.add_criterion("Search and filtering functionality".to_string());
246    goal.add_criterion("Comments system with moderation".to_string());
247    goal.add_criterion("SEO optimization (meta tags, sitemap)".to_string());
248    goal.add_criterion("Author management and permissions".to_string());
249    goal.add_criterion("Analytics and engagement tracking".to_string());
250
251    goal.add_sub_goal("Design blog database schema".to_string(), 0);
252    goal.add_sub_goal("Create CMS backend API".to_string(), 1);
253    goal.add_sub_goal("Build post editor with markdown".to_string(), 2);
254    goal.add_sub_goal("Create blog listing and search pages".to_string(), 3);
255    goal.add_sub_goal("Build individual post pages with SEO".to_string(), 4);
256    goal.add_sub_goal("Implement comments system".to_string(), 5);
257    goal.add_sub_goal("Create author profiles and bio".to_string(), 6);
258    goal.add_sub_goal("Build admin dashboard for content management".to_string(), 7);
259    goal.add_sub_goal("Add analytics tracking and reporting".to_string(), 8);
260
261    goal.status = GoalStatus::InProgress;
262    agent.set_goal(goal.clone());
263
264    let task = TaskRequest::new(
265        "Generate a full-featured blog platform with CMS:\n\
266         1. Post creation and editing with rich text editor\n\
267         2. Markdown support with preview\n\
268         3. Category and tag system\n\
269         4. Advanced search with filters\n\
270         5. Comments system with nested replies\n\
271         6. Author profiles with biography\n\
272         7. SEO optimization (sitemaps, meta tags, structured data)\n\
273         8. Social sharing integration\n\
274         9. Email newsletter subscription\n\
275         10. Analytics dashboard for authors\n\
276         11. Reading time estimates\n\
277         12. Related posts suggestions\n\
278         Include TypeScript, Tailwind CSS, next-mdx-remote for markdown, \
279         and MongoDB/PostgreSQL models."
280    );
281
282    println!("šŸ“ Task: Generate Blog Platform with CMS\n");
283    println!("šŸŽÆ Blog Features:");
284    for criterion in &goal.success_criteria {
285        println!("  āœ“ {}", criterion.description);
286    }
287
288    println!("\nā³ Agent is generating blog platform...\n");
289    let response = agent.run(task).await;
290
291    let output = extract_output_text(&response.result());
292    println!("šŸ“„ Generated Output:\n");
293    println!("{}\n", output);
294
295    println!("šŸ“Š Goal Progress: {}%", goal.get_progress());
296    println!("\nāœ… Example 4 completed!\n");
297}
298
299// ============================================
300// Example 5: Extracting and Processing Output
301// ============================================
302
303async fn example_5_output_extraction() {
304    println!("\n=== Example 5: Output Extraction and Processing ===\n");
305
306    let mut agent = Agent::new("OutputProcessor", "ollama::gemma3:latest");
307
308    // Create a simple task to generate specific file outputs
309    let task = TaskRequest::new(
310        "Generate ONLY the following files in proper format:\n\
311         1. A complete package.json file for a Next.js project\n\
312         2. A next.config.js configuration\n\
313         3. A TypeScript types file for common types\n\
314         Format each file with proper headers like:\n\
315         === FILE: package.json ===\n\
316         [file content]\n\
317         === FILE: next.config.js ===\n\
318         [file content]"
319    );
320
321    println!("šŸ“ Task: Generate Specific Configuration Files\n");
322    println!("ā³ Processing...\n");
323
324    let response = agent.run(task).await;
325    let output = extract_output_text(&response.result());
326
327    // Parse output by file
328    let files: HashMap<String, String> = parse_output_by_file(&output);
329
330    println!("šŸ“¦ Generated Files:\n");
331    for (filename, content) in &files {
332        println!("šŸ“„ File: {}", filename);
333        println!("   Lines: {}", content.lines().count());
334        println!("   Size: {} bytes\n", content.len());
335    }
336
337    println!("āœ… Example 5 completed!\n");
338}
339
340// ============================================
341// Helper function to parse output by file
342// ============================================
343
344fn parse_output_by_file(output: &str) -> HashMap<String, String> {
345    let mut files: HashMap<String, String> = HashMap::new();
346    let mut current_file = String::new();
347    let mut current_content = String::new();
348
349    for line in output.lines() {
350        if line.starts_with("=== FILE:") {
351            // Save previous file if exists
352            if !current_file.is_empty() && !current_content.is_empty() {
353                files.insert(current_file.clone(), current_content.trim().to_string());
354            }
355
356            // Extract filename
357            if let Some(filename) = line
358                .strip_prefix("=== FILE:")
359                .and_then(|s| s.strip_suffix(" ==="))
360            {
361                current_file = filename.trim().to_string();
362                current_content.clear();
363            }
364        } else if !current_file.is_empty() {
365            current_content.push_str(line);
366            current_content.push('\n');
367        }
368    }
369
370    // Save last file
371    if !current_file.is_empty() && !current_content.is_empty() {
372        files.insert(current_file, current_content.trim().to_string());
373    }
374
375    files
376}
377
378// ============================================
379// Main function
380// ============================================
381
382#[tokio::main]
383async fn main() {
384    println!("šŸš€ Ceylon Agent - Next.js App Generator Examples\n");
385    println!("This example demonstrates how to use Ceylon agents to:");
386    println!("  • Generate complete Next.js applications");
387    println!("  • Create project structures and configuration");
388    println!("  • Extract structured output from agent responses\n");
389    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n");
390
391    // Run examples
392    example_1_basic_nextjs_app().await;
393    example_2_ecommerce_app().await;
394    example_3_saas_dashboard().await;
395    example_4_blog_platform().await;
396    example_5_output_extraction().await;
397
398    println!("━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━");
399    println!("\nāœ… All Next.js generator examples completed successfully!\n");
400
401    println!("šŸ“š Key Takeaways:");
402    println!("  1. Goals help structure app generation into clear steps");
403    println!("  2. Success criteria define what files/features must exist");
404    println!("  3. extract_output_text() gets text from OutputData");
405    println!("  4. Output can be parsed to extract individual files");
406    println!("  5. Combine with tools for file system operations\n");
407
408    println!("šŸ”— Next steps:");
409    println!("  • Add tools to write generated files to disk");
410    println!("  • Create custom tools for running npm/git commands");
411    println!("  • Integrate with file system for actual project creation");
412    println!("  • Add validation tools to verify generated code");
413    println!("  • Store generated code in memory for multi-step workflows\n");
414
415    println!("šŸ’” Example: Connecting to Tools");
416    println!("```rust");
417    println!("// Create file writing tool");
418    println!("let file_tool = FileWriterTool::new(\"/path/to/project\");");
419    println!("agent.add_tool(Arc::new(file_tool));");
420    println!("");
421    println!("// Agent can now write files during generation");
422    println!("let response = agent.run(task).await;");
423    println!("```\n");
424}
425
426/*
427
428NEXT.JS APP GENERATION WORKFLOW:
429
4301. CREATE GOAL
431   └─ Define what the app should contain
432   └─ List success criteria (files, features)
433   └─ Break into generation steps
434
4352. CREATE TASK
436   └─ Request comprehensive app generation
437   └─ Include tech stack (TypeScript, Tailwind, etc)
438   └─ Specify features and structure
439
4403. RUN AGENT
441   └─ Agent generates code and configuration
442   └─ Returns as OutputData::Text
443
4444. EXTRACT OUTPUT
445   └─ Convert OutputData to String
446   └─ Parse by file sections (=== FILE: name ===)
447   └─ Extract individual components
448
4495. SAVE TO DISK (optional with tools)
450   └─ Create project directory
451   └─ Write each file to correct location
452   └─ Run npm install to set up
453
454EXAMPLE OUTPUT STRUCTURE:
455
456=== FILE: package.json ===
457{
458  "name": "my-app",
459  "version": "1.0.0",
460  ...
461}
462
463=== FILE: next.config.js ===
464/** @type {import('next').NextConfig} */
465const nextConfig = {
466  ...
467}
468
469=== FILE: pages/index.tsx ===
470export default function Home() {
471  ...
472}
473
474*/