Metadata-Version: 2.4
Name: livefolio
Version: 0.2.0
Summary: Python SDK for the LiveFolio API — create, update, and manage AI-generated interactive HTML documents.
Author-email: LiveFolio <hello@livefolio.cloud>
License: MIT
Project-URL: Homepage, https://livefolio.cloud
Project-URL: Documentation, https://livefolio.cloud/docs
Project-URL: Repository, https://github.com/LiveFolio-Cloud/LiveFolio-oss
Keywords: livefolio,ai,html,documents,folios,mcp
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: httpx>=0.25.0

# LiveFolio Python SDK

`pip install livefolio` -- the official Python client for the [LiveFolio](https://livefolio.cloud) API. Create, version, and share AI-generated interactive HTML documents ("folios") from any Python script or agent.

## Install

```bash
pip install livefolio
```

Requires Python 3.9+ and [httpx](https://www.python-httpx.org/).

## Quickstart

```python
from livefolio import LiveFolio

client = LiveFolio(api_key="lf_live_abc123")

# Create a new folio
folio = client.create_folio(
    title="Quarterly Review",
    initial_html="<h1>Q3 Highlights</h1><p>Revenue up 24%</p>",
    project_mode="deck",
    description="Executive summary deck for Q3 board meeting",
)

print(f"Created: {folio.url}")

# List all your folios
for f in client.list_folios():
    print(f"{f.title} — {f.version_count} versions")

# Get full details (source, history, comments)
detail = client.get_folio(folio.project_id)
print(detail.current_files["index.html"])

# Update files
updated = client.update_folio(
    folio.project_id,
    updated_files={"index.html": "<h1>Q3 Highlights</h1><p>Revenue up 31%</p>"},
    change_message="Corrected revenue figure",
)
print(f"Now at: {updated.url}")
```

## API Reference

### `LiveFolio(api_key, base_url="https://livefolio.cloud")`

| Method | Returns | Description |
|---|---|---|
| `list_folios()` | `list[ProjectSummary]` | List all accessible folios |
| `get_folio(folio_id)` | `ProjectDetail` | Get full source, history, and comments |
| `create_folio(title, initial_html, **kwargs)` | `ProjectDetail` | Publish a new folio |
| `update_folio(folio_id, updated_files=None, change_message=None, **kwargs)` | `ProjectDetail` | Update files, metadata, or sharing settings |

### `create_folio` keyword arguments

| Argument | Type | Default | Description |
|---|---|---|---|
| `description` | `str` | `None` | Short description |
| `project_mode` | `str` | `None` | `deck`, `document`, `spreadsheet`, or `dashboard` |
| `design_preferences` | `DesignPreferences` | `None` | Theme, typography, palette, custom colors |
| `reference_files` | `list[ReferenceFile]` | `None` | Source documents for AI context |
| `is_private` | `bool` | `False` | Require access key to view |
| `access_key` | `str` | `None` | Password if private |
| `allow_comments` | `bool` | `True` | Allow guest comments |
| `presentation_mode_only` | `bool` | `False` | Fullscreen presentation mode |
| `status` | `str` | `"draft"` | `draft` or `published` |

### `update_folio` keyword arguments

Same metadata fields as `create_folio`, plus:

| Argument | Type | Default | Description |
|---|---|---|---|
| `updated_files` | `dict[str, str]` | `None` | Filename to content map (merged with existing) |
| `change_message` | `str` | `None` | Human-readable summary of changes |

### Types

#### `ProjectSummary`

| Field | Type |
|---|---|
| `project_id` | `str` |
| `title` | `str` |
| `description` | `str` |
| `file_count` | `int` |
| `version_count` | `int` |
| `open_comments` | `int` |
| `updated_at` | `str` |
| `share_url` | `str` |
| `studio_url` | `str` |
| `url` | `str` (property) |

#### `ProjectDetail`

All `ProjectSummary` fields, plus:

| Field | Type |
|---|---|
| `project_mode` | `str` |
| `design_preferences` | `dict` |
| `current_files` | `dict[str, str]` |
| `version_history` | `list[dict]` |
| `open_comments` | `list[dict]` |
| `chats` | `list[dict]` |
| `is_private` | `bool` |
| `access_key` | `str` or `None` |
| `allow_comments` | `bool` |
| `presentation_mode_only` | `bool` |
| `status` | `str` |
| `created_at` | `str` |
| `updated_at` | `str` |

#### `DesignPreferences`

| Field | Type |
|---|---|
| `theme` | `str` or `None` |
| `typography` | `str` or `None` |
| `palette` | `str` or `None` |
| `custom_colors` | `dict` or `None` |
| `custom_guidelines` | `str` or `None` |
| `libraries` | `list[str]` or `None` |

#### `ReferenceFile`

| Field | Type |
|---|---|
| `filename` | `str` |
| `content` | `str` |
| `size` | `int` or `None` |

### Exceptions

| Class | HTTP Status |
|---|---|
| `LiveFolioError` | Base exception |
| `LiveFolioAuthError` | 401 |
| `LiveFolioNotFoundError` | 404 |
| `LiveFolioConflictError` | 409 |
| `LiveFolioServerError` | 5xx |

### Context Manager

```python
with LiveFolio(api_key="lf_live_abc123") as client:
    folios = client.list_folios()
# Client is closed automatically
```

### Self-Hosted

```python
client = LiveFolio(
    api_key="my-local-key",
    base_url="http://localhost:3000",
)
```

## The Aspirational Syntax

One day, when multi-modal agents can read the DOM, the workflow will be:

```
$ pip install livefolio
$ python
>>> import livefolio as lf
>>> folio = lf.create("Year in Review", project_mode="deck")
>>> folio.save()
```

Today, you pass HTML directly. Tomorrow, the SDK will handle that too.

## License

MIT
