fastapps


Namefastapps JSON
Version 1.1.1 PyPI version JSON
download
home_pagehttps://github.com/DooiLabs/FastApps
SummaryA zero-boilerplate framework for building interactive ChatGPT widgets
upload_time2025-10-18 06:50:07
maintainerNone
docs_urlNone
authorFastApps Team
requires_python>=3.11
licenseMIT
keywords chatgpt widgets mcp framework react
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # FastApps Framework

<p align="center">
  <strong>A zero-boilerplate framework for building interactive ChatGPT widgets</strong>
</p>

<p align="center">
  <a href="https://pypi.org/project/fastapps/"><img src="https://img.shields.io/pypi/v/fastapps.svg" alt="PyPI"></a>
  <a href="https://pypi.org/project/fastapps/"><img src="https://img.shields.io/pypi/pyversions/fastapps.svg" alt="Python"></a>
  <a href="https://pepy.tech/projects/fastapps"><img src="https://static.pepy.tech/personalized-badge/fastapps?period=total&units=INTERNATIONAL_SYSTEM&left_color=GREY&right_color=GREEN&left_text=downloads" alt="PyPI Downloads"></a>
  <a href="https://github.com/DooiLabs/FastApps/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="License"></a>
  <br>
  <a href="https://github.com/DooiLabs/FastApps/actions"><img src="https://github.com/DooiLabs/FastApps/workflows/CI/badge.svg" alt="CI Status"></a>
  <a href="https://github.com/psf/black"><img src="https://img.shields.io/badge/code%20style-black-000000.svg" alt="Code style: black"></a>
  <a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json" alt="Ruff"></a>
  <a href="https://github.com/DooiLabs/FastApps"><img src="https://img.shields.io/github/stars/DooiLabs/FastApps?style=social" alt="GitHub Stars"></a>
</p>

---

šŸ“š **Documentation**: [https://www.fastapps.org/](https://www.fastapps.org/)

šŸ‘„ **Community**: [Join Our Discord](https://discord.gg/5cEy3Jqek3)

---

## Quick Start

### 1. Create Virtual Environment (Recommended)

```bash
python -m venv venv
source venv/bin/activate    # macOS/Linux
venv\Scripts\activate       # Windows
```

### 2. Install FastApps & Create Project

```bash
pip install fastapps
fastapps init my-app
```

This generates the complete project structure:

```
my-app/
ā”œā”€ā”€ server/
│   ā”œā”€ā”€ __init__.py
│   ā”œā”€ā”€ main.py              # Auto-discovery server
│   ā”œā”€ā”€ tools/               # Widget backends
│   │   └── __init__.py
│   └── api/                 # (optional) Shared APIs
│       └── __init__.py
ā”œā”€ā”€ widgets/                 # Widget frontends (empty initially)
ā”œā”€ā”€ requirements.txt         # Python dependencies
ā”œā”€ā”€ package.json             # JavaScript dependencies
ā”œā”€ā”€ .gitignore
└── README.md
```

### 3. Install Dependencies

```bash
cd my-app
pip install -r requirements.txt
npm install
```

### 4. Create Your First Widget

```bash
fastapps create my-widget
```

This adds to your project:

```
my-app/
ā”œā”€ā”€ server/
│   └── tools/
│       └── my_widget_tool.py # ← Generated: Widget backend
└── widgets/
    └── my-widget/
        └── index.jsx         # ← Generated: Widget frontend
```

### 5. Edit Your Widget Code

**You only need to edit these 2 files:**

#### `server/tools/my_widget_tool.py` - Backend Logic

```python
from fastapps import BaseWidget, Field, ConfigDict
from pydantic import BaseModel
from typing import Dict, Any

class MyWidgetInput(BaseModel):
    model_config = ConfigDict(populate_by_name=True)
    name: str = Field(default="World")

class MyWidgetTool(BaseWidget):
    identifier = "my-widget"
    title = "My Widget"
    input_schema = MyWidgetInput
    invoking = "Processing..."
    invoked = "Done!"
    
    widget_csp = {
        "connect_domains": [],      # APIs you'll call
        "resource_domains": []      # Images/fonts you'll use
    }
    
    async def execute(self, input_data: MyWidgetInput) -> Dict[str, Any]:
        # Your logic here
        return {
            "name": input_data.name,
            "message": f"Hello, {input_data.name}!"
        }
```

#### `widgets/my-widget/index.jsx` - Frontend UI

```jsx
import React from 'react';
import { useWidgetProps } from 'fastapps';

export default function MyWidget() {
  const props = useWidgetProps();
  
  return (
    <div style={{
      padding: '40px',
      textAlign: 'center',
      background: '#4A90E2',
      color: 'white',
      borderRadius: '12px'
    }}>
      <h1>{props.message}</h1>
      <p>Welcome, {props.name}!</p>
    </div>
  );
}
```

**That's it! These are the only files you need to write.**

### 6. Build Widgets

```bash
npm run build
```

### 7. Start Development Server with Public Access

**Option A: Using `fastapps dev` (Recommended)**

The easiest way to run and expose your server:

```bash
fastapps dev
```

On first run, you'll be prompted for your ngrok auth token:
- Get it free at: https://dashboard.ngrok.com/get-started/your-authtoken
- Token is saved and won't be asked again

You'll see:
```
šŸš€ FastApps Development Server
ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¬ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│ Local   │ http://0.0.0.0:8001    │
│ Public  │ https://xyz.ngrok.io   │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”“ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜

šŸ“” MCP Server Endpoint: https://xyz.ngrok.io
```

Use the public URL in ChatGPT Settings > Connectors.

**Option B: Manual Setup**

```bash
# Start server
python server/main.py

# In a separate terminal, create tunnel
ngrok http 8001
```

---

## What You Need to Know

### Widget Structure

Every widget has **exactly 2 files you write**:

1. **Python Tool** (`server/tools/*_tool.py`)
   - Define inputs with Pydantic
   - Write your logic in `execute()`
   - Return data as a dictionary

2. **React Component** (`widgets/*/index.jsx`)
   - Get data with `useWidgetProps()`
   - Render your UI
   - Use inline styles

**Everything else is automatic:**
- Widget discovery
- Registration
- Build process
- Server setup
- Mounting logic

### Input Schema

```python
from fastapps import Field, ConfigDict
from pydantic import BaseModel

class MyInput(BaseModel):
    model_config = ConfigDict(populate_by_name=True)
    
    name: str = Field(default="", description="User's name")
    age: int = Field(default=0, ge=0, le=150)
    email: str = Field(default="", pattern=r'^[\w\.-]+@[\w\.-]+\.\w+$')
```

### CSP (Content Security Policy)

Allow external resources:

```python
widget_csp = {
    "connect_domains": ["https://api.example.com"],     # For API calls
    "resource_domains": ["https://cdn.example.com"]     # For images/fonts
}
```

### React Hooks

```jsx
import { useWidgetProps, useWidgetState, useOpenAiGlobal } from 'fastapps';

function MyWidget() {
  const props = useWidgetProps();              // Data from Python
  const [state, setState] = useWidgetState({}); // Persistent state
  const theme = useOpenAiGlobal('theme');      // ChatGPT theme
  
  return <div>{props.message}</div>;
}
```

---

## Documentation

- **[Quick Start Guide](https://github.com/DooiLabs/FastApps/blob/main/docs/QUICKSTART.md)** - Detailed setup instructions
- **[Tutorial](https://github.com/DooiLabs/FastApps/blob/main/docs/TUTORIAL.md)** - Step-by-step widget examples
- **[Python API](https://github.com/DooiLabs/FastApps/blob/main/docs/PYTHON_API.md)** - Programmatic dev server control
- **[API Reference](https://github.com/DooiLabs/FastApps/blob/main/docs/API.md)** - Complete API documentation
- **[Examples](https://github.com/DooiLabs/FastApps/tree/main/examples)** - Real-world code examples

---

## CLI Commands

```bash
# Initialize new project
fastapps init my-app

# Create new widget (auto-generates both files)
fastapps create mywidget

# Start development server with ngrok tunnel
fastapps dev

# Start on custom port
fastapps dev --port 8080

# Reset ngrok auth token
fastapps reset-token

# View authentication guide
fastapps auth-info
```

**Tip**: If `fastapps` command is not found, use:
```bash
python -m fastapps.cli.main <command>
```

---

## Project Structure After `fastapps create`

When you run `python -m fastapps.cli.main create my-widget`, you get:

```
my-app/
ā”œā”€ā”€ server/
│   ā”œā”€ā”€ __init__.py
│   ā”œā”€ā”€ main.py                  # Already setup (no edits needed)
│   ā”œā”€ā”€ tools/
│   │   ā”œā”€ā”€ __init__.py
│   │   └── my_widget_tool.py    # ← Edit this: Your widget logic
│   └── api/                     # (optional: for shared APIs)
│
ā”œā”€ā”€ widgets/
│   └── my-widget/
│       └── index.jsx            # ← Edit this: Your UI
│
ā”œā”€ā”€ assets/                      # Auto-generated during build
│   ā”œā”€ā”€ my-widget-HASH.html
│   └── my-widget-HASH.js
│
ā”œā”€ā”€ requirements.txt             # Python dependencies
ā”œā”€ā”€ package.json                 # JavaScript dependencies
└── build-all.mts                # Auto-copied from fastapps
```

**You only edit the 2 files marked with ←**

---

## Key Features

- **Zero Boilerplate** - Just write your widget code
- **Auto-Discovery** - Widgets automatically registered
- **Type-Safe** - Pydantic for Python, TypeScript for React
- **CLI Tools** - Scaffold widgets instantly
- **Python API** - Programmatic server control
- **ngrok Integration** - Public URLs with one command
- **React Hooks** - Modern React patterns via `fastapps`
- **MCP Protocol** - Native ChatGPT integration

---

## Python API

Start dev servers programmatically:

```python
from fastapps import start_dev_server

# Simple usage
start_dev_server()

# With configuration
start_dev_server(
    port=8080,
    auto_reload=True,
    ngrok_token="your_token"
)

# Get server info without starting
from fastapps import get_server_info
info = get_server_info(port=8001)
print(f"Public URL: {info.public_url}")
```

See [Python API Documentation](./docs/PYTHON_API.md) for more details.

---

## Examples

### Simple Widget

```python
# server/tools/hello_tool.py
class HelloTool(BaseWidget):
    identifier = "hello"
    title = "Hello"
    input_schema = HelloInput
    
    async def execute(self, input_data):
        return {"message": "Hello World!"}
```

```jsx
// widgets/hello/index.jsx
export default function Hello() {
  const props = useWidgetProps();
  return <h1>{props.message}</h1>;
}
```

### With API Call

```python
async def execute(self, input_data):
    async with httpx.AsyncClient() as client:
        response = await client.get("https://api.example.com/data")
        data = response.json()
    return {"data": data}
```

### With State

```jsx
function Counter() {
  const [state, setState] = useWidgetState({ count: 0 });
  return (
    <button onClick={() => setState({ count: state.count + 1 })}>
      Count: {state.count}
    </button>
  );
}
```

### Development Server with ngrok (pyngrok)

**Real-World Use Cases:**

| Use Case | Scenario | Benefits |
|----------|----------|----------|
| šŸ¤– **ChatGPT Development** | Develop ChatGPT custom actions locally | Test widgets in ChatGPT without deployment |
| šŸŖ **Webhook Testing** | Test webhooks from Stripe, GitHub, Slack | Get real webhook events on localhost |
| šŸ‘„ **Remote Collaboration** | Share your local dev server with team | Instant demos without pushing code |
| šŸ“± **Mobile Testing** | Test mobile apps against local backend | Access localhost from phone/tablet |
| šŸ”Œ **API Integration** | Third-party APIs need public callback URLs | Receive OAuth callbacks locally |
| šŸ¢ **Client Demos** | Show work-in-progress to clients | Professional public URL instantly |
| šŸŽ“ **Workshops/Teaching** | Students access instructor's local server | Share examples in real-time |
| 🌐 **Cross-Browser Testing** | Test on BrowserStack, Sauce Labs | Cloud browsers access your localhost |
| šŸ”„ **CI/CD Preview** | Preview branches before deployment | Test PRs with temporary URLs |
| šŸ› ļø **IoT Development** | IoT devices callback to local server | Hardware talks to dev environment |

#### Programmatic Start
```python
from fastapps import start_dev_server

# Start with automatic ngrok tunnel
start_dev_server(port=8001)

# With custom configuration
start_dev_server(
    port=8080,
    ngrok_token="your_token",
    auto_reload=True
)
```

#### Get Server URLs for Testing
```python
from fastapps import get_server_info

# Create tunnel and get URLs
info = get_server_info(port=8001)
print(f"Local: {info.local_url}")
print(f"Public: {info.public_url}")

# Use in integration tests
import requests
response = requests.get(f"{info.public_url}/health")
```

#### Environment Variable Token
```python
import os
from fastapps import start_dev_server

# Get token from environment (great for CI/CD)
token = os.getenv("NGROK_TOKEN")
start_dev_server(ngrok_token=token)
```

#### Error Handling
```python
from fastapps import start_dev_server, DevServerError, NgrokError

try:
    start_dev_server(port=8001)
except NgrokError as e:
    print(f"ngrok tunnel failed: {e}")
except DevServerError as e:
    print(f"Server error: {e}")
```

#### Automation Script
```python
#!/usr/bin/env python3
from fastapps import start_dev_server
import sys

if __name__ == "__main__":
    try:
        print("šŸš€ Starting FastApps with ngrok...")
        start_dev_server(
            port=8001,
            auto_reload=True,
            log_level="info"
        )
    except KeyboardInterrupt:
        print("\nāœ… Server stopped")
        sys.exit(0)
```

#### Real-World Example Scenarios

**Scenario 1: ChatGPT Custom Action Development**
```python
# Start server for ChatGPT testing
from fastapps import start_dev_server

# Auto-reload when you edit widgets
start_dev_server(
    port=8001,
    auto_reload=True  # Restart on code changes
)
# Copy ngrok URL → ChatGPT Settings → Connectors → Add your URL
# Test widgets live in ChatGPT while developing!
```

**Scenario 2: Webhook Testing (Stripe, GitHub, etc.)**
```python
from fastapps import get_server_info

# Get public URL for webhook configuration
info = get_server_info(port=8001)
print(f"Configure webhook URL: {info.public_url}/webhooks")

# Add this URL to Stripe Dashboard → Webhooks
# Receive real webhook events on your localhost!
```

**Scenario 3: Team Demo / Client Preview**
```python
from fastapps import start_dev_server

# Share work-in-progress with team
start_dev_server(port=8001)

# Send the ngrok URL to your team/client
# They can access your local server instantly!
# No deployment needed
```

**Scenario 4: Mobile App Testing**
```python
from fastapps import get_server_info

info = get_server_info(port=8001)

# Use public URL in your mobile app config
print(f"API Base URL for mobile app: {info.public_url}")

# Test your iOS/Android app against local backend
# No need for deployed staging server
```

**Scenario 5: OAuth Callback (Third-Party APIs)**
```python
from fastapps import start_dev_server

# OAuth providers need public callback URL
start_dev_server(port=8001)

# Register callback: https://your-ngrok-url.ngrok.io/auth/callback
# Test OAuth flow locally:
# 1. User clicks "Login with Google"
# 2. Google redirects to your ngrok URL
# 3. Your local server receives the callback
```

**Scenario 6: CI/CD Integration Testing**
```python
# .github/workflows/test.yml
import os
from fastapps import start_dev_server
import threading
import requests

# Start server in background
def run_server():
    start_dev_server(
        port=8001,
        ngrok_token=os.getenv("NGROK_TOKEN")
    )

# Run server in separate thread
server_thread = threading.Thread(target=run_server, daemon=True)
server_thread.start()

# Run integration tests against public URL
# Perfect for testing webhooks, OAuth, etc. in CI
```

**Scenario 7: IoT/Embedded Device Testing**
```python
from fastapps import get_server_info

# IoT devices need to callback to your server
info = get_server_info(port=8001)

# Configure IoT device with this URL
print(f"Configure device callback: {info.public_url}/iot/callback")

# Your Raspberry Pi, Arduino, etc. can now reach your localhost!
```

---

## Troubleshooting

**Widget not loading?**
- Check `identifier` matches folder name
- Rebuild: `npm run build`
- Restart: `python server/main.py`

**Import errors?**
```bash
pip install --upgrade fastapps
npm install fastapps@latest
```

**Need help?** Check our [docs](https://github.com/DooiLabs/FastApps/tree/main/docs) or [open an issue](https://github.com/DooiLabs/FastApps/issues)

---

## Contributing

We welcome contributions! Please see our contributing guidelines:

- **[Contributing Guide](https://github.com/DooiLabs/FastApps/blob/main/CONTRIBUTING.md)** - How to contribute to FastApps
- **[Code Style Guide](https://github.com/DooiLabs/FastApps/blob/main/CODE_STYLE.md)** - Code formatting and style standards
- **[GitHub Workflows](https://github.com/DooiLabs/FastApps/blob/main/.github/WORKFLOWS.md)** - CI/CD documentation

### Quick Start for Contributors

```bash
# Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/FastApps.git
cd FastApps

# Install development dependencies
pip install -e ".[dev]"

# Install pre-commit hooks
pip install pre-commit
pre-commit install

# Make changes and ensure they pass checks
black .
ruff check --fix .
pytest

# Submit a pull request
```

## License

MIT Ā© FastApps Team

## Links

- **PyPI**: https://pypi.org/project/fastapps/
- **ChatJS Hooks**: https://www.npmjs.com/package/fastapps
- **GitHub**: https://github.com/DooiLabs/FastApps
- **MCP Spec**: https://modelcontextprotocol.io/

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/DooiLabs/FastApps",
    "name": "fastapps",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.11",
    "maintainer_email": null,
    "keywords": "chatgpt, widgets, mcp, framework, react",
    "author": "FastApps Team",
    "author_email": "FastApps Team <david@dooi.ai>",
    "download_url": "https://files.pythonhosted.org/packages/94/f6/d3e1a8cd349424657d9997d01afb49c703d8b07a4ac19d870f9978322ef4/fastapps-1.1.1.tar.gz",
    "platform": null,
    "description": "# FastApps Framework\n\n<p align=\"center\">\n  <strong>A zero-boilerplate framework for building interactive ChatGPT widgets</strong>\n</p>\n\n<p align=\"center\">\n  <a href=\"https://pypi.org/project/fastapps/\"><img src=\"https://img.shields.io/pypi/v/fastapps.svg\" alt=\"PyPI\"></a>\n  <a href=\"https://pypi.org/project/fastapps/\"><img src=\"https://img.shields.io/pypi/pyversions/fastapps.svg\" alt=\"Python\"></a>\n  <a href=\"https://pepy.tech/projects/fastapps\"><img src=\"https://static.pepy.tech/personalized-badge/fastapps?period=total&units=INTERNATIONAL_SYSTEM&left_color=GREY&right_color=GREEN&left_text=downloads\" alt=\"PyPI Downloads\"></a>\n  <a href=\"https://github.com/DooiLabs/FastApps/blob/main/LICENSE\"><img src=\"https://img.shields.io/badge/license-MIT-blue.svg\" alt=\"License\"></a>\n  <br>\n  <a href=\"https://github.com/DooiLabs/FastApps/actions\"><img src=\"https://github.com/DooiLabs/FastApps/workflows/CI/badge.svg\" alt=\"CI Status\"></a>\n  <a href=\"https://github.com/psf/black\"><img src=\"https://img.shields.io/badge/code%20style-black-000000.svg\" alt=\"Code style: black\"></a>\n  <a href=\"https://github.com/astral-sh/ruff\"><img src=\"https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json\" alt=\"Ruff\"></a>\n  <a href=\"https://github.com/DooiLabs/FastApps\"><img src=\"https://img.shields.io/github/stars/DooiLabs/FastApps?style=social\" alt=\"GitHub Stars\"></a>\n</p>\n\n---\n\n\ud83d\udcda **Documentation**: [https://www.fastapps.org/](https://www.fastapps.org/)\n\n\ud83d\udc65 **Community**: [Join Our Discord](https://discord.gg/5cEy3Jqek3)\n\n---\n\n## Quick Start\n\n### 1. Create Virtual Environment (Recommended)\n\n```bash\npython -m venv venv\nsource venv/bin/activate    # macOS/Linux\nvenv\\Scripts\\activate       # Windows\n```\n\n### 2. Install FastApps & Create Project\n\n```bash\npip install fastapps\nfastapps init my-app\n```\n\nThis generates the complete project structure:\n\n```\nmy-app/\n\u251c\u2500\u2500 server/\n\u2502   \u251c\u2500\u2500 __init__.py\n\u2502   \u251c\u2500\u2500 main.py              # Auto-discovery server\n\u2502   \u251c\u2500\u2500 tools/               # Widget backends\n\u2502   \u2502   \u2514\u2500\u2500 __init__.py\n\u2502   \u2514\u2500\u2500 api/                 # (optional) Shared APIs\n\u2502       \u2514\u2500\u2500 __init__.py\n\u251c\u2500\u2500 widgets/                 # Widget frontends (empty initially)\n\u251c\u2500\u2500 requirements.txt         # Python dependencies\n\u251c\u2500\u2500 package.json             # JavaScript dependencies\n\u251c\u2500\u2500 .gitignore\n\u2514\u2500\u2500 README.md\n```\n\n### 3. Install Dependencies\n\n```bash\ncd my-app\npip install -r requirements.txt\nnpm install\n```\n\n### 4. Create Your First Widget\n\n```bash\nfastapps create my-widget\n```\n\nThis adds to your project:\n\n```\nmy-app/\n\u251c\u2500\u2500 server/\n\u2502   \u2514\u2500\u2500 tools/\n\u2502       \u2514\u2500\u2500 my_widget_tool.py # \u2190 Generated: Widget backend\n\u2514\u2500\u2500 widgets/\n    \u2514\u2500\u2500 my-widget/\n        \u2514\u2500\u2500 index.jsx         # \u2190 Generated: Widget frontend\n```\n\n### 5. Edit Your Widget Code\n\n**You only need to edit these 2 files:**\n\n#### `server/tools/my_widget_tool.py` - Backend Logic\n\n```python\nfrom fastapps import BaseWidget, Field, ConfigDict\nfrom pydantic import BaseModel\nfrom typing import Dict, Any\n\nclass MyWidgetInput(BaseModel):\n    model_config = ConfigDict(populate_by_name=True)\n    name: str = Field(default=\"World\")\n\nclass MyWidgetTool(BaseWidget):\n    identifier = \"my-widget\"\n    title = \"My Widget\"\n    input_schema = MyWidgetInput\n    invoking = \"Processing...\"\n    invoked = \"Done!\"\n    \n    widget_csp = {\n        \"connect_domains\": [],      # APIs you'll call\n        \"resource_domains\": []      # Images/fonts you'll use\n    }\n    \n    async def execute(self, input_data: MyWidgetInput) -> Dict[str, Any]:\n        # Your logic here\n        return {\n            \"name\": input_data.name,\n            \"message\": f\"Hello, {input_data.name}!\"\n        }\n```\n\n#### `widgets/my-widget/index.jsx` - Frontend UI\n\n```jsx\nimport React from 'react';\nimport { useWidgetProps } from 'fastapps';\n\nexport default function MyWidget() {\n  const props = useWidgetProps();\n  \n  return (\n    <div style={{\n      padding: '40px',\n      textAlign: 'center',\n      background: '#4A90E2',\n      color: 'white',\n      borderRadius: '12px'\n    }}>\n      <h1>{props.message}</h1>\n      <p>Welcome, {props.name}!</p>\n    </div>\n  );\n}\n```\n\n**That's it! These are the only files you need to write.**\n\n### 6. Build Widgets\n\n```bash\nnpm run build\n```\n\n### 7. Start Development Server with Public Access\n\n**Option A: Using `fastapps dev` (Recommended)**\n\nThe easiest way to run and expose your server:\n\n```bash\nfastapps dev\n```\n\nOn first run, you'll be prompted for your ngrok auth token:\n- Get it free at: https://dashboard.ngrok.com/get-started/your-authtoken\n- Token is saved and won't be asked again\n\nYou'll see:\n```\n\ud83d\ude80 FastApps Development Server\n\u250c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u252c\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502 Local   \u2502 http://0.0.0.0:8001    \u2502\n\u2502 Public  \u2502 https://xyz.ngrok.io   \u2502\n\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2534\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n\n\ud83d\udce1 MCP Server Endpoint: https://xyz.ngrok.io\n```\n\nUse the public URL in ChatGPT Settings > Connectors.\n\n**Option B: Manual Setup**\n\n```bash\n# Start server\npython server/main.py\n\n# In a separate terminal, create tunnel\nngrok http 8001\n```\n\n---\n\n## What You Need to Know\n\n### Widget Structure\n\nEvery widget has **exactly 2 files you write**:\n\n1. **Python Tool** (`server/tools/*_tool.py`)\n   - Define inputs with Pydantic\n   - Write your logic in `execute()`\n   - Return data as a dictionary\n\n2. **React Component** (`widgets/*/index.jsx`)\n   - Get data with `useWidgetProps()`\n   - Render your UI\n   - Use inline styles\n\n**Everything else is automatic:**\n- Widget discovery\n- Registration\n- Build process\n- Server setup\n- Mounting logic\n\n### Input Schema\n\n```python\nfrom fastapps import Field, ConfigDict\nfrom pydantic import BaseModel\n\nclass MyInput(BaseModel):\n    model_config = ConfigDict(populate_by_name=True)\n    \n    name: str = Field(default=\"\", description=\"User's name\")\n    age: int = Field(default=0, ge=0, le=150)\n    email: str = Field(default=\"\", pattern=r'^[\\w\\.-]+@[\\w\\.-]+\\.\\w+$')\n```\n\n### CSP (Content Security Policy)\n\nAllow external resources:\n\n```python\nwidget_csp = {\n    \"connect_domains\": [\"https://api.example.com\"],     # For API calls\n    \"resource_domains\": [\"https://cdn.example.com\"]     # For images/fonts\n}\n```\n\n### React Hooks\n\n```jsx\nimport { useWidgetProps, useWidgetState, useOpenAiGlobal } from 'fastapps';\n\nfunction MyWidget() {\n  const props = useWidgetProps();              // Data from Python\n  const [state, setState] = useWidgetState({}); // Persistent state\n  const theme = useOpenAiGlobal('theme');      // ChatGPT theme\n  \n  return <div>{props.message}</div>;\n}\n```\n\n---\n\n## Documentation\n\n- **[Quick Start Guide](https://github.com/DooiLabs/FastApps/blob/main/docs/QUICKSTART.md)** - Detailed setup instructions\n- **[Tutorial](https://github.com/DooiLabs/FastApps/blob/main/docs/TUTORIAL.md)** - Step-by-step widget examples\n- **[Python API](https://github.com/DooiLabs/FastApps/blob/main/docs/PYTHON_API.md)** - Programmatic dev server control\n- **[API Reference](https://github.com/DooiLabs/FastApps/blob/main/docs/API.md)** - Complete API documentation\n- **[Examples](https://github.com/DooiLabs/FastApps/tree/main/examples)** - Real-world code examples\n\n---\n\n## CLI Commands\n\n```bash\n# Initialize new project\nfastapps init my-app\n\n# Create new widget (auto-generates both files)\nfastapps create mywidget\n\n# Start development server with ngrok tunnel\nfastapps dev\n\n# Start on custom port\nfastapps dev --port 8080\n\n# Reset ngrok auth token\nfastapps reset-token\n\n# View authentication guide\nfastapps auth-info\n```\n\n**Tip**: If `fastapps` command is not found, use:\n```bash\npython -m fastapps.cli.main <command>\n```\n\n---\n\n## Project Structure After `fastapps create`\n\nWhen you run `python -m fastapps.cli.main create my-widget`, you get:\n\n```\nmy-app/\n\u251c\u2500\u2500 server/\n\u2502   \u251c\u2500\u2500 __init__.py\n\u2502   \u251c\u2500\u2500 main.py                  # Already setup (no edits needed)\n\u2502   \u251c\u2500\u2500 tools/\n\u2502   \u2502   \u251c\u2500\u2500 __init__.py\n\u2502   \u2502   \u2514\u2500\u2500 my_widget_tool.py    # \u2190 Edit this: Your widget logic\n\u2502   \u2514\u2500\u2500 api/                     # (optional: for shared APIs)\n\u2502\n\u251c\u2500\u2500 widgets/\n\u2502   \u2514\u2500\u2500 my-widget/\n\u2502       \u2514\u2500\u2500 index.jsx            # \u2190 Edit this: Your UI\n\u2502\n\u251c\u2500\u2500 assets/                      # Auto-generated during build\n\u2502   \u251c\u2500\u2500 my-widget-HASH.html\n\u2502   \u2514\u2500\u2500 my-widget-HASH.js\n\u2502\n\u251c\u2500\u2500 requirements.txt             # Python dependencies\n\u251c\u2500\u2500 package.json                 # JavaScript dependencies\n\u2514\u2500\u2500 build-all.mts                # Auto-copied from fastapps\n```\n\n**You only edit the 2 files marked with \u2190**\n\n---\n\n## Key Features\n\n- **Zero Boilerplate** - Just write your widget code\n- **Auto-Discovery** - Widgets automatically registered\n- **Type-Safe** - Pydantic for Python, TypeScript for React\n- **CLI Tools** - Scaffold widgets instantly\n- **Python API** - Programmatic server control\n- **ngrok Integration** - Public URLs with one command\n- **React Hooks** - Modern React patterns via `fastapps`\n- **MCP Protocol** - Native ChatGPT integration\n\n---\n\n## Python API\n\nStart dev servers programmatically:\n\n```python\nfrom fastapps import start_dev_server\n\n# Simple usage\nstart_dev_server()\n\n# With configuration\nstart_dev_server(\n    port=8080,\n    auto_reload=True,\n    ngrok_token=\"your_token\"\n)\n\n# Get server info without starting\nfrom fastapps import get_server_info\ninfo = get_server_info(port=8001)\nprint(f\"Public URL: {info.public_url}\")\n```\n\nSee [Python API Documentation](./docs/PYTHON_API.md) for more details.\n\n---\n\n## Examples\n\n### Simple Widget\n\n```python\n# server/tools/hello_tool.py\nclass HelloTool(BaseWidget):\n    identifier = \"hello\"\n    title = \"Hello\"\n    input_schema = HelloInput\n    \n    async def execute(self, input_data):\n        return {\"message\": \"Hello World!\"}\n```\n\n```jsx\n// widgets/hello/index.jsx\nexport default function Hello() {\n  const props = useWidgetProps();\n  return <h1>{props.message}</h1>;\n}\n```\n\n### With API Call\n\n```python\nasync def execute(self, input_data):\n    async with httpx.AsyncClient() as client:\n        response = await client.get(\"https://api.example.com/data\")\n        data = response.json()\n    return {\"data\": data}\n```\n\n### With State\n\n```jsx\nfunction Counter() {\n  const [state, setState] = useWidgetState({ count: 0 });\n  return (\n    <button onClick={() => setState({ count: state.count + 1 })}>\n      Count: {state.count}\n    </button>\n  );\n}\n```\n\n### Development Server with ngrok (pyngrok)\n\n**Real-World Use Cases:**\n\n| Use Case | Scenario | Benefits |\n|----------|----------|----------|\n| \ud83e\udd16 **ChatGPT Development** | Develop ChatGPT custom actions locally | Test widgets in ChatGPT without deployment |\n| \ud83e\ude9d **Webhook Testing** | Test webhooks from Stripe, GitHub, Slack | Get real webhook events on localhost |\n| \ud83d\udc65 **Remote Collaboration** | Share your local dev server with team | Instant demos without pushing code |\n| \ud83d\udcf1 **Mobile Testing** | Test mobile apps against local backend | Access localhost from phone/tablet |\n| \ud83d\udd0c **API Integration** | Third-party APIs need public callback URLs | Receive OAuth callbacks locally |\n| \ud83c\udfe2 **Client Demos** | Show work-in-progress to clients | Professional public URL instantly |\n| \ud83c\udf93 **Workshops/Teaching** | Students access instructor's local server | Share examples in real-time |\n| \ud83c\udf10 **Cross-Browser Testing** | Test on BrowserStack, Sauce Labs | Cloud browsers access your localhost |\n| \ud83d\udd04 **CI/CD Preview** | Preview branches before deployment | Test PRs with temporary URLs |\n| \ud83d\udee0\ufe0f **IoT Development** | IoT devices callback to local server | Hardware talks to dev environment |\n\n#### Programmatic Start\n```python\nfrom fastapps import start_dev_server\n\n# Start with automatic ngrok tunnel\nstart_dev_server(port=8001)\n\n# With custom configuration\nstart_dev_server(\n    port=8080,\n    ngrok_token=\"your_token\",\n    auto_reload=True\n)\n```\n\n#### Get Server URLs for Testing\n```python\nfrom fastapps import get_server_info\n\n# Create tunnel and get URLs\ninfo = get_server_info(port=8001)\nprint(f\"Local: {info.local_url}\")\nprint(f\"Public: {info.public_url}\")\n\n# Use in integration tests\nimport requests\nresponse = requests.get(f\"{info.public_url}/health\")\n```\n\n#### Environment Variable Token\n```python\nimport os\nfrom fastapps import start_dev_server\n\n# Get token from environment (great for CI/CD)\ntoken = os.getenv(\"NGROK_TOKEN\")\nstart_dev_server(ngrok_token=token)\n```\n\n#### Error Handling\n```python\nfrom fastapps import start_dev_server, DevServerError, NgrokError\n\ntry:\n    start_dev_server(port=8001)\nexcept NgrokError as e:\n    print(f\"ngrok tunnel failed: {e}\")\nexcept DevServerError as e:\n    print(f\"Server error: {e}\")\n```\n\n#### Automation Script\n```python\n#!/usr/bin/env python3\nfrom fastapps import start_dev_server\nimport sys\n\nif __name__ == \"__main__\":\n    try:\n        print(\"\ud83d\ude80 Starting FastApps with ngrok...\")\n        start_dev_server(\n            port=8001,\n            auto_reload=True,\n            log_level=\"info\"\n        )\n    except KeyboardInterrupt:\n        print(\"\\n\u2705 Server stopped\")\n        sys.exit(0)\n```\n\n#### Real-World Example Scenarios\n\n**Scenario 1: ChatGPT Custom Action Development**\n```python\n# Start server for ChatGPT testing\nfrom fastapps import start_dev_server\n\n# Auto-reload when you edit widgets\nstart_dev_server(\n    port=8001,\n    auto_reload=True  # Restart on code changes\n)\n# Copy ngrok URL \u2192 ChatGPT Settings \u2192 Connectors \u2192 Add your URL\n# Test widgets live in ChatGPT while developing!\n```\n\n**Scenario 2: Webhook Testing (Stripe, GitHub, etc.)**\n```python\nfrom fastapps import get_server_info\n\n# Get public URL for webhook configuration\ninfo = get_server_info(port=8001)\nprint(f\"Configure webhook URL: {info.public_url}/webhooks\")\n\n# Add this URL to Stripe Dashboard \u2192 Webhooks\n# Receive real webhook events on your localhost!\n```\n\n**Scenario 3: Team Demo / Client Preview**\n```python\nfrom fastapps import start_dev_server\n\n# Share work-in-progress with team\nstart_dev_server(port=8001)\n\n# Send the ngrok URL to your team/client\n# They can access your local server instantly!\n# No deployment needed\n```\n\n**Scenario 4: Mobile App Testing**\n```python\nfrom fastapps import get_server_info\n\ninfo = get_server_info(port=8001)\n\n# Use public URL in your mobile app config\nprint(f\"API Base URL for mobile app: {info.public_url}\")\n\n# Test your iOS/Android app against local backend\n# No need for deployed staging server\n```\n\n**Scenario 5: OAuth Callback (Third-Party APIs)**\n```python\nfrom fastapps import start_dev_server\n\n# OAuth providers need public callback URL\nstart_dev_server(port=8001)\n\n# Register callback: https://your-ngrok-url.ngrok.io/auth/callback\n# Test OAuth flow locally:\n# 1. User clicks \"Login with Google\"\n# 2. Google redirects to your ngrok URL\n# 3. Your local server receives the callback\n```\n\n**Scenario 6: CI/CD Integration Testing**\n```python\n# .github/workflows/test.yml\nimport os\nfrom fastapps import start_dev_server\nimport threading\nimport requests\n\n# Start server in background\ndef run_server():\n    start_dev_server(\n        port=8001,\n        ngrok_token=os.getenv(\"NGROK_TOKEN\")\n    )\n\n# Run server in separate thread\nserver_thread = threading.Thread(target=run_server, daemon=True)\nserver_thread.start()\n\n# Run integration tests against public URL\n# Perfect for testing webhooks, OAuth, etc. in CI\n```\n\n**Scenario 7: IoT/Embedded Device Testing**\n```python\nfrom fastapps import get_server_info\n\n# IoT devices need to callback to your server\ninfo = get_server_info(port=8001)\n\n# Configure IoT device with this URL\nprint(f\"Configure device callback: {info.public_url}/iot/callback\")\n\n# Your Raspberry Pi, Arduino, etc. can now reach your localhost!\n```\n\n---\n\n## Troubleshooting\n\n**Widget not loading?**\n- Check `identifier` matches folder name\n- Rebuild: `npm run build`\n- Restart: `python server/main.py`\n\n**Import errors?**\n```bash\npip install --upgrade fastapps\nnpm install fastapps@latest\n```\n\n**Need help?** Check our [docs](https://github.com/DooiLabs/FastApps/tree/main/docs) or [open an issue](https://github.com/DooiLabs/FastApps/issues)\n\n---\n\n## Contributing\n\nWe welcome contributions! Please see our contributing guidelines:\n\n- **[Contributing Guide](https://github.com/DooiLabs/FastApps/blob/main/CONTRIBUTING.md)** - How to contribute to FastApps\n- **[Code Style Guide](https://github.com/DooiLabs/FastApps/blob/main/CODE_STYLE.md)** - Code formatting and style standards\n- **[GitHub Workflows](https://github.com/DooiLabs/FastApps/blob/main/.github/WORKFLOWS.md)** - CI/CD documentation\n\n### Quick Start for Contributors\n\n```bash\n# Fork and clone the repository\ngit clone https://github.com/YOUR_USERNAME/FastApps.git\ncd FastApps\n\n# Install development dependencies\npip install -e \".[dev]\"\n\n# Install pre-commit hooks\npip install pre-commit\npre-commit install\n\n# Make changes and ensure they pass checks\nblack .\nruff check --fix .\npytest\n\n# Submit a pull request\n```\n\n## License\n\nMIT \u00a9 FastApps Team\n\n## Links\n\n- **PyPI**: https://pypi.org/project/fastapps/\n- **ChatJS Hooks**: https://www.npmjs.com/package/fastapps\n- **GitHub**: https://github.com/DooiLabs/FastApps\n- **MCP Spec**: https://modelcontextprotocol.io/\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "A zero-boilerplate framework for building interactive ChatGPT widgets",
    "version": "1.1.1",
    "project_urls": {
        "Bug Reports": "https://github.com/DooiLabs/FastApps/issues",
        "Documentation": "https://www.fastapps.org/quickstart",
        "Homepage": "https://www.fastapps.org",
        "Repository": "https://github.com/DooiLabs/FastApps"
    },
    "split_keywords": [
        "chatgpt",
        " widgets",
        " mcp",
        " framework",
        " react"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "2b75973cd779ca620963f1aed5e78738f4b4910000b00e28153420a6cc115e45",
                "md5": "1b8f0effd4cbe71f81afc35fae130a99",
                "sha256": "657035b561bbf6b5f997eef5128e6b0c09ca44d21b48db161baae7d84fd2be8b"
            },
            "downloads": -1,
            "filename": "fastapps-1.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "1b8f0effd4cbe71f81afc35fae130a99",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.11",
            "size": 34542,
            "upload_time": "2025-10-18T06:50:06",
            "upload_time_iso_8601": "2025-10-18T06:50:06.251962Z",
            "url": "https://files.pythonhosted.org/packages/2b/75/973cd779ca620963f1aed5e78738f4b4910000b00e28153420a6cc115e45/fastapps-1.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "94f6d3e1a8cd349424657d9997d01afb49c703d8b07a4ac19d870f9978322ef4",
                "md5": "6d3c5ac85f1291ce4447aa5411f33f47",
                "sha256": "43fff0c71893be62a656aa33e2eb19e9a57d0040e319ce7d98ad0ab923d1e7f1"
            },
            "downloads": -1,
            "filename": "fastapps-1.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "6d3c5ac85f1291ce4447aa5411f33f47",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.11",
            "size": 276147,
            "upload_time": "2025-10-18T06:50:07",
            "upload_time_iso_8601": "2025-10-18T06:50:07.657351Z",
            "url": "https://files.pythonhosted.org/packages/94/f6/d3e1a8cd349424657d9997d01afb49c703d8b07a4ac19d870f9978322ef4/fastapps-1.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-18 06:50:07",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "DooiLabs",
    "github_project": "FastApps",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "fastapps"
}
        
Elapsed time: 1.19620s