API Rate Limiter
Run ID: 69cb49ed61b1021a29a87a272026-03-31Development
PantheraHive BOS
BOS Dashboard

This document details the design and provides a production-ready implementation for an API Rate Limiter. This solution utilizes the Sliding Window Counter algorithm with Redis as the backend storage, implemented in Python. It is designed for robustness, scalability, and ease of integration into existing systems.


API Rate Limiter: Design & Implementation

1. Introduction to API Rate Limiting

API Rate Limiting is a crucial mechanism for controlling the rate at which clients can send requests to an API. It serves several critical purposes:

2. Chosen Algorithm: Sliding Window Counter

We've selected the Sliding Window Counter algorithm for its balance of accuracy, fairness, and performance.

Why Sliding Window Counter?

How it Works:

For each API client (identified by an IP address, API key, or user ID), the system maintains a sorted set (ZSET) in Redis. Each entry in the ZSET represents a request and stores its timestamp (as the score) and a unique identifier (as the member).

  1. When a request arrives, its current timestamp is recorded.
  2. All requests older than the defined time window (e.g., 60 seconds ago) are removed from the client's ZSET.
  3. The current request's timestamp and a unique ID are added to the ZSET.
  4. The total number of requests remaining in the ZSET (within the window) is counted.
  5. If this count exceeds the max_requests limit, the request is denied (rate-limited). Otherwise, it's allowed.

3. Key Components & Design Rationale

* IP Address: Simple to implement, but problematic for clients behind NATs or proxies.

* API Key: Requires clients to provide a key, offering more granular control.

* User ID: Applicable after authentication, providing per-user limits.

Our implementation supports a configurable key_prefix and expects a key_identifier to be passed, making it flexible.*


Production-Ready Python Implementation

This section provides the complete Python code for the API Rate Limiter, designed for production environments.

1. Dependencies

You will need the redis Python client library. Install it using pip:

text • 97 chars
### 2. `rate_limiter.py`

This file contains the `RateLimiter` class and the Redis Lua script.

Sandboxed live preview

API Rate Limiter - Comprehensive Study Plan

This document outlines a detailed study plan designed to provide a deep understanding of API Rate Limiters, covering their fundamental principles, various algorithms, architectural considerations, and practical implementation strategies. This plan is structured to guide you through a systematic learning process, culminating in the ability to design and discuss robust rate limiting solutions.


1. Introduction: The Importance of API Rate Limiters

API Rate Limiters are critical components in modern distributed systems, serving multiple vital functions:

  • System Stability: Preventing resource exhaustion, denial-of-service (DoS) attacks, and cascading failures by controlling the volume of incoming requests.
  • Fair Resource Usage: Ensuring that no single client or user can monopolize system resources, maintaining service quality for all.
  • Cost Management: Limiting expensive operations or external API calls to stay within budget constraints.
  • Security: Mitigating brute-force attacks and credential stuffing by restricting repeated failed attempts.
  • Operational Control: Providing a mechanism for service providers to enforce usage policies and service level agreements (SLAs).

This study plan will equip you with the knowledge to understand, design, and implement effective API Rate Limiter solutions.


2. Learning Objectives

By the end of this study plan, you will be able to:

  • Conceptual Understanding: Articulate the core purpose, benefits, and challenges of API Rate Limiters.
  • Algorithm Mastery: Differentiate, explain, and compare the primary rate limiting algorithms, including:

* Fixed Window Counter

* Sliding Log

* Sliding Window Counter

* Token Bucket

* Leaky Bucket

  • Trade-off Analysis: Analyze the strengths, weaknesses, and appropriate use cases for each algorithm, considering factors like burst handling, memory usage, and fairness.
  • Architectural Design: Design a high-level architecture for a distributed API Rate Limiter, identifying key components (e.g., API Gateway, Rate Limiter Service, Data Store) and data flows.
  • Scalability & Reliability: Discuss considerations for scaling rate limiters in a distributed environment and ensuring their fault tolerance.
  • Implementation Awareness: Understand the practical aspects of implementing rate limiters, including choice of data stores (e.g., Redis), handling client-side communication (HTTP headers), and monitoring.
  • Advanced Topics: Address challenges such as handling bursts, managing different user tiers, and implementing dynamic rate limits.

3. Weekly Schedule

This schedule provides a structured approach, dedicating focused effort each week to build foundational knowledge and progressively tackle more complex topics.

  • Week 1: Fundamentals & Basic Algorithms (4-6 hours)

* Topics:

* Introduction to API Rate Limiting: Why, What, Where.

* Basic concepts: Rate, Quota, Window.

* Fixed Window Counter Algorithm:

* Mechanism, advantages (simplicity), disadvantages (bursts at window edges).

* Basic pseudocode/logic for implementation.

* Sliding Log Algorithm:

* Mechanism, advantages (accuracy, no edge issues), disadvantages (memory usage for large windows).

* Basic pseudocode/logic, using sorted sets (e.g., Redis ZSET).

* Activities: Read introductory articles, watch conceptual videos, attempt to write pseudocode for both algorithms.

  • Week 2: Advanced Algorithms & Trade-offs (5-7 hours)

* Topics:

* Sliding Window Counter Algorithm:

* Mechanism (combining fixed window and sliding log concepts), advantages (better accuracy than fixed window, less memory than sliding log).

* Implementation considerations (e.g., using two fixed windows).

* Token Bucket Algorithm:

* Mechanism (tokens, bucket capacity, refill rate), advantages (burst tolerance, smooth traffic), disadvantages (bucket size tuning).

* Detailed pseudocode/logic.

* Leaky Bucket Algorithm:

* Mechanism (fixed outflow rate, queue), advantages (smoothes traffic, good for backend stability), disadvantages (queue size tuning, potential for dropped requests).

* Detailed pseudocode/logic.

* Comparative Analysis: In-depth discussion of all algorithms, their suitability for different scenarios, and their respective trade-offs (accuracy, memory, CPU, burst handling).

* Activities: Deep dive into each algorithm's mechanics, compare and contrast them using a table, consider edge cases for each.

  • Week 3: Distributed Rate Limiting & Architecture (6-8 hours)

* Topics:

* Challenges of Distributed Rate Limiting: Consistency, synchronization, network latency, single point of failure.

* High-Level Architecture Design:

* Placement: API Gateway vs. Service Mesh vs. Application-level.

* Components: API Gateway, dedicated Rate Limiter Service, Data Store (e.g., Redis, Memcached).

* Data Flow: How requests are intercepted, counted, and decisions made.

* Data Stores for Rate Limiting:

* Why Redis is popular: In-memory, atomic operations, data structures (hashes, sorted sets).

* Considerations for other options (e.g., database, in-memory cache).

* Scalability & High Availability: Horizontal scaling strategies, replication, partitioning.

* Activities: Sketch a distributed rate limiter architecture on a whiteboard, identify potential bottlenecks, research Redis specific commands for rate limiting.

  • Week 4: Implementation Details & Advanced Topics (5-7 hours)

* Topics:

* Client Communication: HTTP headers (X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After).

* Handling Bursts and Quotas: Differentiating between hard limits, soft limits, and burst allowances.

* User Tiers & Granularity: Applying different rate limits based on user roles, subscription plans, or API keys.

* Monitoring & Alerting: Key metrics to track (rate limit hits, throttled requests, errors), setting up alerts.

* Edge Cases & Security: Handling malicious clients, IP spoofing, and ensuring accurate client identification.

* Case Studies: Analyze how major companies (e.g., Twitter, Stripe, GitHub) implement and communicate their rate limits.

* Activities: Review examples of HTTP headers, think about how to design a flexible rate limiting policy for different user tiers, research real-world API rate limit policies.

  • Week 5 (Optional): Practical Application & Project (8-12 hours)

* Topics:

* Hands-on project to build a simple API Rate Limiter service.

* Activities:

* Choose a Language/Framework: (e.g., Python with Flask/FastAPI, Node.js with Express, Go with Gin, Java with Spring Boot).

* Set up Redis: Use Docker or a local installation.

* Implement at least two algorithms: Select two algorithms (e.g., Token Bucket and Sliding Window Counter) and implement them.

* Create a simple API endpoint: Protect it with your rate limiter.

* Test and Refine: Use tools like curl or Postman to test rate limiting behavior.

Bonus: Implement X-RateLimit- headers in your API responses.


4. Recommended Resources

Leverage a variety of resources to gain a comprehensive understanding:

  • Books:

* "System Design Interview – An insider's guide" by Alex Xu: Contains a dedicated, excellent chapter on designing a distributed rate limiter.

* "Designing Data-Intensive Applications" by Martin Kleppmann: Essential for understanding distributed systems fundamentals relevant to rate limiter architecture.

  • Online Articles & Blogs:

* Educative.io / ByteByteGo / System Design Interview Prep: Search for "design a rate limiter" for detailed walkthroughs and algorithm explanations.

* Medium.com / Dev.to: Many engineers share their insights and implementations of rate limiters.

* Redis Documentation: Explore Redis data structures like Sorted Sets (ZADD, ZRANGEBYSCORE, ZREMRANGEBYSCORE) and Hashes.

  • Videos:

* YouTube Channels (e.g., Gaurav Sen, Tech Dummies Narendra L, LeetCode): Search for "System Design Rate Limiter" for whiteboard sessions and architectural discussions.

* Conference Talks: Look for talks from large tech companies on their rate limiting strategies (e.g., from AWS re:Invent, Google Cloud Next, KubeCon).

  • Online Courses:

* Grokking the System Design Interview (Educative.io): Includes a module specifically on designing a rate limiter.

* Udemy/Coursera: Search for "System Design" courses that cover rate limiting as a key component.

  • Tools:

* Docker: For easily setting up and managing a local Redis instance.

* Your Preferred IDE/Code Editor: For hands-on implementation.

* curl / Postman / Insomnia: For testing API endpoints and observing rate limiting behavior.


5. Milestones

These milestones serve as checkpoints to track your progress and ensure you are meeting the learning objectives.

  • Milestone 1 (End of Week 1): Foundational Understanding

* Achievement: Clearly articulate the need for rate limiting and explain the Fixed Window Counter and Sliding Log algorithms, including their pros and cons.

* Deliverable: Be able to describe these concepts verbally or in a short written summary.

  • Milestone 2 (End of Week 2): Algorithm Mastery

* Achievement: Confidently explain all major rate limiting algorithms (Fixed Window, Sliding Log, Sliding Window Counter, Token Bucket, Leaky Bucket) and their respective use cases and trade-offs.

* Deliverable: Create a comparison table outlining the characteristics of each algorithm.

  • Milestone 3 (End of Week 3): Architectural Blueprint

* Achievement: Sketch a high-level architecture diagram for a distributed API Rate Limiter, identifying critical components, data flow, and key design decisions (e.g., choice of data store).

* Deliverable: A simple architectural diagram (can be hand-drawn or digital) with brief explanations.

  • Milestone 4 (End of Week 4): Comprehensive Insights

* Achievement: Understand advanced topics such as client communication via HTTP headers, handling different user tiers, and strategies for monitoring and alerting.

* Deliverable: Be able to discuss common challenges and solutions for real-world rate limiting scenarios.

  • Milestone 5 (End of Week 5 - Optional): Practical Implementation

* Achievement: Successfully implement a basic functional API Rate Limiter service in a chosen

python

import time

import uuid

import redis

import logging

from typing import Optional, Tuple

Configure logging

logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')

logger = logging.getLogger(__name__)

class RateLimiter:

"""

A Redis-backed API Rate Limiter using the Sliding Window Counter algorithm.

This class provides a flexible and efficient way to limit API request rates

for different clients based on a defined window size and maximum requests.

It leverages Redis Sorted Sets (ZSET) and Lua scripting for atomic operations

and high performance.

"""

# Lua script for atomic rate limiting operations in Redis.

# This script performs the following steps:

# 1. Removes requests older than the current window from the ZSET.

# 2. Adds the current request with its timestamp and a unique ID to the ZSET.

# 3. Counts the number of requests remaining in the ZSET within the window.

# 4. Sets/updates the expiry for the ZSET key.

# 5. Returns 0 if rate-limited, 1 if allowed.

_LUA_SCRIPT = """

local key = KEYS[1]

local window_size_seconds = tonumber(ARGV[1])

local max_requests = tonumber(ARGV[2])

local current_timestamp_ms = tonumber(ARGV[3])

local expiry_time_seconds = tonumber(ARGV[4])

local request_id = ARGV[5]

-- Calculate window start time in milliseconds

local window_start_ms = current_timestamp_ms - (window_size_seconds * 1000)

-- Remove requests older than the current window start

redis.call('ZREMRANGEBYSCORE', key, 0, window_start_ms)

-- Add the current request with its timestamp as score and unique ID as member

-- ZADD key score member

redis.call('ZADD', key, current_timestamp_ms, request_id)

-- Get the number of requests currently in the window

local count = redis.call('ZCARD', key)

-- Set/Update expiry for the key. This prevents keys from living forever

-- if no new requests come. The expiry is set to be slightly longer than

-- the window_size_seconds to ensure the key isn't removed prematurely

-- if the last request is just at the edge of the window.

redis.call('EXPIRE', key, expiry_time_seconds)

if count > max_requests then

return 0 -- Rate limited (0 indicates failure/blocked)

else

return 1 -- Allowed (1 indicates success/allowed)

end

"""

def __init__(

self,

redis_client: redis.Redis,

window_size_seconds: int = 60,

max_requests: int = 100,

key_prefix: str = "rate_limit",

expiry_buffer_seconds: int = 5,

):

"""

Initializes the RateLim

gemini Output

API Rate Limiter: Comprehensive Review and Documentation

This document provides a detailed, professional overview of API Rate Limiters, outlining their purpose, mechanisms, benefits, design considerations, and actionable recommendations for your organization. Implementing effective API rate limiting is crucial for maintaining system stability, security, and ensuring fair usage of your API resources.


1. Executive Summary

An API Rate Limiter is a critical component in any robust API ecosystem, designed to control the number of requests an API client can make within a specified timeframe. Its primary functions include protecting your backend services from overload, preventing malicious attacks (e.g., DoS/DDoS), managing infrastructure costs, and ensuring equitable access for all legitimate users. This document delves into the core aspects of API rate limiting, offering a foundational understanding and strategic guidance for its successful implementation.


2. Understanding API Rate Limiting

2.1. Definition

API Rate Limiting is a technique used to restrict the number of API requests a user or client can make to a server within a given time window. When a client exceeds the defined limit, subsequent requests are typically blocked or throttled for a period.

2.2. Purpose and Importance

Implementing API Rate Limiters serves several vital purposes:

  • System Stability and Reliability: Prevents your backend servers from being overwhelmed by a flood of requests, ensuring consistent performance for all users.
  • Security and Abuse Prevention: Mitigates various forms of attack, including Denial of Service (DoS), Brute-Force attacks, and data scraping, by limiting the rate at which these attacks can occur.
  • Cost Management: Reduces infrastructure costs by preventing excessive resource consumption (CPU, memory, network bandwidth) that can result from uncontrolled API usage.
  • Fair Usage and Quality of Service (QoS): Ensures that no single user or application can monopolize API resources, providing a fair and consistent experience for all legitimate consumers.
  • Resource Optimization: Helps allocate resources efficiently, allowing your API to serve a larger user base effectively.

3. Core Mechanisms and Algorithms

Various algorithms are employed to implement API Rate Limiting, each with its own advantages and trade-offs. The choice of algorithm often depends on specific requirements for accuracy, memory usage, and distributed system compatibility.

  • 3.1. Fixed Window Counter

* Mechanism: Divides time into fixed-size windows (e.g., 1 minute). Each window has a counter. When a request arrives, the counter increments. If the counter exceeds the limit within the current window, the request is rejected.

* Pros: Simple to implement, low memory overhead.

* Cons: Can suffer from "bursty" traffic at the window edges, allowing twice the rate limit if requests occur at the very end of one window and the very beginning of the next.

  • 3.2. Sliding Window Log

* Mechanism: Stores a timestamp for every request made by a client. For each new request, it counts the number of timestamps within the defined window (e.g., the last 60 seconds). If the count exceeds the limit, the request is rejected.

* Pros: Highly accurate, no edge case issues.

* Cons: High memory consumption, especially for high request volumes, as it needs to store all timestamps.

  • 3.3. Sliding Window Counter

* Mechanism: A hybrid approach. It uses two fixed windows: the current window and the previous window. The count for the current window is weighted by the percentage of the previous window that has elapsed.

* Pros: Offers a good balance between accuracy and memory efficiency compared to Sliding Window Log. Addresses the edge case issue of Fixed Window Counter more effectively.

* Cons: More complex to implement than Fixed Window Counter.

  • 3.4. Token Bucket

* Mechanism: Imagine a bucket with a fixed capacity for "tokens." Tokens are added to the bucket at a constant rate. Each API request consumes one token. If the bucket is empty, the request is rejected.

* Pros: Allows for bursts of traffic up to the bucket capacity, simple to understand and implement.

* Cons: The burst size is limited by the bucket capacity. Doesn't strictly enforce a constant rate over short periods if the bucket is full.

  • 3.5. Leaky Bucket

* Mechanism: Similar to a bucket where requests are placed. The bucket has a fixed capacity, and requests "leak out" (are processed) at a constant rate. If the bucket is full, new requests are rejected.

* Pros: Smooths out bursty traffic, ensuring a steady processing rate.

* Cons: Can introduce latency if the bucket fills up, as requests queue. Does not allow for bursts.


4. Key Benefits of Implementing API Rate Limiting

  • Enhanced System Stability: Prevents server overload, ensuring your API remains responsive even under heavy load.
  • Improved Security Posture: Acts as a first line of defense against various cyber threats, significantly reducing the attack surface.
  • Predictable Performance: Guarantees a baseline level of service for all legitimate API consumers by preventing resource monopolization.
  • Reduced Operational Costs: By preventing excessive usage, it minimizes the need for over-provisioning infrastructure, leading to cost savings.
  • Better User Experience: Ensures that well-behaved clients consistently receive prompt responses, fostering a positive developer and user experience.

5. Design Considerations and Best Practices

Successful API rate limiting requires careful planning and implementation. Consider the following:

  • 5.1. Granularity of Limits:

* Per User/Client ID: Most common, tied to an authenticated user or API key.

* Per IP Address: Useful for unauthenticated requests, but can be problematic with shared IPs (e.g., NAT, proxies).

* Per Endpoint: Different endpoints may have different resource demands and thus require different limits (e.g., read operations vs. write operations).

* Per Resource: Limiting access to specific resources within an endpoint.

  • 5.2. Rate Limit Policies:

* Global Limits: Apply across all API requests for a client.

* Endpoint-Specific Limits: Tailored limits for particular API endpoints.

* Tiered Limits: Different limits for different subscription levels (e.g., free tier vs. premium tier).

  • 5.3. Response to Exceeding Limits:

* HTTP Status Code: Always use 429 Too Many Requests.

* Retry-After Header: Include this header in the response, indicating how long the client should wait before making another request. This helps clients implement backoff strategies.

* Clear Error Message: Provide a helpful message in the response body, explaining the limit and how to resolve it.

  • 5.4. Distributed Systems Challenges:

* In a microservices architecture or with multiple API gateway instances, maintaining a consistent global rate limit requires a shared, centralized store (e.g., Redis, Cassandra) for counters.

* Consider eventual consistency vs. strong consistency trade-offs for rate limit updates.

  • 5.5. Monitoring and Alerting:

* Implement robust monitoring to track rate limit breaches, identify potential abuse patterns, and analyze API usage trends.

* Set up alerts for high rates of 429 errors or unusual request patterns.

  • 5.6. Visibility and Communication:

* Clearly document your rate limiting policies in your API documentation.

* Use HTTP headers (e.g., X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset) to inform clients about their current limit status.

  • 5.7. Edge Cases and Whitelisting:

* Consider whitelisting internal services, trusted partners, or specific IP addresses from rate limits if necessary.

* Implement burst limits to allow for temporary spikes in traffic without immediately triggering hard limits.


6. Implementation Strategies

Rate limiting can be implemented at various layers of your architecture:

  • 6.1. Application Layer:

* Description: Implemented directly within your application code using libraries or custom logic.

* Pros: Highly customizable, fine-grained control.

* Cons: Adds complexity to application logic, requires consistent implementation across all services.

  • 6.2. API Gateway/Proxy Layer:

* Description: Utilizes dedicated API gateways (e.g., AWS API Gateway, Azure API Management, NGINX, Kong, Apigee) that offer built-in rate limiting capabilities.

* Pros: Centralized management, offloads rate limiting logic from applications, often highly scalable and performant.

* Cons: Can be an additional cost or point of failure, may require integration effort.

  • 6.3. Dedicated Rate Limiting Service:

* Description: A standalone service (e.g., using Redis for storage) specifically designed to manage and enforce rate limits across your entire infrastructure.

* Pros: Highly scalable, flexible, and decoupled from application logic.

* Cons: Adds another service to manage, requires careful design for distributed consistency.


7. Actionable Recommendations for Your Organization

Based on the comprehensive review, we recommend the following strategic actions:

  1. Define Clear Rate Limit Policies:

* Action: Conduct a workshop with stakeholders (product, engineering, security) to define granular rate limiting policies for different API endpoints, user tiers, and authentication states.

* Deliverable: A documented matrix of rate limits, including limits per window, window size, and criteria (e.g., per IP, per user, per API key).

  1. Choose an Appropriate Algorithm:

* Action: Evaluate the various algorithms (Sliding Window Counter or Token Bucket are often good starting points) based on your specific needs for accuracy, burst tolerance, and resource constraints.

* Consideration: For distributed systems, favor algorithms that are easier to implement with a shared state (e.g., Redis).

  1. Implement via an API Gateway or Dedicated Service:

* Action: For robust, scalable, and centralized management, prioritize implementing rate limiting at the API Gateway layer (if you have one) or by integrating a dedicated rate limiting service. Avoid purely application-level rate limiting unless absolutely necessary for specific microservices.

* Benefit: Reduces application complexity, improves consistency, and leverages specialized infrastructure.

  1. Establish Robust Monitoring and Alerting:

* Action: Integrate rate limit metrics into your existing monitoring dashboards. Set up alerts for sustained periods of 429 Too Many Requests errors or unusual traffic patterns.

* Outcome: Proactive identification of abuse, misconfigured clients, or potential system overload.

  1. Educate API Consumers and Document Thoroughly:

* Action: Update your API documentation to clearly articulate rate limiting policies, expected HTTP responses (429), and the use of the Retry-After header. Provide examples of client-side backoff strategies.

* Impact: Reduces support requests, encourages responsible client behavior, and improves developer experience.

  1. Plan for Scalability and High Availability:

* Action: Ensure your chosen rate limiting solution can scale horizontally to handle increasing API traffic and is highly available to prevent it from becoming a single point of failure.

* Guidance: For distributed systems, use a performant, fault-tolerant distributed cache (e.g., Redis Cluster) for storing rate limit states.

  1. Regular Review and Adjustment:

* Action: Schedule periodic reviews (e.g., quarterly) of your rate limiting policies and their effectiveness. Adjust limits based on observed traffic patterns, business needs, and new API features.

* Adaptability: Ensures your rate limiting strategy remains relevant and effective as your API evolves.


8. Conclusion

API Rate Limiting is not merely a technical control but a strategic necessity for the health, security, and sustained growth of your API platform. By diligently implementing the recommendations outlined in this document, your organization can significantly enhance the resilience of its API infrastructure, safeguard against abuse, optimize resource utilization, and deliver a superior experience to all API consumers. We stand ready to assist you in designing and implementing these critical components.

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