@startuml nuxt-with-rust-project

!theme vibrant
skinparam backgroundColor #FEFEFE

title Nuxt 4 Project with Rust Backend\n"Cross-Language Development Made Simple"

package "my-app/ (Project Root)" {

  ' Configuration files
  file "make.toml" as maketoml #Gold
  note left of maketoml
    **Universal Project Definition**

    [project]
    name = "my-app"
    version = "1.0.0"

    [workspace.frontend]
    path = "apps/web"
    runtime = "node:20"
    package_manager = "pnpm"
    framework = "nuxt"
    framework_version = "4.0"

    [workspace.backend]
    path = "apps/api"
    runtime = "rust:1.75"
    package_manager = "cargo"
    framework = "axum"
    framework_version = "0.7"

    [workspace.shared]
    path = "packages/types"
    runtime = "node:20"
    language = "typescript"

    # Cross-language lifecycle
    [lifecycle.init]
    commands = [
      "ggen init:workspace frontend --template nuxt-4",
      "ggen init:workspace backend --template rust-axum",
      "ggen init:workspace shared --template ts-types",
      "ggen link:workspaces"
    ]

    [lifecycle.dev]
    command = "ggen parallel:dev"
    workspaces = ["frontend", "backend"]
    env_sync = true  # Share env vars

    [lifecycle.build]
    command = "ggen sequential:build"
    order = ["shared", "backend", "frontend"]

    [lifecycle."generate:api"]
    description = "Generate API endpoint in Rust + Nuxt composable"
    commands = [
      "ggen gen api {{name}} --workspace backend",
      "ggen gen composable use{{name}} --workspace frontend",
      "ggen gen types {{name}} --workspace shared"
    ]

    # Smart hooks that work across languages
    [hooks]
    before_build = [
      "ggen validate:versions",  # Check Rust/Node versions
      "ggen sync:types",         # Sync TypeScript types from Rust
    ]
    after_build = [
      "ggen bundle:analyze",
      "ggen api:docs"
    ]

    # Dependencies (both Rust and Node)
    [deps]
    node = ">=20.0.0"
    pnpm = ">=8.0.0"
    rust = ">=1.75.0"
    cargo = ">=1.75.0"
  end note

  file "ggen.toml" as ggentoml #LightGreen
  note right of ggentoml
    [project]
    templates = "templates"

    [rdf]
    base = "http://example.org/my-app/"
    prefixes = {
      api = "http://example.org/api/",
      ui = "http://example.org/ui/"
    }

    [vars]
    author = "Your Name"
    api_port = 4000
    web_port = 3000
  end note

  ' Workspace structure
  folder "apps/" {
    folder "web/ (Nuxt 4)" as web {
      file "nuxt.config.ts" as nuxtconfig
      folder "components/"
      folder "composables/" {
        file "useApi.ts" #LightBlue
        note right
          // Generated by ggen
          // Talks to Rust backend
          export const useApi = () => {
            const config = useRuntimeConfig()
            return $fetch(config.public.apiUrl)
          }
        end note
      }
      folder "pages/"
    }

    folder "api/ (Rust + Axum)" as api {
      file "Cargo.toml" as apiCargo
      folder "src/" {
        file "main.rs" #Orange
        file "routes/" #Orange
        note right
          // Generated by ggen
          use axum::{Router, routing::get};

          #[tokio::main]
          async fn main() {
              let app = Router::new()
                  .route("/api/health", get(health));

              axum::Server::bind(&"0.0.0.0:4000".parse().unwrap())
                  .serve(app.into_make_service())
                  .await
                  .unwrap();
          }
        end note
      }
    }
  }

  folder "packages/" {
    folder "types/ (Shared TypeScript)" as types {
      file "index.ts" #LightBlue
      note right
        // Generated from Rust types
        // via ggen sync:types
        export interface User {
          id: string;
          email: string;
          created_at: Date;
        }
      end note
    }
  }

  folder "templates/" {
    file "api-route.rs.tmpl" #LightCoral
    note bottom
      ---
      to: "apps/api/src/routes/{{name}}.rs"
      sh_before: "ggen validate:route {{name}}"
      sh_after: "cargo fmt {{output}}"
      ---
      use axum::{Json, extract::Path};

      pub async fn {{name}}_handler(
          Path(id): Path<String>
      ) -> Json<Response> {
          // Implementation
      }
    end note

    file "composable.ts.tmpl" #LightCoral
    note bottom
      ---
      to: "apps/web/composables/use{{name}}.ts"
      sh_before: "ggen validate:name {{name}}"
      sh_after: "pnpm exec prettier --write {{output}}"
      ---
      export const use{{name}} = () => {
        return useFetch('/api/{{name | kebabCase}}')
      }
    end note
  }

  folder ".ggen/" {
    file "state.json" as state #Yellow
    note right
      {
        "workspaces": {
          "frontend": {
            "runtime": "node:20.10.0",
            "framework": "nuxt:4.0.0",
            "last_build": "2025-01-10T12:00:00Z"
          },
          "backend": {
            "runtime": "rust:1.75.0",
            "framework": "axum:0.7.0",
            "last_build": "2025-01-10T12:00:00Z"
          }
        },
        "generated": {
          "api_routes": ["health", "users", "posts"],
          "composables": ["useApi", "useAuth"],
          "types_synced": true
        }
      }
    end note
  }
}

actor Developer

' Developer workflows
Developer -> maketoml : ggen init
note right
  **One command, cross-language setup**
  - Scaffolds Nuxt frontend
  - Scaffolds Rust backend
  - Configures TypeScript types
  - Links workspaces
  - Sets up hot reload
end note

Developer -> maketoml : ggen dev
note right
  **Parallel dev servers**
  - Starts Nuxt on :3000
  - Starts Rust API on :4000
  - Hot reload both
  - Syncs types automatically
end note

Developer -> maketoml : ggen generate:api users
note right
  **Cross-language generation**
  1. Creates Rust route in api/
  2. Creates Nuxt composable in web/
  3. Creates TypeScript types in packages/
  4. All three stay in sync!
end note

Developer -> maketoml : ggen build
note right
  **Smart build order**
  1. Builds shared types first
  2. Builds Rust API (checks types)
  3. Builds Nuxt frontend (uses API types)
  4. All type-safe!
end note

note as why
  **Why this changes everything:**

  1. **Rust as infrastructure** - Fast APIs, no Node.js overhead
  2. **Type safety** - Rust types → TypeScript types automatically
  3. **Single command** - ggen works across languages
  4. **Fast feedback** - Rust compiles while Nuxt reloads
  5. **Best of both** - Rust performance + Vue DX

  **Adoption path:**
  - Teams already using Nuxt can add Rust gradually
  - ggen handles the complexity
  - Templates generate boilerplate in both languages
  - State tracking prevents drift
end why

@enduml
