frontpage-host 0.1.17 → 0.1.19

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/dist/compile.js CHANGED
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * GET /api/v1/sites/{slug}/deploy → ready when the live compile SHA equals the tip.
5
5
  */
6
- import { EXIT_OK, EXIT_USAGE, v1Get } from "./http/client.js";
6
+ import { CliHttpError, EXIT_OK, EXIT_USAGE, v1Get } from "./http/client.js";
7
7
  import { progress } from "./runtime.js";
8
8
  const SHA_RE = /^[0-9a-f]{40}$/i;
9
9
  export function normalizeSha(raw) {
@@ -32,6 +32,21 @@ export function compileIsReady(status, expectCommit) {
32
32
  return true;
33
33
  return live === expect;
34
34
  }
35
+ /** Compile clock is gone (flag off / old API). A site-not-found 404 is not this. */
36
+ export function isMissingDeployApi(err) {
37
+ if (!(err instanceof CliHttpError))
38
+ return false;
39
+ const message = err.message.toLowerCase();
40
+ if (message.includes("api not available"))
41
+ return true;
42
+ if (err.status === 404 && (message === "not found." || message === "not found"))
43
+ return true;
44
+ return false;
45
+ }
46
+ /** A deploy payload we can poll. Missing `ready` means the compile clock is not there. */
47
+ export function deployStatusLooksComplete(status) {
48
+ return Boolean(status && typeof status.ready === "boolean");
49
+ }
35
50
  export async function fetchDeployStatus(slug) {
36
51
  return v1Get(`/api/v1/sites/${encodeURIComponent(slug)}/deploy`);
37
52
  }
@@ -42,7 +57,20 @@ export async function waitForCompileReady(args) {
42
57
  const started = Date.now();
43
58
  let last = null;
44
59
  while (Date.now() - started < maxMs) {
45
- last = await fetchStatus(args.slug);
60
+ try {
61
+ last = await fetchStatus(args.slug);
62
+ }
63
+ catch (err) {
64
+ if (isMissingDeployApi(err)) {
65
+ progress("\n");
66
+ return { exitCode: EXIT_USAGE, timedOut: false, failed: true, apiMissing: true, status: null };
67
+ }
68
+ throw err;
69
+ }
70
+ if (!deployStatusLooksComplete(last)) {
71
+ progress("\n");
72
+ return { exitCode: EXIT_USAGE, timedOut: false, failed: true, apiMissing: true, status: last };
73
+ }
46
74
  if (last.compileState === "failed" || last.compileState === "canceled") {
47
75
  progress("\n");
48
76
  return { exitCode: EXIT_USAGE, timedOut: false, failed: true, status: last };
@@ -25,6 +25,7 @@ _frontpage_completions() {
25
25
  seo|settings) COMPREPLY=( $(compgen -W "get set" -- "\${cur}") ) ;;
26
26
  articles) COMPREPLY=( $(compgen -W "list content create-section create-article set-draft" -- "\${cur}") ) ;;
27
27
  analytics) COMPREPLY=( $(compgen -W "dashboard summary query funnel timeseries compare sql" -- "\${cur}") ) ;;
28
+ people) COMPREPLY=( $(compgen -W "list get add set note rm-note follow-up hide unhide" -- "\${cur}") ) ;;
28
29
  modules)
29
30
  if [[ \${COMP_CWORD} -ge 3 && \${COMP_WORDS[2]} == google_reviews ]]; then
30
31
  COMPREPLY=( $(compgen -W "docs request-setup enable disable archive config connect resolve status list-reviews hide show set-stars set-sort set-weight reset-weights write-review-url refresh disconnect" -- "\${cur}") )
@@ -69,6 +70,7 @@ _frontpage() {
69
70
  tokens) _values 'subcommand' set ;;
70
71
  seo|settings) _values 'subcommand' get set ;;
71
72
  analytics) _values 'subcommand' dashboard summary query funnel timeseries compare sql ;;
73
+ people) _values 'subcommand' list get add set note rm-note follow-up hide unhide ;;
72
74
  modules)
73
75
  if [[ $words[2] == google_reviews ]]; then
74
76
  _values 'subcommand' docs request-setup enable disable archive config connect resolve status list-reviews hide show set-stars set-sort set-weight reset-weights write-review-url refresh disconnect
@@ -106,6 +108,7 @@ export function generateFishCompletion() {
106
108
  `complete -c frontpage -n "__fish_seen_subcommand_from tokens" -a "set"`,
107
109
  `complete -c frontpage -n "__fish_seen_subcommand_from seo settings" -a "get set"`,
108
110
  `complete -c frontpage -n "__fish_seen_subcommand_from analytics" -a "dashboard summary query funnel timeseries compare sql"`,
111
+ `complete -c frontpage -n "__fish_seen_subcommand_from people" -a "list get add set note rm-note follow-up hide unhide"`,
109
112
  `complete -c frontpage -n "__fish_seen_subcommand_from modules" -a "list docs request-setup enable disable archive config callbar forms booking signups payments shop ordering articles google_reviews"`,
110
113
  `complete -c frontpage -n "__fish_seen_subcommand_from modules; and __fish_seen_subcommand_from google_reviews" -a "connect resolve status list-reviews hide show set-stars set-sort set-weight reset-weights write-review-url refresh disconnect"`,
111
114
  `complete -c frontpage -n "__fish_seen_subcommand_from modules; and __fish_seen_subcommand_from forms" -a "get set destinations connect-destination remove-destination disconnect-destination attach-destination detach-destination request-destination-setup"`,
@@ -132,8 +132,8 @@ export const MODULE_COMMANDS = [
132
132
  },
133
133
  {
134
134
  key: "payments",
135
- name: "Payments",
136
- summary: "Stripe payments. Connect finishes in the browser, not the terminal.",
135
+ name: "Pay buttons",
136
+ summary: "One-click Stripe pay buttons. No cart. Connect finishes in the browser, not the terminal.",
137
137
  genericActions: GENERIC_ACTIONS,
138
138
  extraActions: [
139
139
  "status",
@@ -151,14 +151,14 @@ export const MODULE_COMMANDS = [
151
151
  ],
152
152
  notes: [
153
153
  "Connect needs an admin API key. It opens Frontpage (you must be logged in there), then Stripe. Already-connected sites stay live — disconnect first to switch accounts.",
154
- "payments and shop share one Stripe account. Disconnecting payments fails if the store still uses that account.",
154
+ "Pay buttons and the Online store share one Stripe account. Disconnecting Pay buttons fails if the store still uses that account.",
155
155
  "request-setup still lights the editor amber bar when you want the owner to finish there.",
156
156
  ],
157
157
  },
158
158
  {
159
159
  key: "shop",
160
160
  name: "Online store",
161
- summary: "Stripe shop. Shares the payments Stripe account.",
161
+ summary: "Catalog, cart, and Stripe checkout. Shares the Pay buttons Stripe account.",
162
162
  genericActions: GENERIC_ACTIONS,
163
163
  extraActions: [
164
164
  "status",
package/dist/registry.js CHANGED
@@ -413,6 +413,97 @@ export const COMMANDS = [
413
413
  topics: ["content"],
414
414
  dangers: ["--mark-read is side-effecting with no confirm"],
415
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|tag|export [--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
+ "frontpage people tag <id> --add vip",
429
+ "frontpage people list --tag vip",
430
+ "frontpage people export",
431
+ ],
432
+ flags: [
433
+ "list: --q --status --source --form-slug --follow-up due|upcoming|none --hidden --sort --last-seen-days --tag --limit --cursor",
434
+ "add requires --email and/or --phone (never name alone)",
435
+ "tag: --add <label> | --remove <slug>",
436
+ "export writes UTF-8 CSV (same filters as list). Optional --out <file>",
437
+ "Hide is not forget. Unique email/phone stay; later ingest un-hides",
438
+ "Unknown leftover flags fail closed (exit 2)",
439
+ ],
440
+ seeAlso: ["inbox", "https://frontpage.host/developers/people"],
441
+ },
442
+ {
443
+ name: "shop",
444
+ summary: "Store catalog: items, variants, stock, and store settings (not Square, not inbox)",
445
+ usage: "frontpage shop items|variants|settings|orders|payments … [--site <slug>] [--json]",
446
+ topics: ["content"],
447
+ examples: [
448
+ "frontpage shop items list",
449
+ "frontpage shop items create camp-hat --title \"Camp hat\" --price-cents 4999 --checkout cart --requires-shipping true --stock 20",
450
+ "frontpage shop variants add camp-hat --id m --option Size=M --price-cents 4999 --stock 8",
451
+ "frontpage shop items stock camp-hat --variant m --add 5",
452
+ "frontpage shop items stock camp-hat --variant m --remove 5",
453
+ "frontpage shop items stock camp-hat --variant m --set 20",
454
+ "frontpage shop settings set-fulfillment --mode pickup",
455
+ "frontpage shop settings set-currency --currency usd",
456
+ ],
457
+ flags: [
458
+ "Integer cents only. $49.99 is 4999. Do not send 49.99 or a dollar string.",
459
+ "--add / --remove become signed delta. 5 adds 5. --remove 5 removes 5. Result copy is added 5 / removed 5 / set to 20 / stockNow.",
460
+ "Pass either --add, --remove, or --set. Never two together. --set unlimited returns counted stock to unlimited.",
461
+ "items: list|get|create|update|archive|activate [--off] | images --urls … | stock [--variant m] --add|--remove|--set",
462
+ "variants: add|update|archive <itemId> --id m --price-cents … [--option Size=M] [--stock]",
463
+ "settings: get|set-fulfillment|set-currency|set-checkout-fee. Connect stays frontpage modules shop|payments connect.",
464
+ "orders / payments list|get read the same ledgers as frontpage inbox orders|payments",
465
+ "Unknown leftover flags fail closed (exit 2)",
466
+ ],
467
+ seeAlso: ["inbox", "https://frontpage.host/developers/shop"],
468
+ },
469
+ {
470
+ name: "mail",
471
+ summary: "Site mailings: drafts, templates, series, and sends (not People, not inbox)",
472
+ usage: "frontpage mail settings|email|template|series|send|sends|enrolments|suppress … [--site <slug>] [--json]",
473
+ topics: ["content"],
474
+ examples: [
475
+ "frontpage mail settings set --postal \"100 Main St\" --reply-to you@example.com",
476
+ "frontpage mail email create --file draft.json --name Hours",
477
+ "frontpage mail send --file email.json --to ada@example.com --wait",
478
+ "frontpage mail send template <id> --to ada@example.com --var first_name=Ada",
479
+ "frontpage mail series steps set <id> --file steps.json",
480
+ "frontpage mail suppress add --email bounce@example.com",
481
+ ],
482
+ flags: [
483
+ "email list is unsent drafts only. Sent one-offs are mail sends list",
484
+ "send --file is an inline one-off (no saved document)",
485
+ "Blocks and series steps are JSON (--file). Unknown leftover flags fail closed (exit 2)",
486
+ ],
487
+ seeAlso: ["people", "inbox"],
488
+ },
489
+ {
490
+ name: "redirects",
491
+ summary: "List, set, or remove HTTP 301/308 path redirects",
492
+ usage: "frontpage redirects list | set --from /old --to /new [--status 301|308] | rm --from /old [--site <slug>] [--json]",
493
+ topics: ["content", "site-building"],
494
+ examples: [
495
+ "frontpage redirects list",
496
+ "frontpage redirects set --from /agents --to /agent",
497
+ "frontpage redirects set --from /old --to /new --status 308",
498
+ "frontpage redirects rm --from /old",
499
+ ],
500
+ flags: [
501
+ "Instant — no push or compile. Not a site file. frontpage revert does not undo a redirect.",
502
+ "Same-origin pathnames only. Status 301 (default) or 308. Cap 50 per site.",
503
+ "Unknown leftover flags fail closed (exit 2)",
504
+ ],
505
+ seeAlso: ["seo", "help site-building"],
506
+ },
416
507
  {
417
508
  name: "seo",
418
509
  summary: "Get or set page SEO",
@@ -502,7 +593,7 @@ export const TOPICS = {
502
593
  4. mkdir work && cd work && frontpage use <subdomain>
503
594
  5. frontpage pull
504
595
  6. Edit files under src/, public/, or content/
505
- 7. frontpage push --message "…"
596
+ 7. frontpage push --message "…" --wait
506
597
  8. frontpage deploy wait # tip compile ready (optional; push --wait does this)
507
598
  Review staging: https://<subdomain>.frontpage.host when that subdomain is publicly shareable.
508
599
  With a custom domain connected, the subdomain is often owner-private (login wall ≠ failed push);
@@ -528,7 +619,7 @@ export const TOPICS = {
528
619
  frontpage status # tipDrift when remote moved since last pull
529
620
  frontpage pull # downloads src/, public/, content/ into cwd
530
621
  frontpage diff # local vs remote via git blobSha (--json → dirty + tipDrift)
531
- frontpage push [--message …] [--wait] # uploads allowlisted files; CAS + active-run guard
622
+ frontpage push [--message …] [--wait] # uploads allowlisted files; deletes remote-only allowlisted paths; CAS + active-run guard
532
623
  frontpage ls [prefix]
533
624
  frontpage cat <path>
534
625
  frontpage search <pattern> [path|--path <path>] [--regex] [--case-sensitive] [--whole-word] [--files-only]
@@ -566,6 +657,10 @@ export const TOPICS = {
566
657
  Hard fences:
567
658
  - No API routes, serverless backends, or databases.
568
659
  - No fake lead forms / checkout / card fields — use data-fp-* modules + frontpage modules, or refuse.
660
+ - Quoted attributes: in frontmatter JS, a backslash-quote is an escape. In an Astro attribute it is
661
+ not. The quote after href= closes the string and the next token fails the compile. Put HTML in a
662
+ frontmatter const and pass it as an expression (auditBody={auditBody}), or use an expression
663
+ attribute. Never put an HTML tag or a backslash-quote inside a quoted JSX attribute.
569
664
  - Platform-owned paths are not syncable (BaseLayout overlay, module/extension shells, package.json…).
570
665
  - Customer layouts (DocsLayout, GuideLayout, …) are fine when site-owned. A wrapper MUST render
571
666
  <BaseLayout> and forward SEO: description={description}, ogImage={ogImage}, and
@@ -584,6 +679,8 @@ export const TOPICS = {
584
679
  - Prefer src/components/Header.astro + Footer.astro (or chrome: { managed: true } in site.ts).
585
680
  - seo block in site.ts + frontpage seo get|set; customize 404.astro but keep frontpage:404 meta;
586
681
  never put /404 in nav or pages. robots/sitemap are platform-managed.
682
+ - Real HTTP 301/308s: frontpage redirects list|set|rm. Instant (no push). Do not ship Astro.redirect,
683
+ location.replace, or a meta refresh for a permanent move. frontpage revert does not undo redirects.
587
684
 
588
685
  Modules & articles (short):
589
686
  - Forms: <form data-fp-form="slug"> with named inputs; no action/onsubmit/honeypot.
@@ -623,7 +720,14 @@ export const TOPICS = {
623
720
  frontpage media list|upload <file> # images/PDF/video; text/CSV = inline not library; sitePath first when stored
624
721
  frontpage images generate --prompt "…" [--count N] # 1–4 AI variations of one prompt; sitePath first; AI $ + storage
625
722
  frontpage inbox [leads|subscribers|orders|google_reviews|…] [--mark-read] [--csv]
723
+ frontpage people list|get|add|set|note|rm-note|follow-up|hide|unhide|tag|export
724
+ # People CRM guide: https://frontpage.host/developers/people
725
+ frontpage shop items|variants|settings|orders|payments
726
+ # Store catalog: https://frontpage.host/developers/shop
727
+ # Integer cents only. $49.99 is 4999. stock --add/--remove are signed delta.
728
+ frontpage mail settings|email|template|series|send|sends|enrolments|suppress
626
729
  frontpage seo get [/path|--path /path] | seo set --path /
730
+ frontpage redirects list|set|rm --from /old --to /new
627
731
  frontpage articles list|content|create-section|create-article|set-draft|…
628
732
  frontpage fonts [list|search] [--slot …] [--query …]
629
733
  frontpage tokens set --group … --key … --value …
@@ -652,7 +756,8 @@ export const TOPICS = {
652
756
  revert creates a NEW commit whose tree matches the target (linear restore).
653
757
  Target SHA must be on this site's history (not another site in the monorepo).
654
758
  Refused while an agent run is active. Goes through commitSiteBranch (build gate).
655
- --yes required when stdin is not a TTY.`,
759
+ --yes required when stdin is not a TTY.
760
+ revert does not undo HTTP redirects — use frontpage redirects rm.`,
656
761
  isolation: `Isolation
657
762
  Every site-scoped call targets subdomain → branch site/<slug> only.
658
763
  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
@@ -14,6 +15,9 @@
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 CRM: frontpage people list|get|add|set|note|rm-note|follow-up|hide|unhide|tag|export. Site-scoped person graph (email or phone). Inbox stays the raw ledger. Hide is not forget. List export is CSV. Unknown leftover flags fail closed. Guide: https://frontpage.host/developers/people
20
+ - Store catalog: frontpage shop items|variants|settings|orders|payments. Integer cents only ($49.99 is 4999). stock --add/--remove are signed delta (added 5 / removed 5 / set to 20 / stockNow). Connect stays frontpage modules shop|payments connect. Not Square ordering. Guide: https://frontpage.host/developers/shop
17
21
  - Analytics funnel: --steps JSON array or comma paths (/, /pricing); bad JSON → Invalid JSON for --steps
18
22
  - Modules: unknown key errors list Known: …; mailing list module key is signups (not subscribe)
19
23
  - 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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frontpage-host",
3
- "version": "0.1.17",
3
+ "version": "0.1.19",
4
4
  "description": "Frontpage CLI — manage your site from the terminal",
5
5
  "type": "module",
6
6
  "bin": {