Skip to content

Commit a48d486

Browse files
authored
Merge pull request #4 from framer/add-publish
Introducing publish example
2 parents 3b0b7de + a90eeb3 commit a48d486

9 files changed

Lines changed: 152 additions & 85 deletions

File tree

.github/workflows/pull_request.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ jobs:
1919
- name: Setup env files for type generation
2020
run: |
2121
for dir in examples/*/; do
22-
[ -f "$dir/.env.example" ] && cp "$dir/.env.example" "$dir/.env"
22+
if [ -f "$dir/.env.example" ]; then
23+
cp "$dir/.env.example" "$dir/.env"
24+
fi
2325
done
2426
2527
- run: npm ci

examples/csv-importer/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"typecheck": "tsc --noEmit"
88
},
99
"dependencies": {
10-
"framer-api": "^0.0.1-beta.0",
10+
"framer-api": "^0.1.1",
1111
"papaparse": "^5.5.3",
1212
"typescript": "^5.9.3"
1313
},

examples/json-api/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
},
1010
"dependencies": {
1111
"@hono/node-server": "^1.14.1",
12-
"framer-api": "^0.0.1-beta.0",
12+
"framer-api": "^0.1.1",
1313
"hono": "^4.11.4",
1414
"typescript": "^5.9.3"
1515
},

examples/notion-automations-sync/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
},
1515
"dependencies": {
1616
"@notionhq/client": "^5.6.0",
17-
"framer-api": "beta"
17+
"framer-api": "0.1.1"
1818
},
1919
"devDependencies": {
2020
"@types/node": "^24.10.0",

examples/publish/README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# Publish
2+
3+
Publishes and deploys a Framer project. Designed to run as a one-shot script, making it ideal for cron jobs, CI/CD pipelines, and systemd timers.
4+
5+
## Usage
6+
7+
```bash
8+
node --env-file=../../.env publish.ts
9+
10+
bun --env-file=../../.env run publish.ts
11+
12+
deno --env-file=../../.env run publish.ts
13+
```
14+
15+
## Environment Variables
16+
17+
| Variable | Required | Description |
18+
|----------|----------|-------------|
19+
| `EXAMPLE_PROJECT_URL` | Yes | Your Framer project URL |
20+
21+
## Scheduling Examples
22+
23+
### Cron
24+
25+
Publish every 4 hours:
26+
27+
```bash
28+
# Edit crontab
29+
crontab -e
30+
31+
# Add this line (adjust paths as needed)
32+
0 */4 * * * cd /path/to/examples/publish && node --env-file=../../.env publish.ts >> /var/log/framer-publish.log 2>&1
33+
```
34+
35+
Common cron schedules:
36+
37+
```bash
38+
0 */4 * * * # Every 4 hours
39+
0 9-18/2 * * 1-5 # Every 2 hours between 9:00 and 18:00, mon-fri
40+
0 9 * * * # Daily at 9:00
41+
0 9 * * 1-5 # Weekdays at 9:00
42+
```

examples/publish/package.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "publish",
3+
"version": "0.0.1",
4+
"private": true,
5+
"type": "module",
6+
"scripts": {
7+
"typecheck": "tsc --noEmit"
8+
},
9+
"dependencies": {
10+
"framer-api": "^0.1.1",
11+
"typescript": "^5.9.3"
12+
},
13+
"devDependencies": {
14+
"@types/node": "^22.10.2"
15+
}
16+
}

examples/publish/publish.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import assert from "node:assert";
2+
import { connect } from "framer-api";
3+
4+
const projectUrl = process.env["EXAMPLE_PROJECT_URL"];
5+
assert(projectUrl, "EXAMPLE_PROJECT_URL environment variable is required");
6+
7+
using framer = await connect(projectUrl);
8+
9+
// Show changes
10+
const changedPaths = await framer.getChangedPaths();
11+
const entries = Object.entries(changedPaths);
12+
const totalChanges = entries.reduce((sum, [, paths]) => sum + paths.length, 0);
13+
14+
if (totalChanges === 0) {
15+
console.log("⛔️ No changes to publish.");
16+
process.exit(0);
17+
}
18+
19+
console.log(`📄 ${totalChanges} change(s):`);
20+
for (const [type, paths] of entries) {
21+
for (const path of paths) {
22+
console.log(` ${type}: ${path}`);
23+
}
24+
}
25+
26+
// Publish
27+
const { deployment } = await framer.publish();
28+
console.log(`🚀 Published deployment ${deployment.id}`);
29+
30+
// Deploy to custom domains
31+
const deployed = await framer.deploy(deployment.id);
32+
33+
if (deployed.length > 0) {
34+
console.log(`✅ Deployed to ${deployed.length} custom domain(s):`);
35+
for (const hostname of deployed) {
36+
console.log(` https://${hostname.hostname}`);
37+
}
38+
} else {
39+
console.log("No custom domains to deploy — default hostname is already live.");
40+
}

examples/publish/tsconfig.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"extends": "../../tsconfig.base.json",
3+
"include": ["publish.ts"]
4+
}

package-lock.json

Lines changed: 44 additions & 81 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)