Microservice Scaffolder
Run ID: 69cc41e06beabe319cec8fc32026-03-31Development
PantheraHive BOS
BOS Dashboard

Microservice Scaffolder: Architectural Plan

This document outlines the detailed architectural plan for the "Microservice Scaffolder" – a tool designed to rapidly generate a complete, production-ready microservice boilerplate. This plan covers the scaffolder's internal architecture, its user interaction model, and the comprehensive structure of the microservices it will produce.


1. Introduction & Core Objectives

The Microservice Scaffolder aims to significantly accelerate development cycles by providing a robust, opinionated, and fully functional starting point for new microservices. By automating the creation of boilerplate code, infrastructure configurations, and best practices, it ensures consistency, reduces setup time, and minimizes human error.

Core Objectives:


2. High-Level Architecture of the Scaffolder

The Microservice Scaffolder will be a CLI-based application structured around a core templating and file generation engine.

text • 3,211 chars
**Components:**

1.  **User Interaction (CLI):** The primary interface for developers to interact with the scaffolder. It will guide users through the microservice generation process using interactive prompts.
2.  **Configuration & Input Parser:** Processes user inputs from the CLI and any optional configuration files, validating them against predefined schemas.
3.  **Scaffolder Core Logic:** Orchestrates the entire generation process, calling upon the template engine and file generator based on parsed inputs.
4.  **Template Engine:** Renders templates using the collected user inputs to produce actual code and configuration files.
5.  **Template Repository:** A structured collection of parameterized templates for various microservice components (API, DB, Docker, CI/CD, etc.) and different technology stacks.
6.  **File Generator:** Writes the rendered content to the specified output directory, creating the complete microservice project.
7.  **Post-Generation Hooks:** Optional scripts or commands executed after file generation (e.g., `npm install`, `pip install`, `git init`).

---

### 3. Detailed Component Breakdown

#### 3.1. User Interface (CLI)

*   **Technology:** Python with `Click` or `Typer` library for robust command-line argument parsing and interactive prompts (e.g., `inquirerpy`).
*   **Commands:**
    *   `scaffold init <project_name>`: Initializes a new microservice project.
    *   `scaffold list-templates`: Lists available microservice templates (e.g., Python/FastAPI, Node.js/Express).
    *   `scaffold config`: Manages global scaffolder configurations.
*   **Interaction:** Interactive prompts will guide the user through choices such as:
    *   Service Name (e.g., `order-service`)
    *   Programming Language & Framework (e.g., Python/FastAPI, Node.js/Express, Go/Gin)
    *   Database Type (e.g., PostgreSQL, MongoDB)
    *   Authentication Method (e.g., JWT, OAuth2 - placeholder for future)
    *   Message Broker (e.g., Kafka, RabbitMQ - placeholder for future)
    *   CI/CD Provider (e.g., GitHub Actions, GitLab CI)
    *   Deployment Target (e.g., Docker, Kubernetes, AWS ECS)

#### 3.2. Configuration & Input Parser

*   **Mechanism:** Parses CLI arguments and potentially a `scaffold.yaml` or `scaffold.json` file for non-interactive or batch generations.
*   **Validation:** Ensures all required parameters are provided and valid (e.g., project name follows naming conventions, chosen language is supported).
*   **Defaults:** Provides intelligent default values for parameters not explicitly specified by the user.

#### 3.3. Scaffolder Core Logic

*   **Orchestration:** Manages the flow from user input to template rendering and file generation.
*   **Template Selection:** Based on user choices (language, framework, DB), it selects the appropriate set of templates from the repository.
*   **Context Generation:** Creates a data dictionary (context) containing all user inputs and derived values, which is then passed to the template engine.

#### 3.4. Template Engine & Repository

*   **Technology:** `Jinja2` (Python) for its powerful templating capabilities, including loops, conditionals, and macros.
*   **Template Repository Structure:**
    
Sandboxed live preview

5.2. API Layer (FastAPI)

  • Framework: FastAPI with Pydantic for data validation and serialization.
  • Endpoints:

* /health: Basic health check.

* Example CRUD operations (e.g.,

gemini Output

Microservice Scaffolder: Product Service Generation

This deliverable provides a complete, production-ready microservice scaffold for a "Product Service," covering all requested components: Docker setup, API routes, database models, tests, CI/CD pipeline configuration, and deployment scripts. The chosen technology stack is Python with FastAPI, PostgreSQL as the database, SQLAlchemy for ORM, Pytest for testing, Docker for containerization, GitHub Actions for CI/CD, and Kubernetes for deployment.


Project Structure

The generated microservice follows a standard, organized project structure:


product-service/
├── app/
│   ├── api/
│   │   ├── routes/
│   │   │   └── products.py             # FastAPI routes for product CRUD
│   │   └── schemas/
│   │       └── product.py              # Pydantic models for request/response validation
│   ├── core/
│   │   └── config.py                   # Application settings and environment variables
│   ├── db/
│   │   ├── crud/
│   │   │   └── product.py              # Database CRUD operations
│   │   ├── models/
│   │   │   └── product.py              # SQLAlchemy ORM model
│   │   └── database.py                 # Database connection setup
│   ├── tests/
│   │   ├── conftest.py                 # Pytest fixtures for testing
│   │   └── test_products.py            # Unit/integration tests for product API
│   └── main.py                         # Main FastAPI application entry point
├── .github/
│   └── workflows/
│       └── ci-cd.yml                   # GitHub Actions CI/CD pipeline configuration
├── kubernetes/
│   ├── configmap.yaml                  # Kubernetes ConfigMap for environment variables
│   ├── deployment.yaml                 # Kubernetes Deployment for the microservice
│   └── service.yaml                    # Kubernetes Service for exposing the microservice
├── scripts/
│   └─�� deploy.sh                       # Shell script for deploying to Kubernetes
├── Dockerfile                          # Docker build instructions
├── docker-compose.yml                  # Docker Compose for local development
├── requirements.txt                    # Python dependencies
├── .env.example                        # Example environment variables file
└── README.md                           # Project README (placeholder)

1. Application Code (app/)

app/main.py

This is the main entry point for the FastAPI application. It initializes the app, includes API routers, and handles database connection lifecycle.


# app/main.py
from fastapi import FastAPI
from contextlib import asynccontextmanager

from app.api.routes import products
from app.core.config import settings
from app.db.database import database

@asynccontextmanager
async def lifespan(app: FastAPI):
    """
    Handles startup and shutdown events for the application.
    Connects to the database on startup and disconnects on shutdown.
    """
    print("Starting up...")
    await database.connect()
    print("Database connected.")
    yield
    print("Shutting down...")
    await database.disconnect()
    print("Database disconnected.")

app = FastAPI(
    title=settings.PROJECT_NAME,
    version=settings.APP_VERSION,
    description="A microservice for managing products.",
    lifespan=lifespan, # Use the lifespan context manager
    openapi_url=f"{settings.API_V1_STR}/openapi.json",
    docs_url=f"{settings.API_V1_STR}/docs",
    redoc_url=f"{settings.API_V1_STR}/redoc",
)

# Include API routers
app.include_router(products.router, prefix=settings.API_V1_STR, tags=["products"])

@app.get("/", tags=["healthcheck"])
async def root():
    """
    Health check endpoint.
    """
    return {"message": "Product Service is running!"}

# You can add more global error handlers or middleware here if needed

Explanation:

  • Initializes a FastAPI application with project metadata from settings.
  • The lifespan function ensures the database connection is established when the application starts and closed gracefully when it shuts down.
  • Includes the products router, making its endpoints available under the /api/v1 prefix.
  • Provides a basic health check endpoint at the root path.

app/core/config.py

Manages application settings and environment variables.


# app/core/config.py
import os
from pydantic_settings import BaseSettings, SettingsConfigDict
from typing import Optional

class Settings(BaseSettings):
    PROJECT_NAME: str = "Product Service"
    APP_VERSION: str = "0.1.0"
    API_V1_STR: str = "/api/v1"

    DATABASE_URL: str
    TEST_DATABASE_URL: Optional[str] = None # For pytest, if separate test DB is used

    # Security settings (example - expand as needed)
    SECRET_KEY: str = "YOUR_SUPER_SECRET_KEY_FOR_JWT_OR_OTHER_STUFF"
    ALGORITHM: str = "HS256"
    ACCESS_TOKEN_EXPIRE_MINUTES: int = 30

    model_config = SettingsConfigDict(env_file=".env", extra="ignore")

settings = Settings()

Explanation:

  • Uses Pydantic's BaseSettings to load environment variables, providing type validation and default values.
  • SettingsConfigDict(env_file=".env") tells Pydantic to look for an .env file for environment variables.
  • Defines core application settings like project name, API prefix, and database URL.
  • Includes placeholders for security settings, which would be expanded for authentication/authorization.

app/db/database.py

Handles the database connection using SQLAlchemy.


# app/db/database.py
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, declarative_base
from app.core.config import settings

# Create an asynchronous engine for the database
# `future=True` is for SQLAlchemy 2.0 style usage
engine = create_async_engine(settings.DATABASE_URL, echo=True, future=True)

# Configure an asynchronous session factory
# `expire_on_commit=False` prevents objects from being expired after commit,
# which can be useful when accessing attributes after a commit.
async_session_maker = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

# Base class for our declarative models
Base = declarative_base()

class Database:
    """
    A simple wrapper for managing database connection and session.
    """
    def __init__(self):
        self._engine = engine
        self._async_session_maker = async_session_maker

    async def connect(self):
        # In SQLAlchemy 2.0 style, engine connection is managed implicitly by session.
        # This method is primarily for demonstrating connection lifecycle or for
        # specific connection pool management if needed.
        # For a simple FastAPI app, just creating the engine is often enough.
        pass # No explicit connect needed for asyncpg/SQLAlchemy 2.0 style

    async def disconnect(self):
        await self._engine.dispose()
        print("Database engine disposed.")

    async def get_db(self):
        """
        Dependency for FastAPI to get a database session.
        Yields an AsyncSession and ensures it's closed after use.
        """
        async with self._async_session_maker() as session:
            yield session

database = Database()

Explanation:

  • Sets up an asynchronous SQLAlchemy engine using create_async_engine.
  • Creates async_session_maker to produce AsyncSession objects.
  • Base = declarative_base() is the base class for all SQLAlchemy ORM models.
  • The Database class provides connect/disconnect (though less critical for asyncpg/SQLAlchemy 2.0 as connection is managed by sessions) and get_db which is designed to be used as a FastAPI dependency to provide a database session.

app/db/models/product.py

Defines the SQLAlchemy ORM model for Product.


# app/db/models/product.py
import datetime
from sqlalchemy import Column, Integer, String, Float, DateTime, func
from app.db.database import Base

class Product(Base):
    """
    SQLAlchemy ORM model for a product.
    """
    __tablename__ = "products"

    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, index=True, nullable=False)
    description = Column(String, nullable=True)
    price = Column(Float, nullable=False)
    created_at = Column(DateTime, default=func.now(), nullable=False)
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now(), nullable=False)

    def __repr__(self):
        return f"<Product(id={self.id}, name='{self.name}', price={self.price})>"

Explanation:

  • Inherits from Base (defined in database.py).
  • Defines columns with their types and constraints (e.g., primary_key, index, nullable).
  • func.now() is used for created_at and updated_at to automatically set timestamps.

app/api/schemas/product.py

Defines Pydantic models for request and response data validation.


# app/api/schemas/product.py
from pydantic import BaseModel, Field
from typing import Optional
import datetime

class ProductBase(BaseModel):
    """
    Base Pydantic model for product attributes.
    """
    name: str = Field(..., min_length=3, max_length=100, example="Laptop Pro")
    description: Optional[str] = Field(None, max_length=500, example="High-performance laptop for professionals.")
    price: float = Field(..., gt=0, example=1200.50)

class ProductCreate(ProductBase):
    """
    Pydantic model for creating a new product.
    Inherits from ProductBase.
    """
    pass # No additional fields for creation beyond base

class ProductUpdate(ProductBase):
    """
    Pydantic model for updating an existing product.
    All fields are optional for partial updates.
    """
    name: Optional[str] = Field(None, min_length=3, max_length=100, example="Laptop Pro Max")
    price: Optional[float] = Field(None, gt=0, example=1350.00)

class ProductInDB(ProductBase):
    """
    Pydantic model representing a product as stored in the database,
    including auto-generated fields like ID and timestamps.
    """
    id: int
    created_at: datetime.datetime
    updated_at: datetime.datetime

    class Config:
        from_attributes = True # Allows mapping from ORM objects
        # orm_mode = True (for Pydantic v1)

Explanation:

  • ProductBase defines common fields with validation rules (e.g., min_length, gt for "greater than").
  • ProductCreate extends ProductBase for input when creating.
  • ProductUpdate makes all fields optional for PATCH requests.
  • ProductInDB includes database-generated fields like id, created_at, updated_at and uses from_attributes = True (or orm_mode = True for Pydantic v1) to allow direct conversion from SQLAlchemy ORM objects.

app/db/crud/product.py

Contains functions for performing CRUD operations on the Product model.


# app/db/crud/product.py
from typing import List, Optional

from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, delete

from app.db.models.product import Product
from app.api.schemas.product import ProductCreate, ProductUpdate

async def get_product(db: AsyncSession, product_id: int) -> Optional[Product]:
    """
    Retrieves a single product by its ID.
    """
    result = await db.execute(select(Product).filter(Product.id == product_id))
    return result.scalar_one_or_none()

async def get_products(db: AsyncSession, skip: int = 0, limit: int = 100) -> List[Product]:
    """
    Retrieves a list
gemini Output

Microservice Scaffolder: Review and Documentation

This document provides a comprehensive review and detailed documentation for the microservice that has been generated by the "Microservice Scaffolder" workflow. This output is designed to be a definitive guide, enabling you to understand, develop, test, and deploy your new microservice effectively.


1. Introduction and Overview

Congratulations! Your new microservice has been successfully scaffolded. This deliverable outlines the structure, components, and functionalities of the generated codebase, providing actionable instructions for immediate development and deployment.

Project Name: [YourServiceName]-microservice (e.g., ProductCatalog-microservice)

Purpose: A foundational microservice designed for efficient management of [YourResourceName] resources (e.g., Product resources). It provides a robust, scalable, and maintainable starting point for your domain-specific business logic.

Key Technologies & Principles Implemented:

  • Language & Framework: Python 3.x with FastAPI (for high-performance API development).
  • Database: PostgreSQL (via SQLAlchemy ORM for robust data management).
  • Containerization: Docker (for consistent development and deployment environments).
  • Testing: Pytest (for comprehensive unit and integration testing).
  • CI/CD: GitHub Actions (ready-to-use pipeline for automated testing and deployment).
  • Deployment Target: Kubernetes (production-ready deployment manifests).
  • API Design: RESTful principles with automatic OpenAPI/Swagger documentation.
  • Data Validation: Pydantic models for request/response validation and serialization.
  • Configuration: Environment variables for flexible and secure configuration.

2. Project Structure

The generated microservice adheres to a clean, modular, and scalable project structure. Below is an overview of the directory layout and the purpose of each component:


.
├── src/
│   ├── api/                 # Defines API endpoints, request/response schemas, and route handlers.
│   │   ├���─ v1/              # Versioned API routes (e.g., for /api/v1/products)
│   │   │   └── [resource].py # Specific API routes for a resource (e.g., products.py)
│   │   └── __init__.py
│   ├── core/                # Core application logic, configuration, dependencies, and utilities.
│   │   ├── config.py        # Application settings loaded from environment variables.
│   │   ├── dependencies.py  # Dependency injection for database sessions, etc.
│   │   ├── exceptions.py    # Custom exception definitions and handlers.
│   │   └── __init__.py
│   ├── database/            # Database connection, ORM models, and migration scripts.
│   │   ├── models.py        # SQLAlchemy ORM models for database tables.
│   │   ├── session.py       # Database session management.
│   │   └── __init__.py
│   └── main.py              # Main FastAPI application entry point, includes routers, middleware.
├── tests/                   # Contains unit and integration tests for the application.
│   ├── unit/                # Unit tests for individual functions/components.
│   ├── integration/         # Integration tests for API endpoints and database interactions.
│   └── conftest.py          # Pytest fixtures for tests.
��── docker/                  # Docker-related files for building and running the application.
│   ├── Dockerfile           # Defines the Docker image for the microservice.
│   └── docker-compose.yml   # Local development setup with application and database.
├── deployment/              # Kubernetes manifests for production deployment.
│   ├── k8s/                 # Kubernetes resource definitions
│   │   ├── deployment.yaml  # Kubernetes Deployment for the microservice.
│   │   ├── service.yaml     # Kubernetes Service for internal cluster access.
│   │   └── ingress.yaml     # (Optional) Kubernetes Ingress for external access.
│   └── README.md            # Instructions for Kubernetes deployment.
├── .github/                 # GitHub Actions CI/CD workflow definitions.
│   └── workflows/
│       └── main.yml         # Defines the build, test, and deploy pipeline.
├── .env.example             # Example environment variables for local development.
├── .gitignore               # Specifies intentionally untracked files to ignore.
├── README.md                # Project README file with essential setup and usage instructions.
├── requirements.txt         # Python package dependencies.
└── alembic.ini              # Alembic configuration for database migrations.

3. Component-Specific Documentation and Review

3.1. Core Application Logic (src/main.py, src/core/)

  • src/main.py: This is the entry point of your FastAPI application. It initializes the FastAPI instance, includes the API routers, sets up event handlers for database connection, and registers global middleware and exception handlers.
  • src/core/config.py: Manages application settings. It uses Pydantic's BaseSettings to load configurations from environment variables (.env file locally, or actual environment variables in production). Action: Customize Settings class with any new configuration parameters your microservice requires.
  • src/core/dependencies.py: Defines dependency injection functions, primarily for providing a database session (get_db) to your API route handlers. This promotes reusability and testability.
  • src/core/exceptions.py: Contains custom exception classes (e.g., NotFoundException, ConflictException) and global exception handlers to provide consistent and user-friendly error responses.

3.2. API Routes (src/api/)

  • Structure: API routes are organized by version (v1/) and then by resource ([resource].py). This modularity makes it easy to add new resources or version your API.
  • Example Endpoints: The scaffolded microservice includes example CRUD (Create, Read, Update, Delete) endpoints for a [YourResourceName] resource.

* POST /api/v1/[resource]s: Create a new resource.

* GET /api/v1/[resource]s: Retrieve all resources.

* GET /api/v1/[resource]s/{id}: Retrieve a single resource by ID.

* PUT /api/v1/[resource]s/{id}: Update an existing resource.

* DELETE /api/v1/[resource]s/{id}: Delete a resource.

  • Pydantic Models: Request bodies and response payloads are defined using Pydantic models (e.g., schemas.py within each resource directory). These models ensure automatic data validation, serialization, and deserialization, improving API robustness and developer experience.
  • OpenAPI/Swagger UI: FastAPI automatically generates interactive API documentation. Access it locally at http://localhost:8000/docs (Swagger UI) or http://localhost:8000/redoc (ReDoc). This documentation is invaluable for API consumers.

3.3. Database Models and Migrations (src/database/, alembic.ini)

  • src/database/models.py: Contains SQLAlchemy ORM models, representing your database tables. An example [YourResourceName] model is provided, demonstrating basic field types and relationships.

* Action: Extend or modify these models to define your specific data structures.

  • src/database/session.py: Handles the creation and management of database connections and sessions. It ensures proper session lifecycle (opening and closing connections).
  • Alembic: The project is configured with Alembic for database schema migrations.

* Action:

1. Initialize migrations: alembic revision --autogenerate -m "Initial migration"

2. Apply migrations: alembic upgrade head

* This allows for controlled evolution of your database schema as your application grows.

3.4. Docker Setup (docker/)

  • Dockerfile: Defines the instructions to build a Docker image for your microservice. It uses a multi-stage build pattern to create a lean production image:

* Build Stage: Installs dependencies and builds any necessary assets.

* Runtime Stage: Copies only the essential application code and runtime dependencies, resulting in a smaller, more secure image.

  • docker-compose.yml: Provides a convenient setup for local development. It orchestrates two services:

* app: Your FastAPI microservice.

* db: A PostgreSQL database instance.

* Action: Run docker-compose up --build in the docker/ directory to start your application and database locally.

3.5

microservice_scaffolder.txt
Download source file
Copy all content
Full output as text
Download ZIP
IDE-ready project ZIP
Copy share link
Permanent URL for this run
Get Embed Code
Embed this result on any website
Print / Save PDF
Use browser print dialog
\n\n\n"); var hasSrcMain=Object.keys(extracted).some(function(k){return k.indexOf("src/main")>=0;}); if(!hasSrcMain) zip.file(folder+"src/main."+ext,"import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport App from './App'\nimport './index.css'\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n \n \n \n)\n"); var hasSrcApp=Object.keys(extracted).some(function(k){return k==="src/App."+ext||k==="App."+ext;}); if(!hasSrcApp) zip.file(folder+"src/App."+ext,"import React from 'react'\nimport './App.css'\n\nfunction App(){\n return(\n
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n
\n )\n}\nexport default App\n"); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e}\n.app{min-height:100vh;display:flex;flex-direction:column}\n.app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px}\nh1{font-size:2.5rem;font-weight:700}\n"); zip.file(folder+"src/App.css",""); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/pages/.gitkeep",""); zip.file(folder+"src/hooks/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\n## Open in IDE\nOpen the project folder in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- Vue (Vite + Composition API + TypeScript) --- */ function buildVue(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "type": "module",\n "scripts": {\n "dev": "vite",\n "build": "vue-tsc -b && vite build",\n "preview": "vite preview"\n },\n "dependencies": {\n "vue": "^3.5.13",\n "vue-router": "^4.4.5",\n "pinia": "^2.3.0",\n "axios": "^1.7.9"\n },\n "devDependencies": {\n "@vitejs/plugin-vue": "^5.2.1",\n "typescript": "~5.7.3",\n "vite": "^6.0.5",\n "vue-tsc": "^2.2.0"\n }\n}\n'); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\nimport { resolve } from 'path'\n\nexport default defineConfig({\n plugins: [vue()],\n resolve: { alias: { '@': resolve(__dirname,'src') } }\n})\n"); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]}\n'); zip.file(folder+"tsconfig.app.json",'{\n "compilerOptions":{\n "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"],\n "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true,\n "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue",\n "strict":true,"paths":{"@/*":["./src/*"]}\n },\n "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"]\n}\n'); zip.file(folder+"env.d.ts","/// \n"); zip.file(folder+"index.html","\n\n\n \n \n "+slugTitle(pn)+"\n\n\n
\n \n\n\n"); var hasMain=Object.keys(extracted).some(function(k){return k==="src/main.ts"||k==="main.ts";}); if(!hasMain) zip.file(folder+"src/main.ts","import { createApp } from 'vue'\nimport { createPinia } from 'pinia'\nimport App from './App.vue'\nimport './assets/main.css'\n\nconst app = createApp(App)\napp.use(createPinia())\napp.mount('#app')\n"); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue","\n\n\n\n\n"); zip.file(folder+"src/assets/main.css","*{margin:0;padding:0;box-sizing:border-box}body{font-family:system-ui,sans-serif;background:#fff;color:#213547}\n"); zip.file(folder+"src/components/.gitkeep",""); zip.file(folder+"src/views/.gitkeep",""); zip.file(folder+"src/stores/.gitkeep",""); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nnpm run dev\n\`\`\`\n\n## Build\n\`\`\`bash\nnpm run build\n\`\`\`\n\nOpen in VS Code or WebStorm.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n"); } /* --- Angular (v19 standalone) --- */ function buildAngular(zip,folder,app,code,panelTxt){ var pn=pkgName(app); var C=cc(pn); var sel=pn.replace(/_/g,"-"); var extracted=extractCode(panelTxt); zip.file(folder+"package.json",'{\n "name": "'+pn+'",\n "version": "0.0.0",\n "scripts": {\n "ng": "ng",\n "start": "ng serve",\n "build": "ng build",\n "test": "ng test"\n },\n "dependencies": {\n "@angular/animations": "^19.0.0",\n "@angular/common": "^19.0.0",\n "@angular/compiler": "^19.0.0",\n "@angular/core": "^19.0.0",\n "@angular/forms": "^19.0.0",\n "@angular/platform-browser": "^19.0.0",\n "@angular/platform-browser-dynamic": "^19.0.0",\n "@angular/router": "^19.0.0",\n "rxjs": "~7.8.0",\n "tslib": "^2.3.0",\n "zone.js": "~0.15.0"\n },\n "devDependencies": {\n "@angular-devkit/build-angular": "^19.0.0",\n "@angular/cli": "^19.0.0",\n "@angular/compiler-cli": "^19.0.0",\n "typescript": "~5.6.0"\n }\n}\n'); zip.file(folder+"angular.json",'{\n "$schema": "./node_modules/@angular/cli/lib/config/schema.json",\n "version": 1,\n "newProjectRoot": "projects",\n "projects": {\n "'+pn+'": {\n "projectType": "application",\n "root": "",\n "sourceRoot": "src",\n "prefix": "app",\n "architect": {\n "build": {\n "builder": "@angular-devkit/build-angular:application",\n "options": {\n "outputPath": "dist/'+pn+'",\n "index": "src/index.html",\n "browser": "src/main.ts",\n "tsConfig": "tsconfig.app.json",\n "styles": ["src/styles.css"],\n "scripts": []\n }\n },\n "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"}\n }\n }\n }\n}\n'); zip.file(folder+"tsconfig.json",'{\n "compileOnSave": false,\n "compilerOptions": {"baseUrl":"./","outDir":"./dist/out-tsc","forceConsistentCasingInFileNames":true,"strict":true,"noImplicitOverride":true,"noPropertyAccessFromIndexSignature":true,"noImplicitReturns":true,"noFallthroughCasesInSwitch":true,"paths":{"@/*":["src/*"]},"skipLibCheck":true,"esModuleInterop":true,"sourceMap":true,"declaration":false,"experimentalDecorators":true,"moduleResolution":"bundler","importHelpers":true,"target":"ES2022","module":"ES2022","useDefineForClassFields":false,"lib":["ES2022","dom"]},\n "references":[{"path":"./tsconfig.app.json"}]\n}\n'); zip.file(folder+"tsconfig.app.json",'{\n "extends":"./tsconfig.json",\n "compilerOptions":{"outDir":"./dist/out-tsc","types":[]},\n "files":["src/main.ts"],\n "include":["src/**/*.d.ts"]\n}\n'); zip.file(folder+"src/index.html","\n\n\n \n "+slugTitle(pn)+"\n \n \n \n\n\n \n\n\n"); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser';\nimport { appConfig } from './app/app.config';\nimport { AppComponent } from './app/app.component';\n\nbootstrapApplication(AppComponent, appConfig)\n .catch(err => console.error(err));\n"); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; }\nbody { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; }\n"); var hasComp=Object.keys(extracted).some(function(k){return k.indexOf("app.component")>=0;}); if(!hasComp){ zip.file(folder+"src/app/app.component.ts","import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\n\n@Component({\n selector: 'app-root',\n standalone: true,\n imports: [RouterOutlet],\n templateUrl: './app.component.html',\n styleUrl: './app.component.css'\n})\nexport class AppComponent {\n title = '"+pn+"';\n}\n"); zip.file(folder+"src/app/app.component.html","
\n
\n

"+slugTitle(pn)+"

\n

Built with PantheraHive BOS

\n
\n \n
\n"); zip.file(folder+"src/app/app.component.css",".app-header{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:60vh;gap:16px}h1{font-size:2.5rem;font-weight:700;color:#6366f1}\n"); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';\nimport { provideRouter } from '@angular/router';\nimport { routes } from './app.routes';\n\nexport const appConfig: ApplicationConfig = {\n providers: [\n provideZoneChangeDetection({ eventCoalescing: true }),\n provideRouter(routes)\n ]\n};\n"); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n"); Object.keys(extracted).forEach(function(p){ var fp=p.startsWith("src/")?p:"src/"+p; zip.file(folder+fp,extracted[p]); }); zip.file(folder+"README.md","# "+slugTitle(pn)+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\nng serve\n# or: npm start\n\`\`\`\n\n## Build\n\`\`\`bash\nng build\n\`\`\`\n\nOpen in VS Code with Angular Language Service extension.\n"); zip.file(folder+".gitignore","node_modules/\ndist/\n.env\n.DS_Store\n*.local\n.angular/\n"); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/m,"").trim(); var reqMap={"numpy":"numpy","pandas":"pandas","sklearn":"scikit-learn","tensorflow":"tensorflow","torch":"torch","flask":"flask","fastapi":"fastapi","uvicorn":"uvicorn","requests":"requests","sqlalchemy":"sqlalchemy","pydantic":"pydantic","dotenv":"python-dotenv","PIL":"Pillow","cv2":"opencv-python","matplotlib":"matplotlib","seaborn":"seaborn","scipy":"scipy"}; var reqs=[]; Object.keys(reqMap).forEach(function(k){if(src.indexOf("import "+k)>=0||src.indexOf("from "+k)>=0)reqs.push(reqMap[k]);}); var reqsTxt=reqs.length?reqs.join("\n"):"# add dependencies here\n"; zip.file(folder+"main.py",src||"# "+title+"\n# Generated by PantheraHive BOS\n\nprint(title+\" loaded\")\n"); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\npython3 -m venv .venv\nsource .venv/bin/activate\npip install -r requirements.txt\n\`\`\`\n\n## Run\n\`\`\`bash\npython main.py\n\`\`\`\n"); zip.file(folder+".gitignore",".venv/\n__pycache__/\n*.pyc\n.env\n.DS_Store\n"); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^\`\`\`[\w]*\n?/m,"").replace(/\n?\`\`\`$/m,"").trim(); var depMap={"mongoose":"^8.0.0","dotenv":"^16.4.5","axios":"^1.7.9","cors":"^2.8.5","bcryptjs":"^2.4.3","jsonwebtoken":"^9.0.2","socket.io":"^4.7.4","uuid":"^9.0.1","zod":"^3.22.4","express":"^4.18.2"}; var deps={}; Object.keys(depMap).forEach(function(k){if(src.indexOf(k)>=0)deps[k]=depMap[k];}); if(!deps["express"])deps["express"]="^4.18.2"; var pkgJson=JSON.stringify({"name":pn,"version":"1.0.0","main":"src/index.js","scripts":{"start":"node src/index.js","dev":"nodemon src/index.js"},"dependencies":deps,"devDependencies":{"nodemon":"^3.0.3"}},null,2)+"\n"; zip.file(folder+"package.json",pkgJson); var fallback="const express=require(\"express\");\nconst app=express();\napp.use(express.json());\n\napp.get(\"/\",(req,res)=>{\n res.json({message:\""+title+" API\"});\n});\n\nconst PORT=process.env.PORT||3000;\napp.listen(PORT,()=>console.log(\"Server on port \"+PORT));\n"; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000\n"); zip.file(folder+".gitignore","node_modules/\n.env\n.DS_Store\n"); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Setup\n\`\`\`bash\nnpm install\n\`\`\`\n\n## Run\n\`\`\`bash\nnpm run dev\n\`\`\`\n"); } /* --- Vanilla HTML --- */ function buildVanillaHtml(zip,folder,app,code){ var title=slugTitle(app); var isFullDoc=code.trim().toLowerCase().indexOf("=0||code.trim().toLowerCase().indexOf("=0; var indexHtml=isFullDoc?code:"\n\n\n\n\n"+title+"\n\n\n\n"+code+"\n\n\n\n"; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */\n*{margin:0;padding:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e}\n"); zip.file(folder+"script.js","/* "+title+" — scripts */\n"); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\n## Open\nDouble-click \`index.html\` in your browser.\n\nOr serve locally:\n\`\`\`bash\nnpx serve .\n# or\npython3 -m http.server 3000\n\`\`\`\n"); zip.file(folder+".gitignore",".DS_Store\nnode_modules/\n.env\n"); } /* ===== MAIN ===== */ var sc=document.createElement("script"); sc.src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"; sc.onerror=function(){ if(lbl)lbl.textContent="Download ZIP"; alert("JSZip load failed — check connection."); }; sc.onload=function(){ var zip=new JSZip(); var base=(_phFname||"output").replace(/\.[^.]+$/,""); var app=base.toLowerCase().replace(/[^a-z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"my_app"; var folder=app+"/"; var vc=document.getElementById("panel-content"); var panelTxt=vc?(vc.innerText||vc.textContent||""):""; var lang=detectLang(_phCode,panelTxt); if(_phIsHtml){ buildVanillaHtml(zip,folder,app,_phCode); } else if(lang==="flutter"){ buildFlutter(zip,folder,app,_phCode,panelTxt); } else if(lang==="react-native"){ buildReactNative(zip,folder,app,_phCode,panelTxt); } else if(lang==="swift"){ buildSwift(zip,folder,app,_phCode,panelTxt); } else if(lang==="kotlin"){ buildKotlin(zip,folder,app,_phCode,panelTxt); } else if(lang==="react"){ buildReact(zip,folder,app,_phCode,panelTxt); } else if(lang==="vue"){ buildVue(zip,folder,app,_phCode,panelTxt); } else if(lang==="angular"){ buildAngular(zip,folder,app,_phCode,panelTxt); } else if(lang==="python"){ buildPython(zip,folder,app,_phCode); } else if(lang==="node"){ buildNode(zip,folder,app,_phCode); } else { /* Document/content workflow */ var title=app.replace(/_/g," "); var md=_phAll||_phCode||panelTxt||"No content"; zip.file(folder+app+".md",md); var h=""+title+""; h+="

"+title+"

"; var hc=md.replace(/&/g,"&").replace(//g,">"); hc=hc.replace(/^### (.+)$/gm,"

$1

"); hc=hc.replace(/^## (.+)$/gm,"

$1

"); hc=hc.replace(/^# (.+)$/gm,"

$1

"); hc=hc.replace(/\*\*(.+?)\*\*/g,"$1"); hc=hc.replace(/\n{2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+"\n\nGenerated by PantheraHive BOS.\n\nFiles:\n- "+app+".md (Markdown)\n- "+app+".html (styled HTML)\n"); } zip.generateAsync({type:"blob"}).then(function(blob){ var a=document.createElement("a"); a.href=URL.createObjectURL(blob); a.download=app+".zip"; a.click(); URL.revokeObjectURL(a.href); if(lbl)lbl.textContent="Download ZIP"; }); }; document.head.appendChild(sc); } function phShare(){navigator.clipboard.writeText(window.location.href).then(function(){var el=document.getElementById("ph-share-lbl");if(el){el.textContent="Link copied!";setTimeout(function(){el.textContent="Copy share link";},2500);}});}function phEmbed(){var runId=window.location.pathname.split("/").pop().replace(".html","");var embedUrl="https://pantherahive.com/embed/"+runId;var code='';navigator.clipboard.writeText(code).then(function(){var el=document.getElementById("ph-embed-lbl");if(el){el.textContent="Embed code copied!";setTimeout(function(){el.textContent="Get Embed Code";},2500);}});}