frontpage-host 0.1.16 → 0.1.18
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/AGENTS.md +30 -19
- package/README.md +3 -3
- package/dist/bin-path.d.ts +21 -0
- package/dist/bin-path.js +65 -0
- package/dist/bin.js +9 -0
- package/dist/commands/deploy.d.ts +1 -1
- package/dist/commands/deploy.js +4 -5
- package/dist/commands/images.d.ts +1 -0
- package/dist/commands/images.js +57 -0
- package/dist/commands/modules.js +4 -0
- package/dist/commands/people.d.ts +1 -0
- package/dist/commands/people.js +239 -0
- package/dist/commands/publish.js +73 -11
- package/dist/commands/push.d.ts +5 -0
- package/dist/commands/push.js +18 -13
- package/dist/commands/redirects.d.ts +1 -0
- package/dist/commands/redirects.js +83 -0
- package/dist/commands/wait-agent-idle.d.ts +12 -0
- package/dist/commands/wait-agent-idle.js +23 -5
- package/dist/commands/wait-site-compile.d.ts +22 -0
- package/dist/commands/wait-site-compile.js +98 -0
- package/dist/compile.d.ts +46 -0
- package/dist/compile.js +99 -0
- package/dist/completions/generate.js +14 -3
- package/dist/modules/commands.js +24 -1
- package/dist/modules/forms_destinations.d.ts +3 -0
- package/dist/modules/forms_destinations.js +147 -0
- package/dist/modules/typed_config.js +21 -9
- package/dist/registry.js +103 -22
- package/llms.txt +8 -5
- package/package.json +1 -1
package/dist/modules/commands.js
CHANGED
|
@@ -63,6 +63,13 @@ export const MODULE_COMMANDS = [
|
|
|
63
63
|
extraActions: [
|
|
64
64
|
"get [--instance <slug>]",
|
|
65
65
|
"set --instance <slug> [--notify-email] [--confirm yes|no]",
|
|
66
|
+
"destinations [--instance <slug>]",
|
|
67
|
+
"connect-destination <privyr|hubspot|pipedrive> --token \"…\" [--lead-source \"…\"]",
|
|
68
|
+
"attach-destination --instance <slug> --provider <id>",
|
|
69
|
+
"detach-destination --instance <slug> --provider <id>",
|
|
70
|
+
"remove-destination <id> --yes",
|
|
71
|
+
"disconnect-destination <id> --yes",
|
|
72
|
+
"request-destination-setup <id> --reason \"…\"",
|
|
66
73
|
],
|
|
67
74
|
notYet: [],
|
|
68
75
|
examples: [
|
|
@@ -70,12 +77,16 @@ export const MODULE_COMMANDS = [
|
|
|
70
77
|
"frontpage modules forms get",
|
|
71
78
|
"frontpage modules forms get --instance lead-gen",
|
|
72
79
|
"frontpage modules forms set --instance lead-gen --notify-email hi@example.com",
|
|
80
|
+
"frontpage modules forms destinations",
|
|
81
|
+
"frontpage modules forms connect-destination privyr --token \"…\"",
|
|
82
|
+
"frontpage modules forms attach-destination --instance lead-gen --provider privyr",
|
|
73
83
|
"frontpage modules forms docs",
|
|
74
84
|
`frontpage modules config forms --instance lead-gen --config '{"notifyEmail":"hi@example.com"}'`,
|
|
75
85
|
],
|
|
76
86
|
notes: [
|
|
77
87
|
"Without --instance, get lists each form (id, status, notifyEmail). Do not target `default`.",
|
|
78
88
|
"Confirmation emails require a paid plan (same as Modules).",
|
|
89
|
+
"Destinations copy leads to HubSpot, Pipedrive, or Privyr. Connect once, then attach each form. Token write is admin (Privyr: paste the Incoming Webhook URL, not a token). request-destination-setup lights the editor amber bar (editor key). remove-destination requires --yes. Locations: https://frontpage.host/developers/modules#forms-destinations",
|
|
79
90
|
],
|
|
80
91
|
},
|
|
81
92
|
{
|
|
@@ -275,7 +286,19 @@ export function isCliModuleAction(key, action) {
|
|
|
275
286
|
if (key === "google_reviews") {
|
|
276
287
|
return GOOGLE_REVIEWS_CLI_ACTIONS.includes(action);
|
|
277
288
|
}
|
|
278
|
-
if (key === "
|
|
289
|
+
if (key === "forms") {
|
|
290
|
+
return (TYPED_CONFIG_CLI_ACTIONS.includes(action) ||
|
|
291
|
+
[
|
|
292
|
+
"destinations",
|
|
293
|
+
"connect-destination",
|
|
294
|
+
"remove-destination",
|
|
295
|
+
"disconnect-destination",
|
|
296
|
+
"attach-destination",
|
|
297
|
+
"detach-destination",
|
|
298
|
+
"request-destination-setup",
|
|
299
|
+
].includes(action));
|
|
300
|
+
}
|
|
301
|
+
if (key === "callbar" || key === "booking" || key === "signups") {
|
|
279
302
|
return TYPED_CONFIG_CLI_ACTIONS.includes(action);
|
|
280
303
|
}
|
|
281
304
|
if (key === "payments" || key === "shop") {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const FORMS_DESTINATION_CLI_ACTIONS: readonly ["destinations", "connect-destination", "remove-destination", "disconnect-destination", "attach-destination", "detach-destination", "request-destination-setup"];
|
|
2
|
+
export declare function isFormsDestinationCliAction(action: string): boolean;
|
|
3
|
+
export declare function runFormsDestinations(slug: string, action: string, flags: string[]): Promise<number>;
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* §FD.CLI — form destination verbs.
|
|
3
|
+
*/
|
|
4
|
+
import { assertNoUnknownFlags, hasFlag, takeFlag } from "../argv.js";
|
|
5
|
+
import { EXIT_OK, EXIT_USAGE, v1Get, v1Post } from "../http/client.js";
|
|
6
|
+
import { emitOk, emitUsage, isJson } from "../runtime.js";
|
|
7
|
+
import { formatModuleUsage } from "./commands.js";
|
|
8
|
+
const USAGE = formatModuleUsage("forms");
|
|
9
|
+
const REMOVE_CONFIRM = "This deletes the destination from Frontpage and stops every form from sending a copy. Your leads stay in Frontpage and still email you.";
|
|
10
|
+
function pathFor(slug) {
|
|
11
|
+
return `/api/v1/sites/${encodeURIComponent(slug)}/modules/forms`;
|
|
12
|
+
}
|
|
13
|
+
export const FORMS_DESTINATION_CLI_ACTIONS = [
|
|
14
|
+
"destinations",
|
|
15
|
+
"connect-destination",
|
|
16
|
+
"remove-destination",
|
|
17
|
+
"disconnect-destination",
|
|
18
|
+
"attach-destination",
|
|
19
|
+
"detach-destination",
|
|
20
|
+
"request-destination-setup",
|
|
21
|
+
];
|
|
22
|
+
export function isFormsDestinationCliAction(action) {
|
|
23
|
+
return FORMS_DESTINATION_CLI_ACTIONS.includes(action);
|
|
24
|
+
}
|
|
25
|
+
function printDestinations(data, instanceFilter) {
|
|
26
|
+
const providers = data.destinations?.providers ?? [];
|
|
27
|
+
const connected = providers.filter((p) => p.connected);
|
|
28
|
+
if (!connected.length) {
|
|
29
|
+
console.log("(no destinations)");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const by = data.destinations?.byInstance ?? {};
|
|
33
|
+
for (const p of connected) {
|
|
34
|
+
console.log(`${p.id.padEnd(10)} connected ${p.last4 ? `••••${p.last4}` : ""}`.trimEnd());
|
|
35
|
+
const slugs = instanceFilter ? [instanceFilter] : Object.keys(by);
|
|
36
|
+
for (const slug of slugs) {
|
|
37
|
+
const row = (by[slug] ?? []).find((r) => r.provider === p.id);
|
|
38
|
+
const sending = row?.enabled ? "sending" : "—";
|
|
39
|
+
const err = row?.lastError ? ` error ${row.lastError}` : "";
|
|
40
|
+
if (instanceFilter && !row) {
|
|
41
|
+
console.log(` ${slug.padEnd(16)} —`);
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (!instanceFilter && !row)
|
|
45
|
+
continue;
|
|
46
|
+
console.log(` ${slug.padEnd(16)} ${sending}${err}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
export async function runFormsDestinations(slug, action, flags) {
|
|
51
|
+
const work = [...flags];
|
|
52
|
+
if (action === "destinations") {
|
|
53
|
+
const instanceId = takeFlag(work, "--instance");
|
|
54
|
+
assertNoUnknownFlags(work, "modules");
|
|
55
|
+
const data = await v1Get(pathFor(slug));
|
|
56
|
+
if (isJson()) {
|
|
57
|
+
emitOk("modules", data.destinations ?? { providers: [], byInstance: {} });
|
|
58
|
+
return EXIT_OK;
|
|
59
|
+
}
|
|
60
|
+
printDestinations(data, instanceId);
|
|
61
|
+
return EXIT_OK;
|
|
62
|
+
}
|
|
63
|
+
if (action === "connect-destination") {
|
|
64
|
+
const provider = work.shift();
|
|
65
|
+
const token = takeFlag(work, "--token");
|
|
66
|
+
const leadSource = takeFlag(work, "--lead-source");
|
|
67
|
+
assertNoUnknownFlags(work, "modules");
|
|
68
|
+
if (!provider || !token) {
|
|
69
|
+
return emitUsage("modules", `Usage: frontpage modules forms connect-destination <privyr|hubspot|pipedrive> --token "…"\n\n${USAGE}`);
|
|
70
|
+
}
|
|
71
|
+
const data = await v1Post(pathFor(slug), {
|
|
72
|
+
action: "destination_connect",
|
|
73
|
+
provider,
|
|
74
|
+
token,
|
|
75
|
+
...(leadSource ? { leadSource } : {}),
|
|
76
|
+
});
|
|
77
|
+
if (isJson()) {
|
|
78
|
+
emitOk("modules", data);
|
|
79
|
+
return EXIT_OK;
|
|
80
|
+
}
|
|
81
|
+
const last4 = typeof data.last4 === "string" ? data.last4 : "";
|
|
82
|
+
console.log(`Connected ${provider}${last4 ? ` ••••${last4}` : ""}.`);
|
|
83
|
+
return EXIT_OK;
|
|
84
|
+
}
|
|
85
|
+
if (action === "remove-destination" || action === "disconnect-destination") {
|
|
86
|
+
const provider = work.shift();
|
|
87
|
+
const yes = hasFlag(work, "--yes");
|
|
88
|
+
assertNoUnknownFlags(work, "modules");
|
|
89
|
+
if (!provider) {
|
|
90
|
+
return emitUsage("modules", `Usage: frontpage modules forms ${action} <privyr|hubspot|pipedrive> --yes\n\n${USAGE}`);
|
|
91
|
+
}
|
|
92
|
+
if (!yes) {
|
|
93
|
+
return emitUsage("modules", REMOVE_CONFIRM, EXIT_USAGE);
|
|
94
|
+
}
|
|
95
|
+
const data = await v1Post(pathFor(slug), {
|
|
96
|
+
action: "destination_remove",
|
|
97
|
+
provider,
|
|
98
|
+
});
|
|
99
|
+
if (isJson()) {
|
|
100
|
+
emitOk("modules", data);
|
|
101
|
+
return EXIT_OK;
|
|
102
|
+
}
|
|
103
|
+
console.log(`Removed ${provider}. Leads still land in Frontpage.`);
|
|
104
|
+
return EXIT_OK;
|
|
105
|
+
}
|
|
106
|
+
if (action === "attach-destination" || action === "detach-destination") {
|
|
107
|
+
const instanceId = takeFlag(work, "--instance");
|
|
108
|
+
const provider = takeFlag(work, "--provider") ?? work.shift();
|
|
109
|
+
assertNoUnknownFlags(work, "modules");
|
|
110
|
+
if (!instanceId || !provider) {
|
|
111
|
+
return emitUsage("modules", `Usage: frontpage modules forms ${action} --instance <slug> --provider <privyr|hubspot|pipedrive>\n\n${USAGE}`);
|
|
112
|
+
}
|
|
113
|
+
const data = await v1Post(pathFor(slug), {
|
|
114
|
+
action: action === "attach-destination" ? "destination_attach" : "destination_detach",
|
|
115
|
+
provider,
|
|
116
|
+
instanceId,
|
|
117
|
+
});
|
|
118
|
+
if (isJson()) {
|
|
119
|
+
emitOk("modules", data);
|
|
120
|
+
return EXIT_OK;
|
|
121
|
+
}
|
|
122
|
+
console.log(action === "attach-destination"
|
|
123
|
+
? `${instanceId} will also send a copy to ${provider}.`
|
|
124
|
+
: `Stopped sending ${instanceId} to ${provider}.`);
|
|
125
|
+
return EXIT_OK;
|
|
126
|
+
}
|
|
127
|
+
if (action === "request-destination-setup") {
|
|
128
|
+
const provider = work.shift();
|
|
129
|
+
const reason = takeFlag(work, "--reason") ?? "";
|
|
130
|
+
assertNoUnknownFlags(work, "modules");
|
|
131
|
+
if (!provider || !reason) {
|
|
132
|
+
return emitUsage("modules", `Usage: frontpage modules forms request-destination-setup <privyr|hubspot|pipedrive> --reason "…"\n\n${USAGE}`);
|
|
133
|
+
}
|
|
134
|
+
const data = await v1Post(pathFor(slug), {
|
|
135
|
+
action: "destination_request_setup",
|
|
136
|
+
provider,
|
|
137
|
+
reason,
|
|
138
|
+
});
|
|
139
|
+
if (isJson()) {
|
|
140
|
+
emitOk("modules", data);
|
|
141
|
+
return EXIT_OK;
|
|
142
|
+
}
|
|
143
|
+
console.log(`Setup requested for ${provider}. The owner sees an amber prompt in the Frontpage editor.`);
|
|
144
|
+
return EXIT_OK;
|
|
145
|
+
}
|
|
146
|
+
return emitUsage("modules", `${USAGE}\n\nUnknown action "${action}".`);
|
|
147
|
+
}
|
|
@@ -46,17 +46,29 @@ function printConfirmable(config, confirmations) {
|
|
|
46
46
|
else
|
|
47
47
|
printLine("confirm", yesNo(on));
|
|
48
48
|
}
|
|
49
|
-
function printFormsList(instances) {
|
|
49
|
+
function printFormsList(instances, destinations) {
|
|
50
50
|
if (!instances.length) {
|
|
51
51
|
console.log("(no forms)");
|
|
52
|
-
return;
|
|
53
52
|
}
|
|
54
|
-
|
|
55
|
-
const
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
53
|
+
else {
|
|
54
|
+
for (const i of instances) {
|
|
55
|
+
const id = i.instance ?? "";
|
|
56
|
+
const label = i.label && i.label !== id ? i.label : "";
|
|
57
|
+
const status = String(i.status ?? "—");
|
|
58
|
+
const email = typeof i.config?.notifyEmail === "string" ? i.config.notifyEmail : "(account email)";
|
|
59
|
+
const attached = (destinations?.byInstance?.[id] ?? [])
|
|
60
|
+
.filter((r) => r.enabled)
|
|
61
|
+
.map((r) => r.provider)
|
|
62
|
+
.join(",");
|
|
63
|
+
console.log(`${id.padEnd(20)} ${status.padEnd(12)} ${label ? `${label} ` : ""}${email.padEnd(22)} ${attached || "—"}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const connected = (destinations?.providers ?? []).filter((p) => p.connected);
|
|
67
|
+
if (connected.length) {
|
|
68
|
+
console.log("");
|
|
69
|
+
for (const p of connected) {
|
|
70
|
+
console.log(`${p.id} connected${p.last4 ? ` ••••${p.last4}` : ""}`);
|
|
71
|
+
}
|
|
60
72
|
}
|
|
61
73
|
}
|
|
62
74
|
function parseYesNoFlag(raw, flag) {
|
|
@@ -81,7 +93,7 @@ export async function runTypedConfig(key, slug, action, flags) {
|
|
|
81
93
|
return EXIT_OK;
|
|
82
94
|
}
|
|
83
95
|
if (key === "forms" && !instanceId) {
|
|
84
|
-
printFormsList(data.instances ?? []);
|
|
96
|
+
printFormsList(data.instances ?? [], data.destinations);
|
|
85
97
|
return EXIT_OK;
|
|
86
98
|
}
|
|
87
99
|
if (key === "callbar")
|
package/dist/registry.js
CHANGED
|
@@ -104,7 +104,7 @@ export const COMMANDS = [
|
|
|
104
104
|
flags: [
|
|
105
105
|
"--site <slug>",
|
|
106
106
|
"--message <text>",
|
|
107
|
-
"--wait: after push, wait until
|
|
107
|
+
"--wait: after push, wait until the new commit's site compile is live (agent-run idle first, then GET /deploy ready)",
|
|
108
108
|
],
|
|
109
109
|
dangers: [
|
|
110
110
|
"Requires prior pull (baseCommitSha)",
|
|
@@ -249,10 +249,16 @@ export const COMMANDS = [
|
|
|
249
249
|
{
|
|
250
250
|
name: "publish",
|
|
251
251
|
summary: "Promote staging to production",
|
|
252
|
-
usage: "frontpage publish [--site <slug>] [--json]",
|
|
252
|
+
usage: "frontpage publish [--site <slug>] [--wait] [--json]",
|
|
253
253
|
topics: ["agent"],
|
|
254
|
+
examples: ["frontpage publish", "frontpage publish --wait"],
|
|
255
|
+
flags: [
|
|
256
|
+
"--wait: wait until the staging tip's site compile is live, then publish (refuses a previous build)",
|
|
257
|
+
"Prints tip SHA and serving SHA; warns if they differ",
|
|
258
|
+
],
|
|
254
259
|
dangers: [
|
|
255
|
-
"Promotes the
|
|
260
|
+
"Promotes the last ready staging compile to PRODUCTION (custom domain)",
|
|
261
|
+
"409 if the tip is not compiled yet — wait, then publish",
|
|
256
262
|
"Agents: never run unless the user explicitly asked to publish",
|
|
257
263
|
],
|
|
258
264
|
seeAlso: ["unpublish", "deploy"],
|
|
@@ -270,13 +276,14 @@ export const COMMANDS = [
|
|
|
270
276
|
},
|
|
271
277
|
{
|
|
272
278
|
name: "deploy",
|
|
273
|
-
summary: "Wait for
|
|
279
|
+
summary: "Wait for the current tip's site compile (not publish)",
|
|
274
280
|
usage: "frontpage deploy wait [--site <slug>] [--json]",
|
|
275
281
|
topics: ["agent"],
|
|
276
282
|
flags: [
|
|
277
|
-
"
|
|
283
|
+
"Waits for editor-agent idle (if a run is in flight), then until GET /deploy ready",
|
|
284
|
+
"ready = the live compile SHA equals the git tip — not a historical agent run",
|
|
278
285
|
"Does NOT promote to production; use publish only when the user asks",
|
|
279
|
-
"Fail-closed: exit 2 when the waited run
|
|
286
|
+
"Fail-closed: exit 2 when the waited agent run is failed/canceled, or the compile fails or times out",
|
|
280
287
|
],
|
|
281
288
|
},
|
|
282
289
|
{
|
|
@@ -361,6 +368,24 @@ export const COMMANDS = [
|
|
|
361
368
|
topics: ["agent", "content"],
|
|
362
369
|
examples: ["frontpage extensions docs charts"],
|
|
363
370
|
},
|
|
371
|
+
{
|
|
372
|
+
name: "images",
|
|
373
|
+
summary: "Generate 1–4 AI image variations of one prompt (counts against AI $ and storage)",
|
|
374
|
+
usage: 'frontpage images generate --prompt "…" [--count N] [--site <slug>] [--json]',
|
|
375
|
+
topics: ["content"],
|
|
376
|
+
examples: [
|
|
377
|
+
'frontpage images generate --prompt "flat illustration of a red stand mixer on marble"',
|
|
378
|
+
'frontpage images generate --prompt "watercolor cafe storefront at dusk" --count 4',
|
|
379
|
+
],
|
|
380
|
+
flags: [
|
|
381
|
+
"One prompt; --count 1–4 is variations of that same picture (default 1)",
|
|
382
|
+
"Human success: sitePath first (markup-safe), then filename",
|
|
383
|
+
"Counts against the site AI $ budget and storage; 402 when the cycle is spent",
|
|
384
|
+
"--count outside 1–4 fails locally (exit 2) with no request",
|
|
385
|
+
"Unknown leftover flags fail closed (exit 2)",
|
|
386
|
+
],
|
|
387
|
+
seeAlso: ["media", "prompt", "help content", "help site-building"],
|
|
388
|
+
},
|
|
364
389
|
{
|
|
365
390
|
name: "media",
|
|
366
391
|
summary: "List or upload site media (images/PDF ≤25 MB, video ≤50 MB)",
|
|
@@ -388,6 +413,45 @@ export const COMMANDS = [
|
|
|
388
413
|
topics: ["content"],
|
|
389
414
|
dangers: ["--mark-read is side-effecting with no confirm"],
|
|
390
415
|
},
|
|
416
|
+
{
|
|
417
|
+
name: "people",
|
|
418
|
+
summary: "List and manage site People (not inbox, not a module)",
|
|
419
|
+
usage: "frontpage people list|get|add|set|note|rm-note|follow-up|hide|unhide [--site <slug>] [--json]",
|
|
420
|
+
topics: ["content"],
|
|
421
|
+
examples: [
|
|
422
|
+
"frontpage people list",
|
|
423
|
+
"frontpage people add --email alex@example.com --name Alex",
|
|
424
|
+
"frontpage people set <id> --status working",
|
|
425
|
+
"frontpage people note <id> --body \"Called them\"",
|
|
426
|
+
"frontpage people follow-up <id> --at 2026-09-12T00:00:00Z",
|
|
427
|
+
"frontpage people hide <id>",
|
|
428
|
+
],
|
|
429
|
+
flags: [
|
|
430
|
+
"list: --q --status --source --form-slug --follow-up due|upcoming|none --hidden --sort --last-seen-days --limit --cursor",
|
|
431
|
+
"add requires --email and/or --phone (never name alone)",
|
|
432
|
+
"Hide is not forget — unique email/phone stay; later ingest un-hides",
|
|
433
|
+
"Unknown leftover flags fail closed (exit 2)",
|
|
434
|
+
],
|
|
435
|
+
seeAlso: ["inbox", "help content"],
|
|
436
|
+
},
|
|
437
|
+
{
|
|
438
|
+
name: "redirects",
|
|
439
|
+
summary: "List, set, or remove HTTP 301/308 path redirects",
|
|
440
|
+
usage: "frontpage redirects list | set --from /old --to /new [--status 301|308] | rm --from /old [--site <slug>] [--json]",
|
|
441
|
+
topics: ["content", "site-building"],
|
|
442
|
+
examples: [
|
|
443
|
+
"frontpage redirects list",
|
|
444
|
+
"frontpage redirects set --from /agents --to /agent",
|
|
445
|
+
"frontpage redirects set --from /old --to /new --status 308",
|
|
446
|
+
"frontpage redirects rm --from /old",
|
|
447
|
+
],
|
|
448
|
+
flags: [
|
|
449
|
+
"Instant — no push or compile. Not a site file. frontpage revert does not undo a redirect.",
|
|
450
|
+
"Same-origin pathnames only. Status 301 (default) or 308. Cap 50 per site.",
|
|
451
|
+
"Unknown leftover flags fail closed (exit 2)",
|
|
452
|
+
],
|
|
453
|
+
seeAlso: ["seo", "help site-building"],
|
|
454
|
+
},
|
|
391
455
|
{
|
|
392
456
|
name: "seo",
|
|
393
457
|
summary: "Get or set page SEO",
|
|
@@ -477,13 +541,14 @@ export const TOPICS = {
|
|
|
477
541
|
4. mkdir work && cd work && frontpage use <subdomain>
|
|
478
542
|
5. frontpage pull
|
|
479
543
|
6. Edit files under src/, public/, or content/
|
|
480
|
-
7. frontpage push --message "…"
|
|
481
|
-
8.
|
|
544
|
+
7. frontpage push --message "…" --wait
|
|
545
|
+
8. frontpage deploy wait # tip compile ready (optional; push --wait does this)
|
|
546
|
+
Review staging: https://<subdomain>.frontpage.host when that subdomain is publicly shareable.
|
|
482
547
|
With a custom domain connected, the subdomain is often owner-private (login wall ≠ failed push);
|
|
483
548
|
anonymous review is on the published custom domain after publish.
|
|
484
|
-
9. frontpage publish
|
|
549
|
+
9. frontpage publish [--wait] # ONLY if the user asked — promotes the ready compile
|
|
485
550
|
|
|
486
|
-
|
|
551
|
+
Push updates the git tip. The site compile is a second clock. deploy wait is not go-live.
|
|
487
552
|
Never publish/unpublish unless the user explicitly asks.
|
|
488
553
|
Agents: read AGENTS.md + frontpage help site-building; use --json for structured I/O.
|
|
489
554
|
More: frontpage help auth | sync | site-building | agent | content | history | isolation | exit-codes`,
|
|
@@ -502,7 +567,7 @@ export const TOPICS = {
|
|
|
502
567
|
frontpage status # tipDrift when remote moved since last pull
|
|
503
568
|
frontpage pull # downloads src/, public/, content/ into cwd
|
|
504
569
|
frontpage diff # local vs remote via git blobSha (--json → dirty + tipDrift)
|
|
505
|
-
frontpage push [--message …] [--wait] # uploads allowlisted files; CAS + active-run guard
|
|
570
|
+
frontpage push [--message …] [--wait] # uploads allowlisted files; deletes remote-only allowlisted paths; CAS + active-run guard
|
|
506
571
|
frontpage ls [prefix]
|
|
507
572
|
frontpage cat <path>
|
|
508
573
|
frontpage search <pattern> [path|--path <path>] [--regex] [--case-sensitive] [--whole-word] [--files-only]
|
|
@@ -511,7 +576,7 @@ export const TOPICS = {
|
|
|
511
576
|
Local state: .frontpage/state.json { slug, baseCommitSha }
|
|
512
577
|
Pull BEFORE EDITING when tip may have moved (UI agent / another checkout) — check tipDrift.
|
|
513
578
|
Pull before push so CAS has baseCommitSha. Do not push while the editor agent is building.
|
|
514
|
-
--wait after push blocks until
|
|
579
|
+
--wait after push blocks until the new commit's site compile is live (agent idle, then GET /deploy ready).
|
|
515
580
|
The UI/canvas agent does not use this CLI; only CLI checkouts need pull.
|
|
516
581
|
Pushing module markup may auto-activate modules (same as the agent).
|
|
517
582
|
tokens.ts may be auto-repaired at commit if it would break the build.
|
|
@@ -520,12 +585,15 @@ export const TOPICS = {
|
|
|
520
585
|
Do not store secrets in the site tree (.env, *.pem, secrets/, credentials.json) — rejected by the API.
|
|
521
586
|
|
|
522
587
|
Staging vs production:
|
|
523
|
-
- Push/prompt/edit update
|
|
524
|
-
-
|
|
525
|
-
- frontpage deploy wait
|
|
526
|
-
-
|
|
588
|
+
- Push/prompt/edit update the git tip. The site compile is a second clock.
|
|
589
|
+
- Review STAGING at https://<subdomain>.frontpage.host after GET /deploy is ready.
|
|
590
|
+
- frontpage deploy wait = agent-run idle (if any) + tip compile ready. It is NOT go-live.
|
|
591
|
+
- A file-only push has no agent run. deploy wait / push --wait must still wait for the compile.
|
|
592
|
+
- frontpage publish promotes the last ready staging compile. 409 if the tip is not built yet.
|
|
593
|
+
- frontpage publish --wait waits for that compile, then publishes. Never publish unless asked.`,
|
|
527
594
|
"site-building": `Site building (Astro contract)
|
|
528
|
-
Stack: Astro 6 + Tailwind v4. Pages in src/pages/. Every page wraps <BaseLayout title description
|
|
595
|
+
Stack: Astro 6 + Tailwind v4. Pages in src/pages/. Every page wraps <BaseLayout title description>,
|
|
596
|
+
or a site layout that itself wraps BaseLayout.
|
|
529
597
|
Control files: src/config/tokens.ts (design tokens), src/config/site.ts (title, nav, pages map, seo).
|
|
530
598
|
|
|
531
599
|
Pages map:
|
|
@@ -537,8 +605,15 @@ export const TOPICS = {
|
|
|
537
605
|
Hard fences:
|
|
538
606
|
- No API routes, serverless backends, or databases.
|
|
539
607
|
- No fake lead forms / checkout / card fields — use data-fp-* modules + frontpage modules, or refuse.
|
|
608
|
+
- Quoted attributes: in frontmatter JS, a backslash-quote is an escape. In an Astro attribute it is
|
|
609
|
+
not. The quote after href= closes the string and the next token fails the compile. Put HTML in a
|
|
610
|
+
frontmatter const and pass it as an expression (auditBody={auditBody}), or use an expression
|
|
611
|
+
attribute. Never put an HTML tag or a backslash-quote inside a quoted JSX attribute.
|
|
540
612
|
- Platform-owned paths are not syncable (BaseLayout overlay, module/extension shells, package.json…).
|
|
541
|
-
- Customer layouts (DocsLayout, GuideLayout, …) are fine when site-owned.
|
|
613
|
+
- Customer layouts (DocsLayout, GuideLayout, …) are fine when site-owned. A wrapper MUST render
|
|
614
|
+
<BaseLayout> and forward SEO: description={description}, ogImage={ogImage}, and
|
|
615
|
+
title={seoTitle ?? derivedFallback} from a 1:1 Astro.props destructure. NEVER title={pageTitle}
|
|
616
|
+
with no seoTitle alias (locks Title/Share image in Search & Social for every page on that layout).
|
|
542
617
|
|
|
543
618
|
Tokens & fonts:
|
|
544
619
|
- Keep required colors/fonts/spacing/radii keys; style via CSS variables / token Tailwind.
|
|
@@ -552,11 +627,13 @@ export const TOPICS = {
|
|
|
552
627
|
- Prefer src/components/Header.astro + Footer.astro (or chrome: { managed: true } in site.ts).
|
|
553
628
|
- seo block in site.ts + frontpage seo get|set; customize 404.astro but keep frontpage:404 meta;
|
|
554
629
|
never put /404 in nav or pages. robots/sitemap are platform-managed.
|
|
630
|
+
- Real HTTP 301/308s: frontpage redirects list|set|rm. Instant (no push). Do not ship Astro.redirect,
|
|
631
|
+
location.replace, or a meta refresh for a permanent move. frontpage revert does not undo redirects.
|
|
555
632
|
|
|
556
633
|
Modules & articles (short):
|
|
557
634
|
- Forms: <form data-fp-form="slug"> with named inputs; no action/onsubmit/honeypot.
|
|
558
635
|
- Articles: frontpage articles …; migrate folders via frontpage prompt (don't invent mass delete+write).
|
|
559
|
-
- Media: frontpage media upload (images/PDF ≤25 MB, video ≤50 MB). Use sitePath /__media/uploads/<slug>/… in markup (not raw blob URLs). Optional ?w= on rasters only.
|
|
636
|
+
- Media: frontpage media upload (images/PDF ≤25 MB, video ≤50 MB). frontpage images generate --prompt "…" [--count N] for 1–4 AI variations of one invented picture (AI $ + storage). Use sitePath /__media/uploads/<slug>/… in markup (not raw blob URLs). Optional ?w= on rasters only.
|
|
560
637
|
|
|
561
638
|
Full guide: https://frontpage.host/developers/site-building
|
|
562
639
|
See also: frontpage help sync | content | AGENTS.md`,
|
|
@@ -568,8 +645,8 @@ export const TOPICS = {
|
|
|
568
645
|
frontpage runs wait [runId] # failed/canceled → exit 2; JSON ok:false + run.error
|
|
569
646
|
frontpage runs cancel <runId>
|
|
570
647
|
frontpage runs retry <runId>
|
|
571
|
-
frontpage deploy wait #
|
|
572
|
-
frontpage publish
|
|
648
|
+
frontpage deploy wait # agent idle + tip compile ready; fail-closed; NOT publish
|
|
649
|
+
frontpage publish [--wait] # ONLY if the user asked — promotes the ready compile
|
|
573
650
|
frontpage unpublish --yes # admin only; never unless asked; --yes when non-TTY
|
|
574
651
|
frontpage usage
|
|
575
652
|
frontpage analytics [--days 7]
|
|
@@ -589,8 +666,11 @@ export const TOPICS = {
|
|
|
589
666
|
Do not publish unless asked.`,
|
|
590
667
|
content: `Content
|
|
591
668
|
frontpage media list|upload <file> # images/PDF/video; text/CSV = inline not library; sitePath first when stored
|
|
669
|
+
frontpage images generate --prompt "…" [--count N] # 1–4 AI variations of one prompt; sitePath first; AI $ + storage
|
|
592
670
|
frontpage inbox [leads|subscribers|orders|google_reviews|…] [--mark-read] [--csv]
|
|
671
|
+
frontpage people list|get|add|set|note|rm-note|follow-up|hide|unhide
|
|
593
672
|
frontpage seo get [/path|--path /path] | seo set --path /
|
|
673
|
+
frontpage redirects list|set|rm --from /old --to /new
|
|
594
674
|
frontpage articles list|content|create-section|create-article|set-draft|…
|
|
595
675
|
frontpage fonts [list|search] [--slot …] [--query …]
|
|
596
676
|
frontpage tokens set --group … --key … --value …
|
|
@@ -619,7 +699,8 @@ export const TOPICS = {
|
|
|
619
699
|
revert creates a NEW commit whose tree matches the target (linear restore).
|
|
620
700
|
Target SHA must be on this site's history (not another site in the monorepo).
|
|
621
701
|
Refused while an agent run is active. Goes through commitSiteBranch (build gate).
|
|
622
|
-
--yes required when stdin is not a TTY
|
|
702
|
+
--yes required when stdin is not a TTY.
|
|
703
|
+
revert does not undo HTTP redirects — use frontpage redirects rm.`,
|
|
623
704
|
isolation: `Isolation
|
|
624
705
|
Every site-scoped call targets subdomain → branch site/<slug> only.
|
|
625
706
|
No client-supplied branch, ref, repo, or clone URL is accepted.
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Frontpage CLI (frontpage-host)
|
|
2
2
|
|
|
3
3
|
- Package: frontpage-host (npm). Binary: frontpage. Do NOT install npm package "frontpage".
|
|
4
|
+
- Astro quoted attributes: in frontmatter JS a backslash-quote is an escape; in an attribute it is not. Pass HTML as {auditBody}. Never HTML or a backslash-quote inside a quoted JSX attribute.
|
|
4
5
|
- Docs in this package: README.md, AGENTS.md (agent operating manual).
|
|
5
6
|
- Introspect: frontpage help | frontpage help --json | frontpage help <topic|command>
|
|
6
7
|
- Topics: quickstart, auth, sync, site-building, agent, content, history, isolation, exit-codes
|
|
@@ -8,20 +9,22 @@
|
|
|
8
9
|
- Fonts: frontpage fonts [--slot] [--query] → exact value → tokens set fonts.<role> → APPLY font-sans|serif|mono|display. Build bundles catalog faces from tokens.ts and/or CSS font-family contexts (not prose). Inline-only without tokens works for catalog faces after rebuild; prefer tokens+utilities for brand roles.
|
|
9
10
|
- Module/extension docs: frontpage modules docs <key> | frontpage extensions docs <key>
|
|
10
11
|
- Search flags: --regex --case-sensitive --whole-word --files-only --context-lines --max-results
|
|
11
|
-
- Modules setup: wizard modules (payments/shop/ordering): frontpage modules <key> connect [--no-open] opens Frontpage (logged-in browser) then Stripe/Square; already-connected stays live. payments/shop connect = admin key; ordering = editor. payments disconnect 409s if shop still uses the shared Stripe account. request-setup remains valid for the editor amber bar. frontpage modules <key> prints that key's CLI usage. Index: https://frontpage.host/developers/modules. Typed config: frontpage modules callbar|forms|booking|signups get|set (forms set needs --instance; confirm emails paid-plan only). google_reviews: frontpage modules google_reviews connect --place-id | --maps-url (server resolve + seed; no Autocomplete; do not write placeId via config). Also status, list-reviews, hide/show, set-stars, set-sort, set-weight, reset-weights, refresh, disconnect. Docs: https://frontpage.host/developers/modules/google-reviews. Markup: data-fp-google-reviews / data-fp-google-ask + required data-fp-requires="google_reviews". Ask scores: frontpage inbox google_reviews.
|
|
12
|
+
- Modules setup: wizard modules (payments/shop/ordering): frontpage modules <key> connect [--no-open] opens Frontpage (logged-in browser) then Stripe/Square; already-connected stays live. payments/shop connect = admin key; ordering = editor. payments disconnect 409s if shop still uses the shared Stripe account. request-setup remains valid for the editor amber bar. frontpage modules <key> prints that key's CLI usage. Index: https://frontpage.host/developers/modules. Typed config: frontpage modules callbar|forms|booking|signups get|set (forms set needs --instance; confirm emails paid-plan only). Form destinations: frontpage modules forms destinations|connect-destination|attach-destination|detach-destination|remove-destination --yes|request-destination-setup (token = admin; request-destination-setup lights the editor bar; request-setup forms is a no-op; connect does not attach every form). Privyr: paste Incoming Webhook URL (https://www.privyr.com/api/v1/incoming-leads/…), not a token. HubSpot: Development → Keys → Service keys or Legacy apps → Auth → Show token. Pipedrive: profile → Company settings → Personal preferences → API. Docs: https://frontpage.host/developers/modules#forms-destinations. google_reviews: frontpage modules google_reviews connect --place-id | --maps-url (server resolve + seed; no Autocomplete; do not write placeId via config). Also status, list-reviews, hide/show, set-stars, set-sort, set-weight, reset-weights, refresh, disconnect. Docs: https://frontpage.host/developers/modules/google-reviews. Markup: data-fp-google-reviews / data-fp-google-ask + required data-fp-requires="google_reviews". Ask scores: frontpage inbox google_reviews.
|
|
12
13
|
- Analytics ops: frontpage analytics summary|query|funnel|timeseries|compare|sql (bare analytics = dashboard)
|
|
13
14
|
- Media: frontpage media upload <file> (images/PDF ≤25 MB, video ≤50 MB, SVG/text ≤4 MB); human prints sitePath first — use /__media/uploads/<slug>/… in markup. Text/CSV is inline only (not media library; --json omits full content).
|
|
14
15
|
- Prompt attachments: frontpage prompt "…" --attach <file|/__media/…|https://…> [--asset-url https://…] (same media caps as media upload)
|
|
15
16
|
- Version: frontpage --version | -V | version
|
|
16
17
|
- SEO get: frontpage seo get [/path|--path /path]; search path filter: [path|--path <path>]; open [/path|--path /path]
|
|
18
|
+
- Redirects: frontpage redirects list|set|rm — HTTP 301/308, instant, not a file; revert does not undo; do not fake with Astro.redirect / meta refresh
|
|
19
|
+
- People: frontpage people list|get|add|set|note|rm-note|follow-up|hide|unhide — site-scoped person graph (email or phone). Inbox stays the raw ledger. Hide is not forget. Unknown leftover flags fail closed.
|
|
17
20
|
- Analytics funnel: --steps JSON array or comma paths (/, /pricing); bad JSON → Invalid JSON for --steps
|
|
18
21
|
- Modules: unknown key errors list Known: …; mailing list module key is signups (not subscribe)
|
|
19
|
-
- Errors: --json API envelopes include requestId when the server returned one; local validation omits requestId/httpStatus; runs wait failed/canceled → ok:false + run.error (exit 2); deploy wait fail-closed; push --wait
|
|
22
|
+
- Errors: --json API envelopes include requestId when the server returned one; local validation omits requestId/httpStatus; runs wait failed/canceled → ok:false + run.error (exit 2); deploy wait = agent idle + tip compile ready (fail-closed / compile timeout → exit 2); push --wait and publish --wait wait for GET /deploy ready
|
|
20
23
|
- Auth: mint fp_live_ key in Frontpage UI (Developers); frontpage login KEY or FRONTPAGE_API_KEY
|
|
21
24
|
- Site id: subdomain only (frontpage use <subdomain>). Not custom domains.
|
|
22
|
-
-
|
|
23
|
-
- Production:
|
|
25
|
+
- Three clocks: git tip (push/prompt/edit) ≠ site compile (GET /deploy ready) ≠ editor agent run (runs wait). File-only push has no agent run.
|
|
26
|
+
- Production: frontpage publish promotes the last ready compile (409 if tip not built). frontpage publish --wait waits then publishes. NEVER publish/unpublish unless the user explicitly asks. Verify live <meta name="frontpage:commit">.
|
|
24
27
|
- Sync: allowlist src/ public/ content/; platform overlay + secret-like paths rejected; pull before edit if tip may have moved (status/diff tipDrift); pull → edit → diff (blobSha) → push [--wait] (CAS); no push during active agent run; UI agent does not use CLI pull; review on subdomain
|
|
25
28
|
- Machine: global --json / --quiet; exit 0/2/3/4/5 (see help exit-codes)
|
|
26
|
-
- deploy wait =
|
|
29
|
+
- deploy wait = agent-run idle (if any) + tip compile ready; it is NOT go-live / publish
|
|
27
30
|
- No runs continue, domains, billing, members, MCP, or git remotes in v1
|