> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fastapps.org/llms.txt
> Use this file to discover all available pages before exploring further.

# FastApps Quick Start

> Spin up your first FastApps project and run a widget in under five minutes.

## Quick Start

Get started with FastApps in just 3 steps:

```bash theme={null}
# 0. Install using uv
uv tool install fastapps
uv tool install --upgrade fastapps # Update to the latest version

# 1. Create project
fastapps init my-app

# 2. Run
cd my-app
fastapps dev
```

That's it! Your example widget is now running at a public URL. The public URL is temporary, and is issued with [cloudflared](https://github.com/cloudflare/cloudflared) behind the scenes. You can view your widget at `https://<your-subdomain>.trycloudflare.com/mcp` and add it to ChatGPT under "Settings > Connectors".

***

## Project Structure

When you run `fastapps init my-app`, this structure is generated:

```
my-app/
├── server/
│   ├── __init__.py              # Empty file
│   ├── main.py                  # Auto-discovery server (pre-configured)
│   └── tools/
│       ├── __init__.py          # Empty file
│       └── my_widget_tool.py    # ← YOUR CODE: Widget backend
│
├── widgets/
│   └── my-widget/
│       └── index.jsx            # ← YOUR CODE: Widget frontend
│
├── requirements.txt
└── package.json
```

***

## Creating More Widgets

You can create additional widgets anytime:

```bash theme={null}
fastapps create another-widget
```

***

## Edit Your Widget Code

You only need to edit these 2 files:

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

```python theme={null}
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 theme={null}
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.**

***

## Test Your App

With your app running (`fastapps dev`) and public URL is ready, \
you have two options to test your widget.

**Option A: Test on MCPJam Inspector**

Add your public URL + /mcp to ChatGPT : \
Example URL : `https://<your-subdomain>.trycloudflare.com/mcp`

```bash theme={null}
npx @mcpjam/inspector@latest
```

Test your app with:

* Tools tab: Deterministically call tools and view your UI
* LLM playground: See your Apps SDK UI in a chat environment

<img src="https://mintcdn.com/dooilabs/sJnzWTeg26dJDtGi/images/image.png?fit=max&auto=format&n=sJnzWTeg26dJDtGi&q=85&s=de5ca0eb60b708787e629b48e5f64c70" alt="image.png" width="3020" height="1636" data-path="images/image.png" />

**Option B: Test on ChatGPT**

Add your public URL + /mcp to ChatGPT's "Settings > Connectors" : \
Example URL : `https://<your-subdomain>.trycloudflare.com/mcp`

## ✅ Ready for Next Steps

* Follow the Tutorial for a guided build
* Explore Widgets and Tools to customize logic and UI
* Connect APIs or state management when you need more power
