@bffless/claude-skills 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +22 -0
- package/.claude-plugin/plugin.json +13 -0
- package/README.md +94 -0
- package/package.json +23 -0
- package/skills/authorization/SKILL.md +59 -0
- package/skills/bffless/SKILL.md +158 -0
- package/skills/chat/SKILL.md +196 -0
- package/skills/pipelines/SKILL.md +81 -0
- package/skills/proxy-rules/SKILL.md +83 -0
- package/skills/repository/SKILL.md +64 -0
- package/skills/share-links/SKILL.md +53 -0
- package/skills/traffic-splitting/SKILL.md +63 -0
- package/skills/upload-artifact/SKILL.md +195 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bffless",
|
|
3
|
+
"owner": {
|
|
4
|
+
"name": "BFFless"
|
|
5
|
+
},
|
|
6
|
+
"metadata": {
|
|
7
|
+
"description": "BFFless platform skills for Claude Code",
|
|
8
|
+
"version": "1.0.0"
|
|
9
|
+
},
|
|
10
|
+
"plugins": [
|
|
11
|
+
{
|
|
12
|
+
"name": "bffless",
|
|
13
|
+
"source": {
|
|
14
|
+
"source": "npm",
|
|
15
|
+
"package": "@bffless/claude-skills",
|
|
16
|
+
"version": "^1.0.0"
|
|
17
|
+
},
|
|
18
|
+
"description": "BFFless platform skills — deployments, pipelines, proxy rules, chat, traffic splitting, and more",
|
|
19
|
+
"category": "platform"
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "bffless",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "BFFless platform skills for Claude Code — deployments, pipelines, proxy rules, chat, traffic splitting, and more",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "BFFless"
|
|
7
|
+
},
|
|
8
|
+
"homepage": "https://docs.bffless.app",
|
|
9
|
+
"repository": "https://github.com/bffless/claude-skills",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"keywords": ["bffless", "static-hosting", "deployments", "pipelines", "chat"],
|
|
12
|
+
"skills": ["./skills/"]
|
|
13
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# @bffless/claude-skills
|
|
2
|
+
|
|
3
|
+
Claude Code plugin with platform skills for [BFFless](https://bffless.app) — a self-hosted static asset hosting platform with AI-powered pipelines.
|
|
4
|
+
|
|
5
|
+
These skills give Claude Code domain knowledge about BFFless features so it can help you build, deploy, and configure your projects.
|
|
6
|
+
|
|
7
|
+
## Skills Included
|
|
8
|
+
|
|
9
|
+
| Skill | Description |
|
|
10
|
+
| --------------------- | -------------------------------------------------------- |
|
|
11
|
+
| **authorization** | Global and project roles, API keys, permission model |
|
|
12
|
+
| **bffless** | Platform overview, key concepts, and feature summary |
|
|
13
|
+
| **chat** | AI chat widget/full-page, skills, streaming, persistence |
|
|
14
|
+
| **pipelines** | Backend automation with handler chains and DB Records |
|
|
15
|
+
| **proxy-rules** | Forward requests to backend APIs, eliminate CORS |
|
|
16
|
+
| **repository** | Deployments, aliases, content browser, rollback |
|
|
17
|
+
| **share-links** | Token-based sharing for private deployments |
|
|
18
|
+
| **traffic-splitting** | A/B testing, canary deployments, weighted routing |
|
|
19
|
+
| **upload-artifact** | GitHub Action for uploading builds to BFFless |
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
### Via Claude Code Plugin Marketplace
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
# Add the marketplace
|
|
27
|
+
/plugin marketplace add bffless/claude-skills
|
|
28
|
+
|
|
29
|
+
# Install the plugin
|
|
30
|
+
/plugin install bffless
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### Via CLI
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
claude plugin install bffless --scope user
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Local Development
|
|
40
|
+
|
|
41
|
+
If you're contributing or want to use a local copy:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone https://github.com/bffless/claude-skills.git
|
|
45
|
+
claude --plugin-dir ./claude-skills
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Usage
|
|
49
|
+
|
|
50
|
+
Once installed, Claude Code automatically uses these skills when you ask about BFFless features. For example:
|
|
51
|
+
|
|
52
|
+
- "Set up a proxy rule to forward /api requests to my backend"
|
|
53
|
+
- "Add AI chat to my site with streaming"
|
|
54
|
+
- "Configure traffic splitting for a canary deployment"
|
|
55
|
+
- "Set up the upload-artifact GitHub Action for my repo"
|
|
56
|
+
|
|
57
|
+
Skills are invoked by name with the `bffless` namespace:
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
/bffless:chat
|
|
61
|
+
/bffless:proxy-rules
|
|
62
|
+
/bffless:pipelines
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## BFFless Pipeline Skills vs Claude Code Skills
|
|
66
|
+
|
|
67
|
+
This package contains **Claude Code plugin skills** — they teach Claude about the BFFless platform so it can assist you as a developer.
|
|
68
|
+
|
|
69
|
+
These are different from **BFFless pipeline skills**, which are markdown files you create in your own project's `.bffless/skills/` directory. Pipeline skills are deployed with your site and loaded by the AI chat handler at runtime to give your chatbot domain-specific knowledge.
|
|
70
|
+
|
|
71
|
+
| | Claude Code Skills (this package) | Pipeline Skills (your project) |
|
|
72
|
+
| ------------ | --------------------------------------- | --------------------------------------- |
|
|
73
|
+
| **Purpose** | Help Claude help _you_ build on BFFless | Give _your chatbot_ domain knowledge |
|
|
74
|
+
| **Location** | Installed as Claude Code plugin | `.bffless/skills/` in your project repo |
|
|
75
|
+
| **Used by** | Claude Code (your dev tool) | BFFless AI chat handler (your users) |
|
|
76
|
+
| **Deployed** | npm install | `bffless/upload-artifact` GitHub Action |
|
|
77
|
+
|
|
78
|
+
## Documentation
|
|
79
|
+
|
|
80
|
+
- [BFFless Docs](https://docs.bffless.app)
|
|
81
|
+
- [Getting Started](https://docs.bffless.app/getting-started/quickstart)
|
|
82
|
+
- [Chat Feature](https://docs.bffless.app/features/chat/)
|
|
83
|
+
- [Pipelines](https://docs.bffless.app/features/pipelines/)
|
|
84
|
+
|
|
85
|
+
## Contributing
|
|
86
|
+
|
|
87
|
+
1. Fork this repo
|
|
88
|
+
2. Add or update skills in `skills/<skill-name>/SKILL.md`
|
|
89
|
+
3. Each skill needs YAML frontmatter with `name` and `description`
|
|
90
|
+
4. Open a PR — CI validates all skills automatically
|
|
91
|
+
|
|
92
|
+
## License
|
|
93
|
+
|
|
94
|
+
MIT
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bffless/claude-skills",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Claude Code plugin with BFFless platform skills",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"claude-code-plugin",
|
|
7
|
+
"bffless",
|
|
8
|
+
"skills",
|
|
9
|
+
"ai",
|
|
10
|
+
"static-hosting"
|
|
11
|
+
],
|
|
12
|
+
"author": "BFFless",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"homepage": "https://docs.bffless.app",
|
|
15
|
+
"repository": {
|
|
16
|
+
"type": "git",
|
|
17
|
+
"url": "https://github.com/bffless/claude-skills"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
".claude-plugin/",
|
|
21
|
+
"skills/"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: authorization
|
|
3
|
+
description: Two-level permission system with global and project roles
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Authorization
|
|
7
|
+
|
|
8
|
+
**Docs**: https://docs.bffless.app/features/authorization/
|
|
9
|
+
|
|
10
|
+
BFFless uses a two-level permission system: global roles for workspace-wide access and project roles for fine-grained control.
|
|
11
|
+
|
|
12
|
+
## Global Roles
|
|
13
|
+
|
|
14
|
+
| Role | Capabilities |
|
|
15
|
+
|------|-------------|
|
|
16
|
+
| **Admin** | Full workspace access, manage users, billing, settings |
|
|
17
|
+
| **User** | Create projects, manage own content |
|
|
18
|
+
| **Member** | View-only access, participate in assigned projects |
|
|
19
|
+
|
|
20
|
+
## Project Roles
|
|
21
|
+
|
|
22
|
+
| Role | Capabilities |
|
|
23
|
+
|------|-------------|
|
|
24
|
+
| **Owner** | Full control, delete project, transfer ownership |
|
|
25
|
+
| **Admin** | Manage settings, users, deployments |
|
|
26
|
+
| **Contributor** | Deploy, create aliases, modify content |
|
|
27
|
+
| **Viewer** | Read-only access to project and deployments |
|
|
28
|
+
|
|
29
|
+
## Permission Sources
|
|
30
|
+
|
|
31
|
+
Users can receive project access from multiple sources:
|
|
32
|
+
|
|
33
|
+
1. **Direct assignment**: Explicitly added to project
|
|
34
|
+
2. **Group membership**: Inherited from user group
|
|
35
|
+
3. **Effective role**: Highest permission wins when multiple sources exist
|
|
36
|
+
|
|
37
|
+
## API Keys
|
|
38
|
+
|
|
39
|
+
Two types of API keys for automation:
|
|
40
|
+
|
|
41
|
+
- **Global keys**: Workspace-wide access, use the creator's permissions
|
|
42
|
+
- **Project keys**: Scoped to single project, specify exact role
|
|
43
|
+
|
|
44
|
+
Best practice: Use project-scoped keys with minimum required permissions.
|
|
45
|
+
|
|
46
|
+
## Common Patterns
|
|
47
|
+
|
|
48
|
+
**External contractors**: Add as Member globally, Contributor on specific projects
|
|
49
|
+
|
|
50
|
+
**CI/CD pipelines**: Create project API key with Contributor role
|
|
51
|
+
|
|
52
|
+
**Client preview access**: Use share links instead of user accounts
|
|
53
|
+
|
|
54
|
+
## Troubleshooting
|
|
55
|
+
|
|
56
|
+
**"Permission denied" errors?**
|
|
57
|
+
- Check effective role (may be inherited from group)
|
|
58
|
+
- Verify API key scope matches the project
|
|
59
|
+
- Global Members need explicit project assignment
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bffless
|
|
3
|
+
description: Knowledge about BFFless platform, features, and setup
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# BFFless Platform Guide
|
|
7
|
+
|
|
8
|
+
BFFless is a self-hosted static asset hosting platform designed for modern frontend deployments. It provides a Backend-for-Frontend (BFF) layer without requiring you to write backend code.
|
|
9
|
+
|
|
10
|
+
## What is BFFless?
|
|
11
|
+
|
|
12
|
+
BFFless is a platform that:
|
|
13
|
+
|
|
14
|
+
- **Hosts static assets** from your CI/CD pipeline (React, Vue, Angular, etc.)
|
|
15
|
+
- **Provides AI-powered pipelines** for backend automation without writing code
|
|
16
|
+
- **Manages deployments** with aliases like `production`, `staging`, `preview`
|
|
17
|
+
- **Handles custom domains** with automatic SSL via Let's Encrypt
|
|
18
|
+
- **Enables traffic splitting** for A/B testing and canary deployments
|
|
19
|
+
- **Offers proxy rules** to forward requests to backend APIs
|
|
20
|
+
|
|
21
|
+
### Key Concepts
|
|
22
|
+
|
|
23
|
+
| Concept | Description |
|
|
24
|
+
| -------------- | --------------------------------------------------------------- |
|
|
25
|
+
| **Deployment** | A snapshot of your build artifacts at a specific commit SHA |
|
|
26
|
+
| **Alias** | A named pointer to a deployment (e.g., `production` → `abc123`) |
|
|
27
|
+
| **Proxy Rule** | Routes requests to external APIs or AI pipelines |
|
|
28
|
+
| **Pipeline** | Chain of handlers that process requests (AI, transform, proxy) |
|
|
29
|
+
| **Skill** | Markdown files that give AI agents specialized knowledge |
|
|
30
|
+
|
|
31
|
+
## Setting Up Proxy Rules
|
|
32
|
+
|
|
33
|
+
Proxy rules let you route requests through BFFless to backend APIs or AI pipelines.
|
|
34
|
+
|
|
35
|
+
### Creating a Proxy Rule
|
|
36
|
+
|
|
37
|
+
1. Go to **Project Settings** → **Proxy Rules**
|
|
38
|
+
2. Click **Add Rule**
|
|
39
|
+
3. Configure the rule:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
Path Pattern: /api/*
|
|
43
|
+
Target URL: https://your-backend.com
|
|
44
|
+
Strip Prefix: true (removes /api from forwarded requests)
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Rule Types
|
|
48
|
+
|
|
49
|
+
| Type | Use Case |
|
|
50
|
+
| -------------------- | ---------------------------------------- |
|
|
51
|
+
| **External Proxy** | Forward to external APIs (REST, GraphQL) |
|
|
52
|
+
| **Pipeline** | Process with AI handlers |
|
|
53
|
+
| **Internal Rewrite** | Serve different static files |
|
|
54
|
+
|
|
55
|
+
### Common Patterns
|
|
56
|
+
|
|
57
|
+
**API Gateway:**
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
/api/* → https://api.example.com/*
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**AI Chat Endpoint:**
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
/api/chat → Pipeline with AI handler
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
**Microservices:**
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
/api/users/* → https://users-service.internal
|
|
73
|
+
/api/orders/* → https://orders-service.internal
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Traffic Splitting
|
|
77
|
+
|
|
78
|
+
Traffic splitting distributes requests across multiple deployment aliases for A/B testing or gradual rollouts.
|
|
79
|
+
|
|
80
|
+
### How It Works
|
|
81
|
+
|
|
82
|
+
1. Configure weights per alias (e.g., 90% production, 10% canary)
|
|
83
|
+
2. First-time visitors get randomly assigned based on weights
|
|
84
|
+
3. A cookie (`__bffless_variant`) maintains sticky sessions
|
|
85
|
+
4. Users see consistent experience on return visits
|
|
86
|
+
|
|
87
|
+
### Setting Up Traffic Splitting
|
|
88
|
+
|
|
89
|
+
1. Go to **Domains** → Select your domain
|
|
90
|
+
2. Click **Traffic Splitting**
|
|
91
|
+
3. Add aliases with weights:
|
|
92
|
+
|
|
93
|
+
| Alias | Weight |
|
|
94
|
+
| ---------- | ------ |
|
|
95
|
+
| production | 90% |
|
|
96
|
+
| canary | 10% |
|
|
97
|
+
|
|
98
|
+
4. Save changes
|
|
99
|
+
|
|
100
|
+
### Use Cases
|
|
101
|
+
|
|
102
|
+
- **A/B Testing**: Compare two versions of your app
|
|
103
|
+
- **Canary Deployments**: Gradually roll out new features
|
|
104
|
+
- **Blue/Green**: Instant switch between deployments
|
|
105
|
+
- **Feature Flags**: Route specific traffic to experimental builds
|
|
106
|
+
|
|
107
|
+
### Best Practices
|
|
108
|
+
|
|
109
|
+
- Start with small percentages for new deployments (5-10%)
|
|
110
|
+
- Monitor error rates before increasing traffic
|
|
111
|
+
- Use the `X-Variant` header to track which variant served the request
|
|
112
|
+
- Cookie duration is configurable (default: 24 hours)
|
|
113
|
+
|
|
114
|
+
## Pipelines and AI Handlers
|
|
115
|
+
|
|
116
|
+
Pipelines let you create backend logic without writing code.
|
|
117
|
+
|
|
118
|
+
### Pipeline Structure
|
|
119
|
+
|
|
120
|
+
A pipeline is a chain of steps:
|
|
121
|
+
|
|
122
|
+
```
|
|
123
|
+
Request → Step 1 → Step 2 → Step 3 → Response
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### AI Handler
|
|
127
|
+
|
|
128
|
+
The AI handler uses LLMs to process requests:
|
|
129
|
+
|
|
130
|
+
- Configure system prompts
|
|
131
|
+
- Set model and temperature
|
|
132
|
+
- Enable skills for specialized knowledge
|
|
133
|
+
- Stream responses for chat interfaces
|
|
134
|
+
|
|
135
|
+
### Example: Chat API
|
|
136
|
+
|
|
137
|
+
1. Create a pipeline with an AI handler
|
|
138
|
+
2. Configure:
|
|
139
|
+
- Model: `gpt-4` or `claude-3`
|
|
140
|
+
- System Prompt: Your assistant instructions
|
|
141
|
+
- Skills: Enable relevant skills
|
|
142
|
+
3. Create a proxy rule pointing to the pipeline
|
|
143
|
+
4. Your frontend calls `/api/chat` and gets AI responses
|
|
144
|
+
|
|
145
|
+
## GitHub Action Integration
|
|
146
|
+
|
|
147
|
+
Upload builds automatically from CI/CD:
|
|
148
|
+
|
|
149
|
+
```yaml
|
|
150
|
+
- uses: bffless/upload-artifact@v1
|
|
151
|
+
with:
|
|
152
|
+
path: dist
|
|
153
|
+
api-url: ${{ vars.BFFLESS_URL }}
|
|
154
|
+
api-key: ${{ secrets.BFFLESS_KEY }}
|
|
155
|
+
alias: production
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
This uploads your build and updates the `production` alias to point to it.
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: chat
|
|
3
|
+
description: Adding AI chat to a site with full page or popup widget layouts, skills, streaming, and message persistence
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Chat
|
|
7
|
+
|
|
8
|
+
**Docs**: https://docs.bffless.app/features/chat/
|
|
9
|
+
|
|
10
|
+
Add an AI-powered chat experience to any site — no backend code required. Choose between a full page chat interface or a popup widget, give your chatbot domain knowledge with skills, and let BFFless handle streaming, persistence, and deployment.
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
BFFless Chat provides:
|
|
15
|
+
|
|
16
|
+
- **No backend code** — configure everything through the admin UI
|
|
17
|
+
- **Streaming responses** — real-time token-by-token output via Server-Sent Events
|
|
18
|
+
- **Skills** — domain-specific knowledge from markdown files deployed with your site
|
|
19
|
+
- **Message persistence** — conversations and messages saved automatically to DB Records
|
|
20
|
+
- **A/B testable** — combine with traffic splitting to test different skills or prompts
|
|
21
|
+
- **Two layouts** — full page chat or floating popup widget
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
### 1. Generate a Chat Schema
|
|
26
|
+
|
|
27
|
+
1. Go to **Pipelines → DB Records**
|
|
28
|
+
2. Click **Generate Schema**
|
|
29
|
+
3. Select **Chat Schema**
|
|
30
|
+
4. Enter a name (e.g., `support`)
|
|
31
|
+
5. Choose a scope:
|
|
32
|
+
- **User-scoped** — conversations tied to authenticated users
|
|
33
|
+
- **Guest-scoped** — conversations accessible without authentication
|
|
34
|
+
6. Click **Generate**
|
|
35
|
+
|
|
36
|
+
This creates:
|
|
37
|
+
- A `{name}_conversations` DB Record for conversation metadata
|
|
38
|
+
- A `{name}_messages` DB Record for individual messages
|
|
39
|
+
- A pipeline with a `POST /api/chat` endpoint pre-configured with the AI handler
|
|
40
|
+
|
|
41
|
+
### 2. Configure an AI Provider
|
|
42
|
+
|
|
43
|
+
1. Navigate to **Settings → AI**
|
|
44
|
+
2. Select a provider (OpenAI, Anthropic, or Google AI)
|
|
45
|
+
3. Enter your API key
|
|
46
|
+
4. Choose a default model
|
|
47
|
+
5. Click **Test Connection** to verify
|
|
48
|
+
6. Save
|
|
49
|
+
|
|
50
|
+
### 3. Connect Your Frontend
|
|
51
|
+
|
|
52
|
+
Use the AI SDK's `useChat` hook:
|
|
53
|
+
|
|
54
|
+
```tsx
|
|
55
|
+
import { useChat } from '@ai-sdk/react';
|
|
56
|
+
|
|
57
|
+
function Chat() {
|
|
58
|
+
const { messages, input, handleInputChange, handleSubmit, status } = useChat({
|
|
59
|
+
api: '/api/chat',
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
return (
|
|
63
|
+
<div>
|
|
64
|
+
{messages.map((m) => (
|
|
65
|
+
<div key={m.id}>
|
|
66
|
+
<strong>{m.role}:</strong> {m.parts.map(p => p.text).join('')}
|
|
67
|
+
</div>
|
|
68
|
+
))}
|
|
69
|
+
<form onSubmit={handleSubmit}>
|
|
70
|
+
<input value={input} onChange={handleInputChange} placeholder="Type a message..." />
|
|
71
|
+
<button type="submit" disabled={status === 'streaming'}>Send</button>
|
|
72
|
+
</form>
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 4. Deploy
|
|
79
|
+
|
|
80
|
+
Push your code to GitHub and deploy with the `bffless/upload-artifact` GitHub Action. Your chat endpoint is live as soon as the deployment completes.
|
|
81
|
+
|
|
82
|
+
## Chat Layouts
|
|
83
|
+
|
|
84
|
+
### Full Page Chat
|
|
85
|
+
|
|
86
|
+
A standalone chat page that takes over the full viewport. Includes suggested prompts, real-time streaming with markdown rendering, and a clean conversational UI.
|
|
87
|
+
|
|
88
|
+
Best for: dedicated support pages, knowledge base assistants, internal tools.
|
|
89
|
+
|
|
90
|
+
### Popup Widget
|
|
91
|
+
|
|
92
|
+
A floating chat bubble that opens a slide-up chat panel. Users can start a new conversation or close the widget without losing context. The widget stays accessible on any page.
|
|
93
|
+
|
|
94
|
+
Best for: landing pages, documentation sites, e-commerce — anywhere you want chat available without dedicating a full page.
|
|
95
|
+
|
|
96
|
+
## Skills
|
|
97
|
+
|
|
98
|
+
Skills are markdown files that give your chatbot domain-specific knowledge. Deploy them alongside your site and the AI loads relevant skills on-demand during conversations.
|
|
99
|
+
|
|
100
|
+
Skills are **versioned with each deployment** — when an alias points to a commit, the skills for that commit are used. This makes them git-managed, rollback-safe, and A/B testable with traffic splitting.
|
|
101
|
+
|
|
102
|
+
### Creating a Skill
|
|
103
|
+
|
|
104
|
+
Add a `SKILL.md` file to `.bffless/skills/<skill-name>/`:
|
|
105
|
+
|
|
106
|
+
```markdown
|
|
107
|
+
---
|
|
108
|
+
name: pricing-faq
|
|
109
|
+
description: Answer questions about pricing, plans, and billing
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
# Pricing FAQ
|
|
113
|
+
|
|
114
|
+
(Your knowledge content here in markdown)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Deploying Skills
|
|
118
|
+
|
|
119
|
+
Upload skills alongside your build artifacts:
|
|
120
|
+
|
|
121
|
+
```yaml
|
|
122
|
+
- name: Deploy build
|
|
123
|
+
uses: bffless/upload-artifact@v1
|
|
124
|
+
with:
|
|
125
|
+
source: dist
|
|
126
|
+
|
|
127
|
+
- name: Deploy skills
|
|
128
|
+
uses: bffless/upload-artifact@v1
|
|
129
|
+
with:
|
|
130
|
+
source: .bffless
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Configuring Skills in Pipelines
|
|
134
|
+
|
|
135
|
+
Set the skills mode in the AI handler configuration:
|
|
136
|
+
|
|
137
|
+
| Mode | Description |
|
|
138
|
+
|------|-------------|
|
|
139
|
+
| **None** | Disable all skills (default) |
|
|
140
|
+
| **All** | Enable all uploaded skills |
|
|
141
|
+
| **Selected** | Enable only specific skills by name |
|
|
142
|
+
|
|
143
|
+
## Message Persistence
|
|
144
|
+
|
|
145
|
+
When enabled, conversations and messages are automatically saved to DB Records. The handler manages:
|
|
146
|
+
|
|
147
|
+
- **Conversations**: chat_id, message_count, total_tokens, model
|
|
148
|
+
- **Messages**: conversation_id, role, content, tokens_used
|
|
149
|
+
|
|
150
|
+
Message persistence is optional — for simple use cases, skip it entirely and chat works without any database configuration.
|
|
151
|
+
|
|
152
|
+
## Configuration
|
|
153
|
+
|
|
154
|
+
Key settings for the AI chat handler:
|
|
155
|
+
|
|
156
|
+
| Setting | Description | Options / Default |
|
|
157
|
+
|---------|-------------|-------------------|
|
|
158
|
+
| **Mode** | Chat or Completion | `chat`, `completion` |
|
|
159
|
+
| **Provider** | AI provider | `openai`, `anthropic`, `google` |
|
|
160
|
+
| **Model** | Specific model | Provider-dependent |
|
|
161
|
+
| **System Prompt** | Instructions for the AI | Free-text |
|
|
162
|
+
| **Response Format** | Stream or JSON | `stream`, `message` |
|
|
163
|
+
| **Skills Mode** | Which skills to enable | `none`, `all`, `selected` |
|
|
164
|
+
| **Temperature** | Response creativity | `0` – `2` (default: `0.7`) |
|
|
165
|
+
| **Max Tokens** | Maximum output length | `256` – `100000` (default: `4096`) |
|
|
166
|
+
| **Max History** | Messages in context | `0` – `200` (default: `50`) |
|
|
167
|
+
|
|
168
|
+
## Supported Providers
|
|
169
|
+
|
|
170
|
+
| Provider | Models | Default |
|
|
171
|
+
|----------|--------|---------|
|
|
172
|
+
| OpenAI | gpt-4o, gpt-4-turbo, gpt-4, gpt-4o-mini, gpt-3.5-turbo | gpt-4o |
|
|
173
|
+
| Anthropic | claude-opus-4-6, claude-sonnet-4-6, claude-haiku-4-5 | claude-sonnet-4-6 |
|
|
174
|
+
| Google AI | gemini-1.5-pro, gemini-1.5-flash, gemini-1.5-flash-8b | gemini-1.5-pro |
|
|
175
|
+
|
|
176
|
+
## Demo
|
|
177
|
+
|
|
178
|
+
- Full page chat: https://chat.docs.bffless.app/
|
|
179
|
+
- Popup widget: https://chat.docs.bffless.app/popup/
|
|
180
|
+
- Source code: https://github.com/bffless/demo-chat
|
|
181
|
+
|
|
182
|
+
## Troubleshooting
|
|
183
|
+
|
|
184
|
+
**Chat responses not streaming?**
|
|
185
|
+
- Verify response format is set to **Stream (SSE)**
|
|
186
|
+
- Ensure the AI handler is the **last step** in your pipeline
|
|
187
|
+
- Check frontend is using `useChat` from `@ai-sdk/react`
|
|
188
|
+
|
|
189
|
+
**Skills not loading?**
|
|
190
|
+
- Verify `.bffless/skills/` exists in your deployment
|
|
191
|
+
- Ensure skills mode is set to **All** or **Selected** (not None)
|
|
192
|
+
- Check each skill has valid `SKILL.md` with YAML frontmatter (name and description)
|
|
193
|
+
|
|
194
|
+
**Messages not persisting?**
|
|
195
|
+
- Ensure **Message Persistence** is enabled in the AI handler config
|
|
196
|
+
- Verify both Conversations Schema and Messages Schema are selected
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pipelines
|
|
3
|
+
description: Backend automation without code using handler chains
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pipelines
|
|
7
|
+
|
|
8
|
+
**Docs**: https://docs.bffless.app/features/pipelines/
|
|
9
|
+
|
|
10
|
+
Pipelines provide backend functionality for static sites without writing server code. Chain handlers together to process forms, store data, send emails, and more.
|
|
11
|
+
|
|
12
|
+
## Handler Types
|
|
13
|
+
|
|
14
|
+
| Handler | Purpose |
|
|
15
|
+
|---------|---------|
|
|
16
|
+
| **Form** | Parse form submissions (multipart, JSON, URL-encoded) |
|
|
17
|
+
| **Data CRUD** | Create, read, update, delete DB Records |
|
|
18
|
+
| **Email** | Send emails via configured provider |
|
|
19
|
+
| **Response** | Return custom JSON or redirect |
|
|
20
|
+
| **Function** | Custom JavaScript for complex logic |
|
|
21
|
+
| **Aggregate** | Combine data from multiple sources |
|
|
22
|
+
|
|
23
|
+
## DB Records
|
|
24
|
+
|
|
25
|
+
Schema-based data storage built into BFFless:
|
|
26
|
+
|
|
27
|
+
1. Define schema in project settings (fields, types, validation)
|
|
28
|
+
2. Use Data CRUD handler to interact with records
|
|
29
|
+
3. Query with filters, sorting, pagination
|
|
30
|
+
|
|
31
|
+
## Expression Syntax
|
|
32
|
+
|
|
33
|
+
Access data throughout the pipeline using expressions:
|
|
34
|
+
|
|
35
|
+
- `input.*` - Parsed request body
|
|
36
|
+
- `query.*` - URL query parameters
|
|
37
|
+
- `params.*` - URL path parameters
|
|
38
|
+
- `headers.*` - Request headers
|
|
39
|
+
- `steps.<name>.*` - Output from previous handler
|
|
40
|
+
- `user.*` - Authenticated user info (if applicable)
|
|
41
|
+
|
|
42
|
+
Example: `${input.email}` or `${steps.createUser.id}`
|
|
43
|
+
|
|
44
|
+
## Common Workflows
|
|
45
|
+
|
|
46
|
+
**Contact form:**
|
|
47
|
+
1. Form handler → parse submission
|
|
48
|
+
2. Data CRUD → store in "submissions" schema
|
|
49
|
+
3. Email → notify admin
|
|
50
|
+
4. Response → thank you message
|
|
51
|
+
|
|
52
|
+
**Waitlist signup:**
|
|
53
|
+
1. Form handler → parse email
|
|
54
|
+
2. Data CRUD → check if exists, then create
|
|
55
|
+
3. Email → send confirmation to user
|
|
56
|
+
4. Response → success or "already registered"
|
|
57
|
+
|
|
58
|
+
**Webhook receiver:**
|
|
59
|
+
1. Form handler → parse JSON payload
|
|
60
|
+
2. Function → validate signature, transform data
|
|
61
|
+
3. Data CRUD → store event
|
|
62
|
+
4. Response → 200 OK
|
|
63
|
+
|
|
64
|
+
## Configuration Tips
|
|
65
|
+
|
|
66
|
+
1. Name handlers descriptively for readable expressions
|
|
67
|
+
2. Use Response handler last to control what client sees
|
|
68
|
+
3. Test with simple inputs before adding validation
|
|
69
|
+
4. Check pipeline logs for debugging failed executions
|
|
70
|
+
|
|
71
|
+
## Troubleshooting
|
|
72
|
+
|
|
73
|
+
**Pipeline not triggering?**
|
|
74
|
+
- Verify endpoint path matches request URL
|
|
75
|
+
- Check HTTP method (GET, POST, etc.) is correct
|
|
76
|
+
- Ensure pipeline is enabled and deployed
|
|
77
|
+
|
|
78
|
+
**Expression returning undefined?**
|
|
79
|
+
- Check handler name matches exactly (case-sensitive)
|
|
80
|
+
- Verify previous handler completed successfully
|
|
81
|
+
- Use pipeline logs to see actual values at each step
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: proxy-rules
|
|
3
|
+
description: Forward requests to backend APIs without CORS
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Proxy Rules
|
|
7
|
+
|
|
8
|
+
**Docs**: https://docs.bffless.app/features/proxy-rules/
|
|
9
|
+
|
|
10
|
+
Proxy rules forward requests from your static site to backend APIs, eliminating CORS issues and hiding API endpoints from clients.
|
|
11
|
+
|
|
12
|
+
## Configuration Levels
|
|
13
|
+
|
|
14
|
+
**Project defaults**: Apply to all aliases unless overridden
|
|
15
|
+
|
|
16
|
+
**Alias overrides**: Specific aliases can have different proxy configurations
|
|
17
|
+
|
|
18
|
+
## Rule Structure
|
|
19
|
+
|
|
20
|
+
Each rule specifies:
|
|
21
|
+
- **Path pattern**: Which requests to intercept
|
|
22
|
+
- **Target**: Backend URL to forward to
|
|
23
|
+
- **Strip prefix**: Whether to remove the matched prefix
|
|
24
|
+
|
|
25
|
+
## Pattern Types
|
|
26
|
+
|
|
27
|
+
**Prefix match** (most common):
|
|
28
|
+
```
|
|
29
|
+
/api/* → https://api.example.com
|
|
30
|
+
```
|
|
31
|
+
Request to `/api/users` forwards to `https://api.example.com/users`
|
|
32
|
+
|
|
33
|
+
**Exact match**:
|
|
34
|
+
```
|
|
35
|
+
/health → https://backend.example.com/status
|
|
36
|
+
```
|
|
37
|
+
Only exact path matches, no wildcards
|
|
38
|
+
|
|
39
|
+
**Suffix match**:
|
|
40
|
+
```
|
|
41
|
+
*.json → https://data.example.com
|
|
42
|
+
```
|
|
43
|
+
Matches any path ending in `.json`
|
|
44
|
+
|
|
45
|
+
## Strip Prefix Behavior
|
|
46
|
+
|
|
47
|
+
With strip prefix ON (default):
|
|
48
|
+
```
|
|
49
|
+
/api/* → https://backend.com
|
|
50
|
+
/api/users → https://backend.com/users
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
With strip prefix OFF:
|
|
54
|
+
```
|
|
55
|
+
/api/* → https://backend.com
|
|
56
|
+
/api/users → https://backend.com/api/users
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Common Patterns
|
|
60
|
+
|
|
61
|
+
**API proxy**: `/api/*` → your backend server
|
|
62
|
+
|
|
63
|
+
**Third-party API**: `/stripe/*` → `https://api.stripe.com` (hides API from client)
|
|
64
|
+
|
|
65
|
+
**Microservices**: Different prefixes route to different services
|
|
66
|
+
|
|
67
|
+
## Security Notes
|
|
68
|
+
|
|
69
|
+
- All proxy targets must use HTTPS
|
|
70
|
+
- BFFless validates targets to prevent SSRF attacks
|
|
71
|
+
- Headers like `Host` are rewritten to match target
|
|
72
|
+
- Client IP forwarded via `X-Forwarded-For`
|
|
73
|
+
|
|
74
|
+
## Troubleshooting
|
|
75
|
+
|
|
76
|
+
**Requests not proxying?**
|
|
77
|
+
- Check path pattern matches request URL exactly
|
|
78
|
+
- Verify alias isn't overriding project defaults
|
|
79
|
+
- Confirm target URL is HTTPS and reachable
|
|
80
|
+
|
|
81
|
+
**Getting CORS errors still?**
|
|
82
|
+
- Ensure the proxy rule is active on the alias being accessed
|
|
83
|
+
- Check browser DevTools for actual request URL (may not be hitting proxy)
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: repository
|
|
3
|
+
description: Browse deployments, manage aliases, view branches
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Repository
|
|
7
|
+
|
|
8
|
+
**Docs**: https://docs.bffless.app/features/repository-overview/
|
|
9
|
+
|
|
10
|
+
The Repository is your central hub for browsing deployments, managing aliases, and navigating your project's content.
|
|
11
|
+
|
|
12
|
+
## Content Browser
|
|
13
|
+
|
|
14
|
+
The browser has four panels:
|
|
15
|
+
|
|
16
|
+
1. **Files Panel**: Navigate directory structure, search files
|
|
17
|
+
2. **Preview Panel**: Live preview of selected file
|
|
18
|
+
3. **History Panel**: Deployment timeline, compare versions
|
|
19
|
+
4. **References Panel**: See which aliases point to this deployment
|
|
20
|
+
|
|
21
|
+
## Deployments
|
|
22
|
+
|
|
23
|
+
Each deployment is an immutable snapshot of your build output. Deployments are identified by:
|
|
24
|
+
|
|
25
|
+
- **Deployment ID**: Unique hash
|
|
26
|
+
- **Git info**: Branch, commit SHA, commit message (if available)
|
|
27
|
+
- **Timestamp**: When deployed
|
|
28
|
+
- **Size**: Total file size
|
|
29
|
+
|
|
30
|
+
## Aliases
|
|
31
|
+
|
|
32
|
+
Aliases are named pointers to deployments. Two types:
|
|
33
|
+
|
|
34
|
+
**Manual aliases**: You control which deployment they point to
|
|
35
|
+
- `production`, `staging`, `v1.2.0`
|
|
36
|
+
- Update manually or via API
|
|
37
|
+
|
|
38
|
+
**Auto-preview aliases**: Automatically created for branches/PRs
|
|
39
|
+
- `preview-feature-branch`, `pr-123`
|
|
40
|
+
- Updated on each push, deleted when branch is deleted
|
|
41
|
+
|
|
42
|
+
## Common Workflows
|
|
43
|
+
|
|
44
|
+
**Deploy new version:**
|
|
45
|
+
1. Upload via CLI/API/GitHub Action
|
|
46
|
+
2. New deployment appears in Repository
|
|
47
|
+
3. Update alias to point to new deployment
|
|
48
|
+
|
|
49
|
+
**Rollback:**
|
|
50
|
+
1. Find previous deployment in History
|
|
51
|
+
2. Update production alias to point to it
|
|
52
|
+
3. Instant rollback, no rebuild needed
|
|
53
|
+
|
|
54
|
+
**Preview PRs:**
|
|
55
|
+
1. Configure auto-preview in project settings
|
|
56
|
+
2. Each PR gets unique preview URL
|
|
57
|
+
3. Preview updates on each push
|
|
58
|
+
|
|
59
|
+
## Navigation Tips
|
|
60
|
+
|
|
61
|
+
- Use keyboard shortcuts: `j/k` to navigate files, `Enter` to preview
|
|
62
|
+
- Search supports glob patterns: `*.html`, `components/**`
|
|
63
|
+
- Click deployment hash to copy full URL
|
|
64
|
+
- Right-click alias for quick actions menu
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: share-links
|
|
3
|
+
description: Token-based sharing for private deployments
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Share Links
|
|
7
|
+
|
|
8
|
+
**Docs**: https://docs.bffless.app/features/share-links/
|
|
9
|
+
|
|
10
|
+
Share links allow sharing private deployments without requiring authentication. Each link contains a unique token that grants temporary access.
|
|
11
|
+
|
|
12
|
+
## Creating Share Links
|
|
13
|
+
|
|
14
|
+
1. Navigate to your deployment in the Repository
|
|
15
|
+
2. Click the **Share** button in the toolbar
|
|
16
|
+
3. Configure options:
|
|
17
|
+
- **Expiration**: Set duration or leave unlimited
|
|
18
|
+
- **Usage limit**: Max number of visits (optional)
|
|
19
|
+
- **Label**: Descriptive name for tracking
|
|
20
|
+
4. Copy the generated URL
|
|
21
|
+
|
|
22
|
+
## Link Management
|
|
23
|
+
|
|
24
|
+
- **View usage**: See visit count and last accessed time
|
|
25
|
+
- **Disable**: Temporarily suspend access without deleting
|
|
26
|
+
- **Regenerate**: Create new token, invalidating the old URL
|
|
27
|
+
- **Delete**: Permanently remove access
|
|
28
|
+
|
|
29
|
+
## Use Cases
|
|
30
|
+
|
|
31
|
+
- **Portfolio sharing**: Send private work to potential clients
|
|
32
|
+
- **Client reviews**: Share staging sites for feedback
|
|
33
|
+
- **Beta testing**: Distribute preview builds to testers
|
|
34
|
+
- **Time-limited access**: Demos that expire after a meeting
|
|
35
|
+
|
|
36
|
+
## Best Practices
|
|
37
|
+
|
|
38
|
+
1. Use descriptive labels to track who has which link
|
|
39
|
+
2. Set expiration dates for sensitive content
|
|
40
|
+
3. Combine with traffic splitting to show different content per link
|
|
41
|
+
4. Regenerate tokens if a link is compromised
|
|
42
|
+
5. Monitor usage to detect unexpected access patterns
|
|
43
|
+
|
|
44
|
+
## Troubleshooting
|
|
45
|
+
|
|
46
|
+
**Link not working?**
|
|
47
|
+
- Check if the link is disabled or expired
|
|
48
|
+
- Verify usage limit hasn't been reached
|
|
49
|
+
- Ensure the deployment still exists
|
|
50
|
+
|
|
51
|
+
**Need to revoke access?**
|
|
52
|
+
- Disable the link immediately, or delete it entirely
|
|
53
|
+
- Regenerate creates a new URL while keeping tracking history
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: traffic-splitting
|
|
3
|
+
description: Distribute traffic across aliases with weights and rules
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Traffic Splitting
|
|
7
|
+
|
|
8
|
+
**Docs**: https://docs.bffless.app/features/traffic-splitting/
|
|
9
|
+
|
|
10
|
+
Traffic splitting distributes requests across multiple deployment aliases. Use it for A/B testing, canary deployments, and personalized experiences.
|
|
11
|
+
|
|
12
|
+
## Configuration
|
|
13
|
+
|
|
14
|
+
### Weights
|
|
15
|
+
|
|
16
|
+
Assign percentage weights to aliases. Weights must sum to 100.
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
production: 90%
|
|
20
|
+
canary: 10%
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Sticky Sessions
|
|
24
|
+
|
|
25
|
+
When enabled, visitors consistently see the same variant. Controlled via cookie. Disable for true random distribution per request.
|
|
26
|
+
|
|
27
|
+
### Traffic Rules
|
|
28
|
+
|
|
29
|
+
Rules override weights based on conditions. Evaluated in order, first match wins.
|
|
30
|
+
|
|
31
|
+
**Rule conditions:**
|
|
32
|
+
- **Headers**: Match request headers (e.g., `X-Beta-User: true`)
|
|
33
|
+
- **Query params**: Match URL parameters (e.g., `?variant=new`)
|
|
34
|
+
- **Cookies**: Match cookie values
|
|
35
|
+
- **Share link**: Route specific share links to specific aliases
|
|
36
|
+
|
|
37
|
+
## Use Cases
|
|
38
|
+
|
|
39
|
+
**A/B Testing**: Split traffic 50/50 between variants, measure conversion
|
|
40
|
+
|
|
41
|
+
**Canary Deployment**: Send 5% to new version, monitor for errors, gradually increase
|
|
42
|
+
|
|
43
|
+
**Beta Features**: Route users with beta header to feature branch
|
|
44
|
+
|
|
45
|
+
**Personalized Demos**: Use share links to show customized content per client
|
|
46
|
+
|
|
47
|
+
## Configuration Tips
|
|
48
|
+
|
|
49
|
+
1. Start canary deployments at 5-10%, increase gradually
|
|
50
|
+
2. Enable sticky sessions for consistent user experience
|
|
51
|
+
3. Use rules for deterministic routing (internal testing, specific clients)
|
|
52
|
+
4. Combine with share links for per-recipient personalization
|
|
53
|
+
|
|
54
|
+
## Troubleshooting
|
|
55
|
+
|
|
56
|
+
**Unexpected routing?**
|
|
57
|
+
- Rules are evaluated before weights; check rule order
|
|
58
|
+
- Clear cookies if sticky session is routing to old variant
|
|
59
|
+
- Verify alias names match exactly (case-sensitive)
|
|
60
|
+
|
|
61
|
+
**Traffic percentages seem off?**
|
|
62
|
+
- Small sample sizes show high variance; need 100+ requests for accuracy
|
|
63
|
+
- Sticky sessions can skew percentages if users have different visit frequencies
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: upload-artifact
|
|
3
|
+
description: GitHub Action for uploading build artifacts to BFFless
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# BFFless Upload Artifact Action
|
|
7
|
+
|
|
8
|
+
The `bffless/upload-artifact` GitHub Action uploads build artifacts from your CI/CD pipeline to a BFFless instance. It's available on the [GitHub Marketplace](https://github.com/bffless/upload-artifact).
|
|
9
|
+
|
|
10
|
+
For full documentation, see the [README on GitHub](https://github.com/bffless/upload-artifact).
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
Only 3 inputs are required:
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
- uses: bffless/upload-artifact@v1
|
|
18
|
+
with:
|
|
19
|
+
path: dist
|
|
20
|
+
api-url: ${{ vars.ASSET_HOST_URL }}
|
|
21
|
+
api-key: ${{ secrets.ASSET_HOST_KEY }}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Common Workflows
|
|
25
|
+
|
|
26
|
+
### PR Preview with Comment
|
|
27
|
+
|
|
28
|
+
```yaml
|
|
29
|
+
jobs:
|
|
30
|
+
build:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
permissions:
|
|
33
|
+
contents: read
|
|
34
|
+
pull-requests: write # Required for PR comments
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@v4
|
|
37
|
+
with:
|
|
38
|
+
fetch-depth: 0 # Required for commit timestamp
|
|
39
|
+
|
|
40
|
+
- name: Build
|
|
41
|
+
run: npm run build
|
|
42
|
+
|
|
43
|
+
- uses: bffless/upload-artifact@v1
|
|
44
|
+
with:
|
|
45
|
+
path: dist
|
|
46
|
+
api-url: ${{ vars.ASSET_HOST_URL }}
|
|
47
|
+
api-key: ${{ secrets.ASSET_HOST_KEY }}
|
|
48
|
+
alias: preview
|
|
49
|
+
description: 'PR #${{ github.event.pull_request.number }} preview'
|
|
50
|
+
pr-comment: true
|
|
51
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Production Deploy
|
|
55
|
+
|
|
56
|
+
```yaml
|
|
57
|
+
- uses: bffless/upload-artifact@v1
|
|
58
|
+
id: deploy
|
|
59
|
+
with:
|
|
60
|
+
path: dist
|
|
61
|
+
api-url: ${{ vars.ASSET_HOST_URL }}
|
|
62
|
+
api-key: ${{ secrets.ASSET_HOST_KEY }}
|
|
63
|
+
alias: production
|
|
64
|
+
tags: ${{ needs.release.outputs.version }}
|
|
65
|
+
description: 'Release ${{ needs.release.outputs.version }}'
|
|
66
|
+
|
|
67
|
+
- run: echo "Deployed to ${{ steps.deploy.outputs.sha-url }}"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Multiple Artifacts (Same Workflow)
|
|
71
|
+
|
|
72
|
+
You can upload multiple artifacts in the same workflow:
|
|
73
|
+
|
|
74
|
+
```yaml
|
|
75
|
+
- name: Upload frontend
|
|
76
|
+
uses: bffless/upload-artifact@v1
|
|
77
|
+
with:
|
|
78
|
+
path: apps/frontend/dist
|
|
79
|
+
api-url: ${{ vars.ASSET_HOST_URL }}
|
|
80
|
+
api-key: ${{ secrets.ASSET_HOST_KEY }}
|
|
81
|
+
alias: production
|
|
82
|
+
base-path: /dist
|
|
83
|
+
|
|
84
|
+
- name: Upload skills
|
|
85
|
+
uses: bffless/upload-artifact@v1
|
|
86
|
+
with:
|
|
87
|
+
path: .bffless
|
|
88
|
+
api-url: ${{ vars.ASSET_HOST_URL }}
|
|
89
|
+
api-key: ${{ secrets.ASSET_HOST_KEY }}
|
|
90
|
+
alias: production
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## All Inputs
|
|
94
|
+
|
|
95
|
+
| Input | Required | Default | Description |
|
|
96
|
+
|-------|----------|---------|-------------|
|
|
97
|
+
| `path` | **yes** | -- | Build directory to upload |
|
|
98
|
+
| `api-url` | **yes** | -- | BFFless platform URL |
|
|
99
|
+
| `api-key` | **yes** | -- | API key for authentication |
|
|
100
|
+
| `repository` | no | `github.repository` | Repository in `owner/repo` format |
|
|
101
|
+
| `commit-sha` | no | auto | Git commit SHA |
|
|
102
|
+
| `branch` | no | auto | Branch name |
|
|
103
|
+
| `is-public` | no | `'true'` | Public visibility |
|
|
104
|
+
| `alias` | no | -- | Deployment alias (e.g., `production`) |
|
|
105
|
+
| `base-path` | no | `/<path>` | Path prefix in zip |
|
|
106
|
+
| `committed-at` | no | auto | ISO 8601 commit timestamp |
|
|
107
|
+
| `description` | no | -- | Human-readable description |
|
|
108
|
+
| `proxy-rule-set-name` | no | -- | Proxy rule set name |
|
|
109
|
+
| `proxy-rule-set-id` | no | -- | Proxy rule set ID |
|
|
110
|
+
| `tags` | no | -- | Comma-separated tags |
|
|
111
|
+
| `summary` | no | `'true'` | Write GitHub Step Summary |
|
|
112
|
+
| `summary-title` | no | `'Deployment Summary'` | Summary heading |
|
|
113
|
+
| `working-directory` | no | `'.'` | Working directory |
|
|
114
|
+
| `pr-comment` | no | `'false'` | Post comment on PR |
|
|
115
|
+
| `comment-header` | no | `'🚀 BFFLESS Deployment'` | PR comment header |
|
|
116
|
+
| `github-token` | no | `GITHUB_TOKEN` | Token for PR comments |
|
|
117
|
+
|
|
118
|
+
## Outputs
|
|
119
|
+
|
|
120
|
+
| Output | Description |
|
|
121
|
+
|--------|-------------|
|
|
122
|
+
| `deployment-url` | Primary URL (SHA-based) |
|
|
123
|
+
| `sha-url` | Immutable SHA-based URL |
|
|
124
|
+
| `alias-url` | Alias-based URL |
|
|
125
|
+
| `preview-url` | Preview URL (if basePath provided) |
|
|
126
|
+
| `branch-url` | Branch-based URL |
|
|
127
|
+
| `deployment-id` | API deployment ID |
|
|
128
|
+
| `file-count` | Number of files uploaded |
|
|
129
|
+
| `total-size` | Total bytes |
|
|
130
|
+
| `response` | Raw JSON response |
|
|
131
|
+
|
|
132
|
+
## How It Works
|
|
133
|
+
|
|
134
|
+
1. **Validates** the build directory exists
|
|
135
|
+
2. **Zips** the directory preserving structure
|
|
136
|
+
3. **Uploads** via multipart POST to `/api/deployments/zip`
|
|
137
|
+
4. **Sets outputs** from API response
|
|
138
|
+
5. **Writes Step Summary** with deployment table
|
|
139
|
+
6. **Posts PR comment** (if enabled)
|
|
140
|
+
7. **Cleans up** temporary files
|
|
141
|
+
|
|
142
|
+
## Auto-Detection
|
|
143
|
+
|
|
144
|
+
The action automatically detects:
|
|
145
|
+
|
|
146
|
+
- **Repository**: from `github.repository`
|
|
147
|
+
- **Commit SHA**: PR head SHA or push SHA
|
|
148
|
+
- **Branch**: PR head ref or push ref
|
|
149
|
+
- **Committed At**: via `git log` (requires `fetch-depth: 0`)
|
|
150
|
+
- **Base Path**: derived from `path` input as `/<path>`
|
|
151
|
+
|
|
152
|
+
## PR Comments
|
|
153
|
+
|
|
154
|
+
When `pr-comment: true`, the action posts a formatted comment:
|
|
155
|
+
|
|
156
|
+
> ## 🚀 BFFLESS Deployment
|
|
157
|
+
>
|
|
158
|
+
> **Alias:** `preview`
|
|
159
|
+
>
|
|
160
|
+
> | Property | Value |
|
|
161
|
+
> | ----------- | ---------------------------------- |
|
|
162
|
+
> | **Preview** | [example.com](https://example.com) |
|
|
163
|
+
> | **Commit** | `abc1234` |
|
|
164
|
+
> | **Files** | 42 |
|
|
165
|
+
> | **Size** | 1.2 MB |
|
|
166
|
+
|
|
167
|
+
Comments are automatically updated on subsequent pushes (no duplicates).
|
|
168
|
+
|
|
169
|
+
## Troubleshooting
|
|
170
|
+
|
|
171
|
+
### Missing commit timestamp
|
|
172
|
+
|
|
173
|
+
```yaml
|
|
174
|
+
- uses: actions/checkout@v4
|
|
175
|
+
with:
|
|
176
|
+
fetch-depth: 0 # Full history needed for git log
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### PR comment permission denied
|
|
180
|
+
|
|
181
|
+
```yaml
|
|
182
|
+
permissions:
|
|
183
|
+
pull-requests: write # Required for comments
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Custom base path
|
|
187
|
+
|
|
188
|
+
If your app expects to be served from a subdirectory:
|
|
189
|
+
|
|
190
|
+
```yaml
|
|
191
|
+
- uses: bffless/upload-artifact@v1
|
|
192
|
+
with:
|
|
193
|
+
path: build
|
|
194
|
+
base-path: /docs/build # Served at /docs/build/*
|
|
195
|
+
```
|