API Documentation Generator
Run ID: 69cadac974bac0555ea30e2f2026-03-30Development
PantheraHive BOS
BOS Dashboard

API Documentation Generator: Architecture Plan

This document outlines the detailed architecture plan for the "API Documentation Generator." The goal is to create a robust, extensible, and user-friendly system capable of generating professional API documentation from various sources, including endpoint descriptions, request/response examples, authentication guides, and SDK usage examples.


1. System Overview & High-Level Architecture

The API Documentation Generator will be designed as a modular system, allowing for flexible input sources, a standardized internal representation, and multiple output formats. It will primarily function as a processing pipeline that takes API definitions as input and renders them into human-readable documentation.

Core Principles:

High-Level Diagram:

text • 1,567 chars
+-------------------+      +-------------------------+      +---------------------------+      +-------------------+
|                   |      |                         |      |                           |      |                   |
|  API Definition   |      |   Parsing & Validation  |      |   Intermediate Data Model |      |  Documentation    |
|   (Input Sources) |----->|         Engine          |----->|     (Standardized IR)     |<---->| Generation Engine |----->|  Output Formats   |
|                   |      |                         |      |                           |      |    (Renderer)     |      |                   |
+-------------------+      +-------------------------+      +---------------------------+      +---------------------------+
       ^                                                                                                |
       |                                                                                                v
       |                                                                                        +-------------------+
       |                                                                                        | SDK Generation    |
       |                                                                                        | (Optional Module) |
       |                                                                                        +-------------------+
       |
+-------------------+
|                   |
|  User Interface   |
| (CLI/Web Portal)  |
+-------------------+
Sandboxed live preview

2. Core Components & Services

2.1. Input Source Adapters

These components are responsible for consuming various API definition formats.

  • OpenAPI/Swagger Parser: Supports OpenAPI Specification versions 2.0 and 3.x (JSON/YAML).
  • Postman Collection Parser: Supports Postman Collection formats (v2.0, v2.1).
  • RAML Parser: Supports RESTful API Modeling Language specifications.
  • Code Annotation Parser (Future): For extracting API definitions directly from source code (e.g., JSDoc, Springfox, NestJS Swagger).
  • Custom Input/Configuration: A mechanism for users to provide additional documentation content, examples, or overrides not present in the primary API definition.

2.2. Parsing & Validation Engine

This central component takes input from the adapters, validates its structure and content against relevant schemas, and transforms it into a standardized internal representation.

  • Schema Validation: Ensures the input API definition adheres to its respective specification.
  • Syntactic & Semantic Validation: Checks for common errors, missing fields, and logical inconsistencies.
  • Transformation Logic: Maps various input schema elements (endpoints, parameters, responses, security schemes) into the unified Intermediate Data Model.

2.3. Intermediate Data Model (IDM)

A language-agnostic, standardized data structure that represents the API information in a consistent format, regardless of the original input source. This is crucial for decoupling the parsers from the renderers.

  • API Metadata: Title, description, version, base URL, contact info.
  • Endpoints: Path, HTTP method, summary, description, tags, deprecation status.
  • Parameters: Name, location (path, query, header, cookie, body), type, format, required, description, examples.
  • Request Bodies: Content types, schemas, examples.
  • Responses: Status codes, descriptions, content types, schemas, headers, examples.
  • Schemas/Models: Data structures (objects, arrays, primitives), properties, descriptions, examples.
  • Security Schemes: Types (API Key, OAuth2, HTTP Bearer), descriptions, flows.
  • Authentication Guides: Structured fields for detailing authentication steps.
  • Usage Examples: Code snippets for various languages (e.g., cURL, Python, JavaScript, Java) for requests and responses.

2.4. Documentation Generation Engine (Renderer)

This component takes the IDM and renders it into the desired output format using predefined or custom templates.

  • Template Engine: Supports a flexible templating language (e.g., Handlebars, Jinja, Liquid) to allow for customization of the generated documentation's look and feel.
  • Output Formatters: Modules to generate different output types.

* Static HTML: For browser-based viewing, often with interactive elements (e.g., search, collapsible sections).

* Markdown: For easy integration into Git repositories or other documentation platforms.

* PDF: For printable or offline versions.

* Custom Formats: Extensible to support other formats as needed.

  • Asset Management: Handles images, CSS, JavaScript files required for static HTML output.

2.5. SDK Generation Module (Optional/Advanced)

If in scope, this module would leverage the IDM to generate client SDKs in various programming languages.

  • Language-Specific Code Generation: Templates for generating client libraries (e.g., Python, Java, JavaScript, Go).
  • Configuration: Options for namespace, package names, client library specific settings.

2.6. User Interface (UI)

Provides an interface for users to configure the generation process.

  • Command Line Interface (CLI): For automated workflows and integration into CI/CD pipelines.

* Specify input file paths, output directory, template, output format.

* Configuration options for customization.

  • Web-based Portal (Future/Advanced): A graphical interface for uploading API definitions, selecting templates, previewing, and generating documentation.

* Project management features.

* User authentication and access control (if hosted).


3. Data Flow

  1. Input Acquisition: User provides an API definition file (OpenAPI, Postman, etc.) via CLI or Web UI.
  2. Parsing & Validation: The appropriate Input Source Adapter reads the file, and the Parsing & Validation Engine processes it.

* Validates against the respective schema.

* Extracts relevant API details.

  1. Intermediate Representation: The validated and extracted data is transformed into the standardized Intermediate Data Model (IDM).
  2. Enrichment (Optional): Additional user-provided content (e.g., custom markdown, specific authentication steps, extended examples) can be merged with the IDM.
  3. Documentation Generation: The Documentation Generation Engine takes the IDM and applies the selected template.

* Renders API endpoints, models, security, and examples.

* Generates interactive elements for HTML output.

  1. Output Delivery: The generated documentation (e.g., HTML files, Markdown files, PDF) is saved to the specified output directory or presented for download.
  2. SDK Generation (Optional): If requested, the SDK Generation Module uses the IDM to produce client library source code.

4. Technology Stack Recommendations

  • Primary Programming Language: Python or TypeScript/Node.js. Both offer strong ecosystems for parsing, data manipulation, and web development.

* Python Advantages: Mature libraries for YAML/JSON parsing, strong community, good for CLI tools.

* TypeScript/Node.js Advantages: Excellent for web UIs, strong for JSON schema validation, good for performance in I/O operations.

  • Input Parsing:

* OpenAPI: openapi-parser (JS), py-openapi (Python), js-yaml/PyYAML.

* Postman: Custom parser leveraging JSON schema validation.

* RAML: raml-parser (JS), pyraml (Python).

  • Intermediate Data Model: Plain Old Python Objects (POPOs) or TypeScript Interfaces/Classes.
  • Templating Engine:

* Python: Jinja2 (powerful, widely used).

* TypeScript/Node.js: Handlebars.js, Nunjucks (Jinja2-like).

  • Static Site Generation (for HTML output):

* MkDocs (Python): Excellent for Markdown-based documentation, highly customizable themes.

* Docusaurus (JS/React): Feature-rich, modern documentation site generator.

* Next.js / Gatsby (JS/React): For highly customized and interactive documentation portals.

  • CLI Framework:

* Python: Click, Argparse.

* TypeScript/Node.js: Commander.js, Yargs.

  • SDK Generation (if applicable): OpenAPI Generator (can be integrated or used as a reference for custom generation logic).
  • Web UI (if applicable): React.js/Vue.js (Frontend) with Flask/FastAPI (Python) or Express.js/NestJS (Node.js) (Backend).

5. Key Architectural Considerations

  • Extensibility:

* Plugin Architecture: Allow users to write custom parsers, transformers, or renderers.

* Template Customization: Provide clear guidelines and examples for users to create their own documentation templates.

  • Performance:

* Efficient parsing and data processing, especially for large API definitions.

* Optimized rendering for static site generation.

  • Scalability (for Web UI/Hosted Service):

* Stateless processing of documentation generation requests.

* Containerization (Docker) for easy deployment and scaling.

  • Maintainability:

* Clear code structure, comprehensive unit tests, and integration tests.

* Well-documented internal APIs and development guides.

  • User Experience (Developer Experience - DX):

* Clear error messages during parsing and validation.

* Intuitive CLI commands and configuration options.

* High-quality default templates.

  • Security (for Web UI/Hosted Service):

* Input sanitization to prevent injection attacks.

* Secure handling of API keys or credentials if passed through the system.

* Access control for generated documentation.

  • Versioning:

* Support for multiple API versions within a single documentation set.

* Versioning of the documentation generator itself.


6. High-Level Milestones / Phased Approach

Phase 1: Core Generator (MVP)

  • Define Intermediate Data Model (IDM).
  • Develop OpenAPI 3.x Parser & Validator.
  • Implement basic Documentation Generation Engine with a default static HTML template.
  • Develop a robust CLI for basic configuration (input, output, format).
  • Establish CI/CD for automated testing and deployment.

Phase 2: Input & Output Expansion

  • Add Postman Collection Parser.
  • Add Markdown output formatter.
  • Enhance existing HTML template with interactive features (search, navigation).
  • Allow for custom template selection via CLI.

Phase 3: Advanced Features & Refinement

  • Add RAML Parser.
  • Implement PDF output formatter.
  • Integrate SDK Generation Module (e.g., Python, JavaScript).
  • Develop a basic Web-based UI for guided generation.
  • Introduce custom content injection (e.g., adding custom intro/outro Markdown).

Phase 4: Ecosystem & Extensibility

  • Develop a plugin system for custom parsers/renderers.
  • Integrate with popular static site generators (e.g., MkDocs, Docusaurus) as rendering targets.
  • Refine Web UI with project management and user accounts (if hosted).

7. Future Enhancements

  • API Mocking Server Generation: Generate a basic mock server based on the API definition for testing purposes.
  • Interactive API Console: Allow users to make live API calls directly from the generated HTML documentation.
  • Version Control Integration: Automatically pull API definitions from Git repositories.
  • Webhook Support: Trigger documentation generation on API definition changes.
  • Localization: Support for generating documentation in multiple languages.
  • Accessibility Features: Ensure generated documentation adheres to WCAG guidelines.
  • Advanced Analytics: Track usage of generated documentation (if hosted).

This architecture plan provides a solid foundation for developing a powerful and flexible API Documentation Generator, meeting the requirements for professional, detailed, and actionable output.

gemini Output

The following output provides a comprehensive, detailed, and professional code generation solution for an API Documentation Generator. This deliverable focuses on a Python script that takes an OpenAPI/Swagger specification (JSON or YAML) and generates a structured Markdown documentation file, including endpoint descriptions, request/response examples, authentication guides, and SDK-like usage examples.


API Documentation Generator: Code Generation (Step 2 of 3)

This step delivers a robust, well-commented Python script designed to automate the generation of professional API documentation from an OpenAPI (formerly Swagger) specification. The script produces a Markdown file that can be easily converted to HTML, PDF, or integrated into static site generators for a polished documentation portal.

1. Introduction to the Solution

The core of this solution is a Python script that parses an OpenAPI specification file (either JSON or YAML format) and transforms its contents into a human-readable Markdown document. This approach offers flexibility, version control friendliness, and ease of integration into CI/CD pipelines.

Key Features:

  • Automatic Parsing: Reads OpenAPI 3.x specifications.
  • Structured Output: Generates clear sections for overview, authentication, and individual endpoints.
  • Endpoint Details: Includes method, path, summary, description, parameters (path, query, header, cookie), request bodies, and responses.
  • Schema & Example Integration: Displays request and response schemas, along with example payloads where available.
  • Authentication Guide: Outlines defined security schemes and how to use them.
  • SDK Usage Examples: Provides generic, language-agnostic HTTP request examples (using Python's requests library as a demonstration) for each endpoint, mimicking SDK usage.

2. Core Python Script: openapi_to_markdown.py

This script is designed to be run from your command line, taking the path to your OpenAPI specification file as an argument.


# openapi_to_markdown.py

import json
import yaml
import os
from collections import OrderedDict

# --- Configuration ---
OUTPUT_DIR = "generated_docs"
OUTPUT_FILENAME = "API_Documentation.md"
DEFAULT_INDENT = 4 # for JSON examples

# --- Helper Functions ---
def load_openapi_spec(file_path):
    """Loads an OpenAPI specification from a JSON or YAML file."""
    if not os.path.exists(file_path):
        raise FileNotFoundError(f"OpenAPI spec file not found: {file_path}")

    with open(file_path, 'r', encoding='utf-8') as f:
        if file_path.lower().endswith(('.yaml', '.yml')):
            return yaml.safe_load(f)
        elif file_path.lower().endswith('.json'):
            return json.load(f)
        else:
            raise ValueError("Unsupported file format. Please provide a .json, .yaml, or .yml file.")

def format_json_pretty(data):
    """Formats a dictionary as a pretty-printed JSON string."""
    return json.dumps(data, indent=DEFAULT_INDENT)

def generate_sdk_example(method, path, parameters, request_body, security_schemes):
    """Generates a generic SDK-like usage example using Python requests."""
    example_lines = []
    example_lines.append(f"```python")
    example_lines.append(f"import requests")
    example_lines.append(f"import json")
    example_lines.append(f"")
    example_lines.append(f"# Base URL for the API")
    example_lines.append(f"BASE_URL = 'https://api.example.com/v1'") # TODO: Replace with actual base URL from spec if available

    # Handle authentication
    auth_headers = {}
    if security_schemes:
        example_lines.append(f"# Authentication (adjust as per your API's security scheme)")
        for scheme_name, scheme_def in security_schemes.items():
            if scheme_def.get('type') == 'apiKey':
                if scheme_def.get('in') == 'header':
                    auth_headers[scheme_def.get('name', 'X-API-Key')] = f'YOUR_{scheme_def.get("name", "API_KEY").upper()}'
                    example_lines.append(f'{scheme_def.get("name", "API_KEY").upper()} = "YOUR_{scheme_def.get("name", "API_KEY").upper()}"')
                    example_lines.append(f'headers = {{"{scheme_def.get("name", "X-API-Key")}": {scheme_def.get("name", "API_KEY").upper()}}}')
                elif scheme_def.get('in') == 'query':
                    example_lines.append(f'{scheme_def.get("name", "API_KEY").upper()} = "YOUR_{scheme_def.get("name", "API_KEY").upper()}"')
                    example_lines.append(f'params = {{"{scheme_def.get("name", "api_key")}": {scheme_def.get("name", "API_KEY").upper()}}}')
            elif scheme_def.get('type') == 'http' and scheme_def.get('scheme') == 'bearer':
                example_lines.append(f'ACCESS_TOKEN = "YOUR_BEARER_TOKEN"')
                example_lines.append(f'headers = {{"Authorization": f"Bearer {{ACCESS_TOKEN}}"}}')
            # Add more auth types (OAuth2, OpenID Connect) as needed
        example_lines.append("")

    # Construct URL with path parameters
    path_params = {}
    query_params = {}
    header_params = {}

    path_formatted = path
    for param in parameters:
        if param.get('in') == 'path':
            param_name = param['name']
            path_formatted = path_formatted.replace(f'{{{param_name}}}', f'{{path_params["{param_name}"]}}')
            path_params[param_name] = f'"{param_name}_value"' # Placeholder
        elif param.get('in') == 'query':
            query_params[param['name']] = f'"{param["name"]}_value"' # Placeholder
        elif param.get('in') == 'header':
            header_params[param['name']] = f'"{param["name"]}_value"' # Placeholder

    if path_params:
        example_lines.append(f'path_params = {json.dumps(path_params, indent=DEFAULT_INDENT)}')
        example_lines.append(f'endpoint_path = f"{path_formatted}"')
    else:
        example_lines.append(f'endpoint_path = "{path_formatted}"')

    example_lines.append(f'url = f"{{BASE_URL}}{{endpoint_path}}"')
    example_lines.append("")

    # Handle query parameters
    if query_params:
        example_lines.append(f'query_params = {json.dumps(query_params, indent=DEFAULT_INDENT)}')
        example_lines.append(f'# Combine existing headers and query params if any from authentication')
        example_lines.append(f'params = {{**locals().get("params", {{}}), **query_params}}') # Merge with auth params
    else:
        example_lines.append(f'params = locals().get("params", {{}})') # Use auth params if any

    # Handle header parameters
    if header_params:
        example_lines.append(f'custom_headers = {json.dumps(header_params, indent=DEFAULT_INDENT)}')
        example_lines.append(f'# Combine existing headers from authentication with custom headers')
        example_lines.append(f'headers = {{**locals().get("headers", {{}}), **custom_headers}}') # Merge with auth headers
    else:
        example_lines.append(f'headers = locals().get("headers", {{}})') # Use auth headers if any

    # Handle request body
    request_data = None
    if request_body:
        content_type = next(iter(request_body.get('content', {})), 'application/json')
        schema_ref = request_body.get('content', {}).get(content_type, {}).get('schema', {})
        
        # Try to get an example from the schema
        if '$ref' in schema_ref:
            # This would require resolving the $ref, which is complex.
            # For simplicity, we'll use a generic placeholder or direct example if available.
            pass
        
        # Prioritize direct examples if present
        example = request_body.get('content', {}).get(content_type, {}).get('example')
        if example:
            request_data = example
        elif schema_ref and 'properties' in schema_ref:
            # Basic example generation from properties
            request_data = {prop: f"<{schema_ref['properties'][prop].get('type', 'string')}>" 
                            for prop in schema_ref['properties']}
        
        if request_data:
            example_lines.append(f'payload = {format_json_pretty(request_data)}')
            if 'json' in content_type:
                example_lines.append(f'data = json.dumps(payload)')
                example_lines.append(f'headers["Content-Type"] = "{content_type}"')
            else: # For other types like x-www-form-urlencoded
                example_lines.append(f'data = payload') # Or urlencode for form data
            example_lines.append("")

    # Make the request
    example_lines.append(f'try:')
    request_params = []
    if request_data:
        request_params.append('data=data')
    if headers:
        request_params.append('headers=headers')
    if params: # query params
        request_params.append('params=params')

    request_call = f'response = requests.{method.lower()}(url, {", ".join(request_params)})'
    example_lines.append(f'    {request_call}')
    example_lines.append(f'    response.raise_for_status() # Raise an exception for HTTP errors (4xx or 5xx)')
    example_lines.append(f'    print(f"Status Code: {{response.status_code}}")')
    example_lines.append(f'    print(f"Response Body: {{response.json()}}")')
    example_lines.append(f'except requests.exceptions.HTTPError as err:')
    example_lines.append(f'    print(f"HTTP Error: {{err}}")')
    example_lines.append(f'    print(f"Response Body: {{err.response.text}}")')
    example_lines.append(f'except requests.exceptions.RequestException as err:')
    example_lines.append(f'    print(f"Request Error: {{err}}")')
    example_lines.append(f'```')
    return "\n".join(example_lines)

# --- Main Generator Class ---
class OpenApiToMarkdownGenerator:
    def __init__(self, spec):
        self.spec = spec
        self.output = []
        self.security_schemes = self.spec.get('components', {}).get('securitySchemes', {})

    def _write(self, content):
        """Appends content to the output buffer."""
        self.output.append(content)

    def _get_schema_details(self, schema_ref):
        """Resolves a schema reference and returns its details."""
        if '$ref' in schema_ref:
            ref_path = schema_ref['$ref'].lstrip('#/')
            parts = ref_path.split('/')
            
            # Navigate the spec to find the referenced schema
            current = self.spec
            for part in parts:
                if part in current:
                    current = current[part]
                else:
                    return {"description": f"Could not resolve reference: {schema_ref['$ref']}"}
            return current
        return schema_ref

    def generate_header(self):
        """Generates the main documentation header and overview."""
        info = self.spec.get('info', {})
        self._write(f"# {info.get('title', 'API Documentation')}")
        self._write(f"")
        self._write(f"Version: {info.get('version', '1.0.0')}")
        self._write(f"")
        if info.get('description'):
            self._write(info['description'])
            self._write(f"")

        servers = self.spec.get('servers', [])
        if servers:
            self._write("## Base URLs")
            for server in servers:
                self._write(f"- `{server.get('url')}` - {server.get('description', 'Default server')}")
            self._write(f"")

    def generate_authentication_section(self):
        """Generates the authentication guide."""
        if not self.security_schemes:
            return

        self._write("## Authentication")
        self._write("This API uses the following authentication methods:")
        self._write("")

        for scheme_name, scheme_def in self.security_schemes.items():
            self._write(f"### {scheme_name}")
            self._write(f"**Type:** `{scheme_def.get('type')}`")
            if scheme_def.get('scheme'):
                self._write(f"**Scheme:** `{scheme_def.get('scheme')}`")
            if scheme_def.get('bearerFormat'):
                self._write(f"**Bearer Format:** `{scheme_def.get('bearerFormat')}`")
            if scheme_def.get('name') and scheme_def.get('in'):
                self._write(f"**Parameter:** `{scheme_def.get
gemini Output

As a professional AI assistant within PantheraHive, I have generated comprehensive and detailed API documentation based on your request. This document provides a clear and actionable guide for integrating with the hypothetical "PantheraHive Project Management API," covering essential aspects from authentication to specific endpoint usage and SDK examples.


PantheraHive Project Management API Documentation

Welcome to the PantheraHive Project Management API documentation. This API allows you to programmatically manage projects, tasks, and users within the PantheraHive ecosystem. With this API, you can integrate your applications, automate workflows, and extend the functionality of PantheraHive to suit your specific needs.

1. Introduction

The PantheraHive Project Management API is a RESTful API that enables developers to interact with project management resources such as projects, tasks, and users. All API requests and responses are formatted as JSON, and standard HTTP methods are used for resource manipulation.

Key Features:

  • Project Management: Create, read, update, and delete projects.
  • Task Management: Manage tasks associated with projects, including creation, retrieval, and status updates.
  • User Assignment: Assign users to projects and tasks.

2. Base URL

All API requests should be made to the following base URL:

https://api.pantherahive.com/v1

3. Authentication

The PantheraHive Project Management API uses API Key authentication. To authenticate your requests, you must include your API Key in the Authorization header of every request.

How to obtain your API Key:

  1. Log in to your PantheraHive account.
  2. Navigate to "Settings" -> "API Keys".
  3. Generate a new API Key if you don't have one, or use an existing one.
  4. Keep your API Key secure and do not share it publicly.

Authentication Header Example:


Authorization: Bearer YOUR_API_KEY

Replace YOUR_API_KEY with the actual API Key obtained from your PantheraHive account.

Example Request with Authentication:


curl -X GET \
  https://api.pantherahive.com/v1/projects \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json'

4. Error Handling

The API uses standard HTTP status codes to indicate the success or failure of an API request. In case of an error, the API will return a JSON object with details about the error.

Common HTTP Status Codes:

  • 200 OK: The request was successful.
  • 201 Created: The resource was successfully created.
  • 204 No Content: The request was successful, but there is no content to return (e.g., DELETE request).
  • 400 Bad Request: The request was malformed or invalid.
  • 401 Unauthorized: Authentication failed or was not provided.
  • 403 Forbidden: The authenticated user does not have permission to access the resource.
  • 404 Not Found: The requested resource could not be found.
  • 405 Method Not Allowed: The HTTP method used is not supported for this endpoint.
  • 429 Too Many Requests: Rate limit exceeded.
  • 500 Internal Server Error: An unexpected error occurred on the server.

Error Response Example:


{
  "code": "resource_not_found",
  "message": "Project with ID 'proj_xyz' not found.",
  "details": {
    "resource_type": "project",
    "resource_id": "proj_xyz"
  }
}

5. Rate Limiting

To ensure fair usage and system stability, the PantheraHive API enforces rate limits.

Currently, the limit is 100 requests per minute per API Key.

If you exceed the rate limit, you will receive a 429 Too Many Requests status code. The response will include Retry-After header indicating how long you should wait before making another request.

Rate Limit Headers:

  • X-RateLimit-Limit: The maximum number of requests you can make in the current window.
  • X-RateLimit-Remaining: The number of requests remaining in the current window.
  • X-RateLimit-Reset: The time at which the current rate limit window resets, in UTC epoch seconds.

6. Endpoints

This section details the available API endpoints, their methods, parameters, and example requests/responses.


6.1. Projects

##### 6.1.1. List All Projects

Retrieves a list of all projects accessible by the authenticated user.

  • GET /projects

Parameters:

  • Query Parameters:

* status (optional, string): Filter projects by status (e.g., active, completed, archived).

* limit (optional, integer): Maximum number of projects to return (default: 20, max: 100).

* offset (optional, integer): Number of projects to skip for pagination.

Request Example:


curl -X GET \
  'https://api.pantherahive.com/v1/projects?status=active&limit=10' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json'

Successful Response (200 OK):


{
  "data": [
    {
      "id": "proj_abc123",
      "name": "Website Redesign",
      "description": "Redesign the company's main website for improved UX.",
      "status": "active",
      "startDate": "2023-01-15",
      "endDate": "2023-06-30",
      "ownerId": "user_xyz789",
      "createdAt": "2023-01-10T10:00:00Z",
      "updatedAt": "2023-03-20T14:30:00Z"
    },
    {
      "id": "proj_def456",
      "name": "Mobile App Development",
      "description": "Develop a new mobile application for iOS and Android.",
      "status": "active",
      "startDate": "2023-02-01",
      "endDate": null,
      "ownerId": "user_abc111",
      "createdAt": "2023-01-25T11:00:00Z",
      "updatedAt": "2023-05-01T09:15:00Z"
    }
  ],
  "total": 2,
  "limit": 10,
  "offset": 0
}

##### 6.1.2. Get Project by ID

Retrieves details for a specific project.

  • GET /projects/{projectId}

Parameters:

  • Path Parameters:

* projectId (required, string): The unique identifier of the project.

Request Example:


curl -X GET \
  https://api.pantherahive.com/v1/projects/proj_abc123 \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json'

Successful Response (200 OK):


{
  "id": "proj_abc123",
  "name": "Website Redesign",
  "description": "Redesign the company's main website for improved UX.",
  "status": "active",
  "startDate": "2023-01-15",
  "endDate": "2023-06-30",
  "ownerId": "user_xyz789",
  "createdAt": "2023-01-10T10:00:00Z",
  "updatedAt": "2023-03-20T14:30:00Z"
}

Error Response (404 Not Found):


{
  "code": "resource_not_found",
  "message": "Project with ID 'proj_nonexistent' not found.",
  "details": {
    "resource_type": "project",
    "resource_id": "proj_nonexistent"
  }
}

##### 6.1.3. Create a New Project

Creates a new project with the provided details.

  • POST /projects

Parameters:

  • Request Body (JSON):

* name (required, string): The name of the project.

* description (optional, string): A brief description of the project.

* status (optional, string): Initial status of the project (default: active).

* startDate (optional, date string): The planned start date for the project (YYYY-MM-DD).

* endDate (optional, date string): The planned end date for the project (YYYY-MM-DD).

* ownerId (required, string): The ID of the user who owns the project.

Request Example:


curl -X POST \
  https://api.pantherahive.com/v1/projects \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
        "name": "New Marketing Campaign",
        "description": "Launch a new digital marketing campaign for product X.",
        "status": "active",
        "startDate": "2024-07-01",
        "ownerId": "user_abc111"
      }'

Successful Response (201 Created):


{
  "id": "proj_ghi789",
  "name": "New Marketing Campaign",
  "description": "Launch a new digital marketing campaign for product X.",
  "status": "active",
  "startDate": "2024-07-01",
  "endDate": null,
  "ownerId": "user_abc111",
  "createdAt": "2024-06-25T15:00:00Z",
  "updatedAt": "2024-06-25T15:00:00Z"
}

##### 6.1.4. Update a Project

Updates an existing project's details. Only the fields provided in the request body will be updated.

  • PUT /projects/{projectId}

Parameters:

  • Path Parameters:

* projectId (required, string): The unique identifier of the project to update.

  • Request Body (JSON):

* name (optional, string): The new name of the project.

* description (optional, string): The new description of the project.

* status (optional, string): The new status of the project (e.g., completed).

* endDate (optional, date string): The new planned end date for the project (YYYY-MM-DD).

* ownerId (optional, string): The ID of the new project owner.

Request Example:


curl -X PUT \
  https://api.pantherahive.com/v1/projects/proj_abc123 \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
        "status": "completed",
        "endDate": "2023-06-28"
      }'

Successful Response (200 OK):


{
  "id": "proj_abc123",
  "name": "Website Redesign",
  "description": "Redesign the company's main website for improved UX.",
  "status": "completed",
  "startDate": "2023-01-15",
  "endDate": "2023-06-28",
  "ownerId": "user_xyz789",
  "createdAt": "2023-01-10T10:00:00Z",
  "updatedAt": "2024-06-25T16:00:00Z"
}

##### 6.1.5. Delete a Project

Deletes a project permanently. This action cannot be undone.

  • DELETE /projects/{projectId}

Parameters:

  • Path Parameters:

* projectId (required, string): The unique identifier of the project to delete.

Request Example:


curl -X DELETE \
  https://api.pantherahive.com/v1/projects/proj_def456 \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json'

Successful Response (204 No Content):

No response body is returned for successful DELETE requests.


6.2. Tasks

##### 6.2.1. List Tasks for a Project

Retrieves a list of tasks associated with a specific project.

  • GET /projects/{projectId}/tasks

Parameters:

  • Path Parameters:

* projectId (required, string): The unique identifier of the project.

  • Query Parameters:

* status (optional, string): Filter tasks by status (e.g., pending, in_progress, completed).

* assignedTo (optional, string): Filter tasks by the ID of the assigned user.

Request Example:


curl -X GET \
  'https://api.pantherahive.com/v1/projects/proj_abc123/tasks?status=pending' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json'

Successful Response (200 OK):


{
  "data": [
    {
      "id": "task_111aaa",
      "projectId": "proj_abc123",
      "name": "Design homepage mockups",
      "description": "Create initial mockups for the new website homepage.",
      "status": "pending",
      "dueDate": "2023-02-10",
      "assignedToId": "user_xyz789",
      "priority": "high",
      "createdAt": "2023-01-20T09:00:00Z",
      "updatedAt": "2023-01-20T09:00:00Z"
    },
    {
      "id": "task_222bbb",
      "projectId": "proj_abc123",
      "name": "Write content for 'About Us' page",

api_documentation_generator.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);}});}