API Rate Limiter
Run ID: 69ccbe8f3e7fb09ff16a4afe2026-04-01Development
PantheraHive BOS
BOS Dashboard

API Rate Limiter Architecture Plan

This document outlines a detailed architecture plan for a robust, scalable, and highly available API Rate Limiter. It covers the core components, design considerations, recommended technologies, and a phased implementation roadmap, including learning objectives and milestones.


1. Introduction to API Rate Limiting

An API Rate Limiter is a critical component in modern microservices architectures, designed to control the rate at which clients or users can send requests to an API. Its primary purposes include:

  • Preventing Abuse & DoS Attacks: Safeguarding backend services from malicious or accidental overload.
  • Resource Management: Ensuring fair usage of shared resources and preventing any single client from monopolizing the system.
  • Cost Control: Managing infrastructure costs by limiting excessive requests that consume computing resources.
  • Traffic Shaping: Smoothing out traffic spikes and ensuring consistent service availability.
  • Monetization: Implementing tiered access levels for different service plans.

This architectural plan focuses on building a distributed rate limiting solution that is highly performant, resilient, and configurable.

2. Core Requirements

To ensure a comprehensive and effective solution, the API Rate Limiter must meet the following functional and non-functional requirements:

2.1. Functional Requirements

  • Request Limiting: Ability to limit requests based on various identifiers (IP address, user ID, API key, JWT claims, client ID).
  • Granular Control: Support for limiting requests per endpoint, per method, or globally.
  • Algorithm Support: Implement support for multiple rate limiting algorithms (e.g., Sliding Window Counter, Token Bucket).
  • Configurable Rules: Allow dynamic configuration of rate limits (e.g., 100 requests per minute, 5 requests per second).
  • Over-Limit Handling: Reject requests exceeding limits with a standard HTTP 429 (Too Many Requests) status code and appropriate Retry-After headers.
  • Burst Tolerance: Allow for short bursts of traffic within defined limits (e.g., using Token Bucket).
  • Distributed Enforcement: Enforce limits consistently across multiple instances of the API Gateway and rate limiting service.
  • Quota Management: Potentially integrate with a quota system for long-term usage tracking (future consideration).

2.2. Non-functional Requirements

  • Performance:

* Low Latency: Minimal overhead added to each API request (target: <5ms).

* High Throughput: Capable of handling millions of rate limit checks per second.

  • Scalability: Horizontally scalable to handle increasing API traffic and a growing number of rate limiting rules.
  • High Availability & Fault Tolerance: Resilient to failures of individual components (e.g., rate limiting service instances, data store).
  • Configurability: Dynamic updates to rate limiting rules without requiring service restarts.
  • Observability: Comprehensive metrics, logging, and tracing for monitoring the rate limiter's health and effectiveness.
  • Security: Protection against bypass attempts and manipulation of rate limiting mechanisms.
  • Durability: Persistence of rate limit counters and states (e.g., for Token Bucket) across restarts.

3. High-Level Architecture Overview

The API Rate Limiter will be implemented as a dedicated microservice, integrated with the existing API Gateway. This separation of concerns allows for independent scaling and management.


+----------------+       +-------------------+       +-----------------------+       +-------------------+
|                |       |                   |       |                       |       |                   |
|  Client (User) |------>|  API Gateway      |------>|  Rate Limiting Service|------>|  Data Store (Redis)|
|                |       | (e.g., Nginx, Kong)|       | (e.g., Go/Java MicroS)|       | (e.g., Redis Cluster)|
+----------------+       |                   |       |                       |       |                   |
                         |  (Plugin/Filter)  |<------| (Check Limit, Update) |<------| (Counters, State) |
                         +-------------------+       +-----------------------+       +-------------------+
                                   |                               |
                                   |  
gemini Output

This document provides a comprehensive, production-ready implementation of an API Rate Limiter using the Sliding Window Counter algorithm and Redis for distributed state management. This solution is designed to be robust, scalable, and directly applicable to your API infrastructure, ensuring fair usage, protecting resources, and preventing abuse.


API Rate Limiter: Code Generation & Implementation Guide

1. Introduction to API Rate Limiting

An API Rate Limiter is a critical component in modern web services, designed to control the rate at which users or services can access an API. Its importance stems from several key aspects:

  • Preventing Abuse: Protects against malicious activities such as Distributed Denial of Service (DDoS) attacks, brute-force login attempts, and excessive scraping.
gemini Output

API Rate Limiter: Comprehensive Overview and Implementation Guide

This document provides a detailed professional overview of API Rate Limiting, covering its purpose, benefits, common strategies, implementation considerations, and best practices. This deliverable is designed to equip you with the knowledge necessary to effectively design, implement, and manage API rate limiting for your services.


1. Introduction to API Rate Limiting

An API Rate Limiter is a mechanism that controls the number of requests an API client can make to a server within a defined time window. It acts as a gatekeeper, preventing clients from overwhelming the API with excessive requests. This is a critical component for maintaining API stability, fairness, and security.

2. Why Implement an API Rate Limiter?

Implementing an API Rate Limiter offers significant benefits for both API providers and consumers:

  • For API Providers:

* Resource Protection: Prevents API servers from being overloaded by a surge of requests, ensuring stability and availability for all users.

* Cost Management: Reduces infrastructure costs associated with handling excessive traffic, especially in cloud-based environments where scaling is dynamic.

* Security & Abuse Prevention: Mitigates various forms of abuse, such as Denial-of-Service (DoS) attacks, brute-force attacks on login endpoints, and data scraping.

* Fair Usage: Ensures that no single client or group of clients monopolizes server resources, providing a fair experience for all legitimate users.

* Service Level Agreement (SLA) Compliance: Helps maintain performance metrics and uptime guarantees by preventing resource exhaustion.

  • For API Consumers:

* Predictable Performance: Ensures the API remains responsive and reliable, even under high load, leading to a better user experience.

* Clear Usage Policies: Provides clear guidelines on how the API should be used, helping developers build more robust and compliant applications.

* Error Prevention: By returning clear 429 Too Many Requests responses, clients can adapt their request patterns instead of encountering server errors or timeouts.

3. Key Concepts & Terminology

  • Rate Limit: The maximum number of requests allowed within a specific time window (e.g., 100 requests per minute).
  • Quota: A broader limit, often referring to a total number of requests allowed over a longer period (e.g., 10,000 requests per day) or for specific resources.
  • Throttling: The process of intentionally slowing down or regulating the flow of requests. Rate limiting is a form of throttling.
  • Backoff Strategy: A client-side mechanism where an application waits for a progressively longer period before retrying a failed or rate-limited request.
  • Burst Limit: Allows a client to exceed the regular rate limit for a short period, up to a certain maximum, to handle temporary spikes in demand.
  • Identification Key: The unique identifier used to track requests for a specific client (e.g., IP address, API key, user ID, client ID, JWT token).

4. Common Rate Limiting Algorithms/Strategies

Different algorithms offer various trade-offs in terms of complexity, fairness, and performance.

4.1. Fixed Window Counter

  • How it works: A fixed time window (e.g., 60 seconds) is defined. A counter for each client is reset at the beginning of each window. Requests increment the counter until the limit is reached.
  • Pros: Simple to implement, low overhead.
  • Cons:

* Burst Problem: Clients can make a large number of requests at the very end of one window and then immediately at the beginning of the next, effectively doubling the rate limit for a short period.

* Doesn't handle "rollover" traffic gracefully.

4.2. Sliding Window Log

  • How it works: For each client, the timestamps of all requests are stored. When a new request arrives, the system counts how many timestamps fall within the current window (e.g., the last 60 seconds). Old timestamps are discarded.
  • Pros: Very accurate and fair, as it considers the actual request times.
  • Cons:

* High Memory Usage: Requires storing a timestamp for every request, which can be memory-intensive for high-volume APIs.

* Computationally more expensive due to list manipulation and counting.

4.3. Sliding Window Counter

  • How it works: A hybrid approach using two fixed windows: the current window and the previous window. When a request comes in, it calculates the allowed requests based on a weighted average of the previous window's usage and the current window's usage.

requests_in_current_window + (requests_in_previous_window overlap_percentage)

  • Pros: Addresses the burst problem of the Fixed Window Counter and is more memory-efficient than Sliding Window Log.
  • Cons: Not perfectly accurate, as it's an approximation, but generally good enough for most use cases.

4.4. Leaky Bucket

  • How it works: Analogous to a bucket with a hole at the bottom. Requests are added to the bucket (queue). Requests leak out of the bucket at a constant rate. If the bucket overflows (queue is full), new requests are dropped.
  • Pros: Smooths out bursts of requests into a steady flow, preventing server overload.
  • Cons:

* A sudden burst of requests might be delayed or dropped, even if the average rate is within limits.

* All requests are processed at a fixed rate, which might not be ideal for varied request types.

4.5. Token Bucket

  • How it works: Tokens are added to a bucket at a fixed rate. Each request consumes one token. If a request arrives and there are tokens in the bucket, it consumes a token and proceeds. If the bucket is empty, the request is dropped or queued. The bucket has a maximum capacity.
  • Pros:

* Allows for bursts of requests up to the bucket capacity (number of tokens).

* Simple to implement and efficient.

* Flexible: allows setting both a sustained rate (token generation rate) and a burst rate (bucket capacity).

  • Cons: If the bucket capacity is too small, it might still drop legitimate burst traffic.

5. Implementation Considerations

5.1. Scope of Rate Limiting

  • Global: Applies to all requests across the entire API.
  • Per User/API Key: Limits individual users or applications. Most common and recommended.
  • Per IP Address: Limits requests from a single IP. Useful for unauthenticated access but can be problematic for users behind NATs or proxies.
  • Per Endpoint: Different limits for different API endpoints (e.g., POST /login might have a stricter limit than GET /products).
  • Per Resource: Limiting access to specific resources within an endpoint (e.g., a user can only update their own profile a certain number of times).

5.2. Enforcement Point

  • API Gateway/Load Balancer: Ideal for centralized control, offloading rate limiting logic from individual services. Examples: NGINX, Envoy, AWS API Gateway, Azure API Management.
  • Microservice/Application Level: Implemented within the application code. Provides fine-grained control but adds complexity to each service. Often used in conjunction with a gateway for specific business logic limits.
  • Sidecar Proxy: In a microservices architecture, a sidecar proxy (e.g., Istio) can handle rate limiting for a service without modifying the service code.

5.3. Identification of Clients

Robust client identification is crucial for accurate rate limiting. Common methods include:

  • API Key: A unique key provided by the client.
  • OAuth Token/JWT: Authenticated user or application identifier.
  • IP Address: Source IP of the request. Be mindful of proxies and load balancers (use X-Forwarded-For or similar headers).
  • User ID/Client ID: After authentication, use the internal user or client identifier.

5.4. Error Handling and Response

When a client exceeds the rate limit, the API should respond with:

  • HTTP Status Code 429 Too Many Requests: This standard status code indicates rate limiting.
  • Retry-After Header: Specifies how long the client should wait before making another request (either a date-time or a number of seconds). This is crucial for clients to implement proper backoff strategies.
  • Informative Response Body: A JSON or XML body explaining the error and potentially providing details about the current limit.

5.5. Headers for Transparency

It's good practice to include rate limit-related headers in all API responses, not just 429 errors, to inform clients of their current status:

  • X-RateLimit-Limit: The maximum number of requests allowed in the current window.
  • X-RateLimit-Remaining: The number of requests remaining in the current window.
  • X-RateLimit-Reset: The time (in UTC epoch seconds or date-time) when the current rate limit window resets.

6. Best Practices for API Rate Limiting

  1. Start with Sensible Defaults: Begin with reasonable rate limits based on expected usage and resource capacity. Adjust as you gather data.
  2. Granular Control: Implement different rate limits for different types of users (e.g., free tier vs. premium tier) and different endpoints (e.g., read vs. write operations).
  3. Clear Documentation: Explicitly document your rate limits, the headers you use, and recommended client-side backoff strategies.
  4. Client-Side Backoff: Encourage and provide guidance for clients to implement exponential backoff with jitter to avoid stampeding the API after a rate limit.
  5. Distributed Rate Limiting: For microservices architectures, use a centralized rate limiting service (e.g., Redis, dedicated rate limiting service) to ensure consistent limits across all instances and services.
  6. Edge-Based Enforcement: Whenever possible, enforce rate limits at the edge (API Gateway, CDN) to protect your backend services from unnecessary load.
  7. Monitor and Alert: Track rate limit hits, blocked requests, and overall API usage. Set up alerts for unusual patterns or sustained high rate limit violations.
  8. Graceful Degradation: Consider allowing critical requests to pass even if general limits are exceeded, or temporarily increasing limits during peak times.
  9. Allowlist Trusted Clients: For internal services or trusted partners, consider allowing them to bypass or have significantly higher rate limits.
  10. Test Thoroughly: Simulate various load scenarios, including abusive patterns, to ensure your rate limiter behaves as expected.

7. Choosing the Right Rate Limiting Strategy

The optimal strategy depends on your specific requirements:

  • Simplicity & Low Overhead: Fixed Window Counter (if burst problems are acceptable or mitigated elsewhere).
  • High Accuracy & Fairness (but high memory): Sliding Window Log (for critical APIs where precision is paramount).
  • Good Balance of Accuracy & Efficiency: Sliding Window Counter (a strong general-purpose choice).
  • Smoothing Bursts into Constant Flow: Leaky Bucket (for scenarios where consistent processing rate is key).
  • Allowing Controlled Bursts: Token Bucket (highly recommended for most modern APIs due to its flexibility and performance).

For most production-grade APIs, a combination of Token Bucket or Sliding Window Counter implemented at an API Gateway level, with more specific limits handled at the application level where needed, provides a robust solution.

8. Monitoring and Alerting

Effective monitoring is crucial for understanding the impact and effectiveness of your rate limiting strategy.

  • Metrics to Track:

* Total requests processed.

* Number of requests blocked by rate limits (429 responses).

* Percentage of requests blocked by rate limits.

* Rate limit usage per client/API key.

* Latency of rate limiting checks.

  • Alerting:

* Set up alerts for sudden spikes in 429 responses, indicating potential attacks or misbehaving clients.

* Alert on sustained high rate limit usage for specific clients, which might indicate a need to adjust their limits or reach out to them.

* Monitor the health and performance of your rate limiting infrastructure itself.

9. Conclusion

API Rate Limiting is an indispensable part of building robust, scalable, and secure APIs. By carefully selecting an appropriate algorithm, considering implementation details, and adhering to best practices, you can protect your services, manage resources effectively, and provide a reliable experience for your API consumers.

We recommend reviewing your current API usage patterns and future growth projections to tailor the most effective rate limiting strategy for your specific needs. Please reach out to our team if you require further assistance in designing or implementing your API Rate Limiter.

api_rate_limiter.md
Download as Markdown
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
"); 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' import ReactDOM from 'react-dom/client' import App from './App' import './index.css' ReactDOM.createRoot(document.getElementById('root')!).render( ) "); 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' import './App.css' function App(){ return(

"+slugTitle(pn)+"

Built with PantheraHive BOS

) } export default App "); zip.file(folder+"src/index.css","*{margin:0;padding:0;box-sizing:border-box} body{font-family:system-ui,-apple-system,sans-serif;background:#f0f2f5;color:#1a1a2e} .app{min-height:100vh;display:flex;flex-direction:column} .app-header{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;padding:40px} h1{font-size:2.5rem;font-weight:700} "); 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)+" Generated by PantheraHive BOS. ## Setup ```bash npm install npm run dev ``` ## Build ```bash npm run build ``` ## Open in IDE Open the project folder in VS Code or WebStorm. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local "); } /* --- 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",'{ "name": "'+pn+'", "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", "build": "vue-tsc -b && vite build", "preview": "vite preview" }, "dependencies": { "vue": "^3.5.13", "vue-router": "^4.4.5", "pinia": "^2.3.0", "axios": "^1.7.9" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", "typescript": "~5.7.3", "vite": "^6.0.5", "vue-tsc": "^2.2.0" } } '); zip.file(folder+"vite.config.ts","import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import { resolve } from 'path' export default defineConfig({ plugins: [vue()], resolve: { alias: { '@': resolve(__dirname,'src') } } }) "); zip.file(folder+"tsconfig.json",'{"files":[],"references":[{"path":"./tsconfig.app.json"},{"path":"./tsconfig.node.json"}]} '); zip.file(folder+"tsconfig.app.json",'{ "compilerOptions":{ "target":"ES2020","useDefineForClassFields":true,"module":"ESNext","lib":["ES2020","DOM","DOM.Iterable"], "skipLibCheck":true,"moduleResolution":"bundler","allowImportingTsExtensions":true, "isolatedModules":true,"moduleDetection":"force","noEmit":true,"jsxImportSource":"vue", "strict":true,"paths":{"@/*":["./src/*"]} }, "include":["src/**/*.ts","src/**/*.d.ts","src/**/*.tsx","src/**/*.vue"] } '); zip.file(folder+"env.d.ts","/// "); zip.file(folder+"index.html"," "+slugTitle(pn)+"
"); 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' import { createPinia } from 'pinia' import App from './App.vue' import './assets/main.css' const app = createApp(App) app.use(createPinia()) app.mount('#app') "); var hasApp=Object.keys(extracted).some(function(k){return k.indexOf("App.vue")>=0;}); if(!hasApp) zip.file(folder+"src/App.vue"," "); 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} "); 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)+" Generated by PantheraHive BOS. ## Setup ```bash npm install npm run dev ``` ## Build ```bash npm run build ``` Open in VS Code or WebStorm. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local "); } /* --- 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",'{ "name": "'+pn+'", "version": "0.0.0", "scripts": { "ng": "ng", "start": "ng serve", "build": "ng build", "test": "ng test" }, "dependencies": { "@angular/animations": "^19.0.0", "@angular/common": "^19.0.0", "@angular/compiler": "^19.0.0", "@angular/core": "^19.0.0", "@angular/forms": "^19.0.0", "@angular/platform-browser": "^19.0.0", "@angular/platform-browser-dynamic": "^19.0.0", "@angular/router": "^19.0.0", "rxjs": "~7.8.0", "tslib": "^2.3.0", "zone.js": "~0.15.0" }, "devDependencies": { "@angular-devkit/build-angular": "^19.0.0", "@angular/cli": "^19.0.0", "@angular/compiler-cli": "^19.0.0", "typescript": "~5.6.0" } } '); zip.file(folder+"angular.json",'{ "$schema": "./node_modules/@angular/cli/lib/config/schema.json", "version": 1, "newProjectRoot": "projects", "projects": { "'+pn+'": { "projectType": "application", "root": "", "sourceRoot": "src", "prefix": "app", "architect": { "build": { "builder": "@angular-devkit/build-angular:application", "options": { "outputPath": "dist/'+pn+'", "index": "src/index.html", "browser": "src/main.ts", "tsConfig": "tsconfig.app.json", "styles": ["src/styles.css"], "scripts": [] } }, "serve": {"builder":"@angular-devkit/build-angular:dev-server","configurations":{"production":{"buildTarget":"'+pn+':build:production"},"development":{"buildTarget":"'+pn+':build:development"}},"defaultConfiguration":"development"} } } } } '); zip.file(folder+"tsconfig.json",'{ "compileOnSave": false, "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"]}, "references":[{"path":"./tsconfig.app.json"}] } '); zip.file(folder+"tsconfig.app.json",'{ "extends":"./tsconfig.json", "compilerOptions":{"outDir":"./dist/out-tsc","types":[]}, "files":["src/main.ts"], "include":["src/**/*.d.ts"] } '); zip.file(folder+"src/index.html"," "+slugTitle(pn)+" "); zip.file(folder+"src/main.ts","import { bootstrapApplication } from '@angular/platform-browser'; import { appConfig } from './app/app.config'; import { AppComponent } from './app/app.component'; bootstrapApplication(AppComponent, appConfig) .catch(err => console.error(err)); "); zip.file(folder+"src/styles.css","* { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: system-ui, -apple-system, sans-serif; background: #f9fafb; color: #111827; } "); 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'; import { RouterOutlet } from '@angular/router'; @Component({ selector: 'app-root', standalone: true, imports: [RouterOutlet], templateUrl: './app.component.html', styleUrl: './app.component.css' }) export class AppComponent { title = '"+pn+"'; } "); zip.file(folder+"src/app/app.component.html","

"+slugTitle(pn)+"

Built with PantheraHive BOS

"); 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} "); } zip.file(folder+"src/app/app.config.ts","import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; export const appConfig: ApplicationConfig = { providers: [ provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes) ] }; "); zip.file(folder+"src/app/app.routes.ts","import { Routes } from '@angular/router'; export const routes: Routes = []; "); 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)+" Generated by PantheraHive BOS. ## Setup ```bash npm install ng serve # or: npm start ``` ## Build ```bash ng build ``` Open in VS Code with Angular Language Service extension. "); zip.file(folder+".gitignore","node_modules/ dist/ .env .DS_Store *.local .angular/ "); } /* --- Python --- */ function buildPython(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^```[w]* ?/m,"").replace(/ ?```$/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(" "):"# add dependencies here "; zip.file(folder+"main.py",src||"# "+title+" # Generated by PantheraHive BOS print(title+" loaded") "); zip.file(folder+"requirements.txt",reqsTxt); zip.file(folder+".env.example","# Environment variables "); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Setup ```bash python3 -m venv .venv source .venv/bin/activate pip install -r requirements.txt ``` ## Run ```bash python main.py ``` "); zip.file(folder+".gitignore",".venv/ __pycache__/ *.pyc .env .DS_Store "); } /* --- Node.js --- */ function buildNode(zip,folder,app,code){ var title=slugTitle(app); var pn=pkgName(app); var src=code.replace(/^```[w]* ?/m,"").replace(/ ?```$/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)+" "; zip.file(folder+"package.json",pkgJson); var fallback="const express=require("express"); const app=express(); app.use(express.json()); app.get("/",(req,res)=>{ res.json({message:""+title+" API"}); }); const PORT=process.env.PORT||3000; app.listen(PORT,()=>console.log("Server on port "+PORT)); "; zip.file(folder+"src/index.js",src||fallback); zip.file(folder+".env.example","PORT=3000 "); zip.file(folder+".gitignore","node_modules/ .env .DS_Store "); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Setup ```bash npm install ``` ## Run ```bash npm run dev ``` "); } /* --- 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:" "+title+" "+code+" "; zip.file(folder+"index.html",indexHtml); zip.file(folder+"style.css","/* "+title+" — styles */ *{margin:0;padding:0;box-sizing:border-box} body{font-family:system-ui,-apple-system,sans-serif;background:#fff;color:#1a1a2e} "); zip.file(folder+"script.js","/* "+title+" — scripts */ "); zip.file(folder+"assets/.gitkeep",""); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. ## Open Double-click `index.html` in your browser. Or serve locally: ```bash npx serve . # or python3 -m http.server 3000 ``` "); zip.file(folder+".gitignore",".DS_Store node_modules/ .env "); } /* ===== 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(/ {2,}/g,"

"); h+="

"+hc+"

Generated by PantheraHive BOS
"; zip.file(folder+app+".html",h); zip.file(folder+"README.md","# "+title+" Generated by PantheraHive BOS. Files: - "+app+".md (Markdown) - "+app+".html (styled HTML) "); } 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);}});}