frontpage-host 0.1.4 → 0.1.5
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 +1 -1
- package/dist/bin.js +6 -0
- package/dist/commands/extensions.js +15 -1
- package/dist/commands/fonts.d.ts +1 -0
- package/dist/commands/fonts.js +71 -0
- package/dist/commands/modules.js +18 -1
- package/dist/commands/search.js +58 -8
- package/dist/commands/tokens.d.ts +1 -0
- package/dist/commands/tokens.js +64 -0
- package/dist/completions/generate.js +10 -4
- package/dist/registry.js +53 -9
- package/llms.txt +3 -0
- package/package.json +1 -1
package/AGENTS.md
CHANGED
|
@@ -100,7 +100,7 @@ Sites are Astro 6 + Tailwind v4. More detail: `frontpage help site-building` or
|
|
|
100
100
|
2. **`src/config/site.ts`** — keep `pages` (path registry) and `nav` in sync when adding/renaming/deleting page files. Tab title comes from BaseLayout, not the `pages` map label.
|
|
101
101
|
3. **One file per URL** for similar page sets (services, guides, …). Do not default to `getStaticPaths()` over `src/data/*.ts`. Blog/news → `frontpage articles`, not a hand-rolled catalog.
|
|
102
102
|
4. **No backends / databases / fake forms or checkout.** Real forms use `<form data-fp-form="slug">` + `frontpage modules`. Refuse or use modules for payments.
|
|
103
|
-
5. **Tokens** in `src/config/tokens.ts` — keep required color/font/spacing/radii keys; style via CSS variables / token Tailwind. Setting a font token is not enough — apply `font-sans` / `font-serif` / `font-display`.
|
|
103
|
+
5. **Tokens** in `src/config/tokens.ts` — keep required color/font/spacing/radii keys; style via CSS variables / token Tailwind. Setting a font token is not enough — apply `font-sans` / `font-serif` / `font-display`. Browse fonts with `frontpage fonts`; set one token with `frontpage tokens set --group … --key … --value …` (CAS like push). Module how-tos: `frontpage modules docs <key>` / `frontpage extensions docs <key>`.
|
|
104
104
|
6. **Shared chrome** — prefer `src/components/Header.astro` + `Footer.astro` (or `chrome: { managed: true }` in `site.ts`).
|
|
105
105
|
7. **404** — customize `src/pages/404.astro` if needed; keep `frontpage:404` meta; never register `/404` in `nav`/`pages`.
|
|
106
106
|
8. **Platform-owned paths** stay off-limits (BaseLayout overlay, module/extension shells, `package.json`, …). Customer layouts like `DocsLayout` / `GuideLayout` are OK.
|
package/dist/bin.js
CHANGED
|
@@ -29,6 +29,8 @@ import { runSeo } from "./commands/seo.js";
|
|
|
29
29
|
import { runArticles } from "./commands/articles.js";
|
|
30
30
|
import { runSettings } from "./commands/settings.js";
|
|
31
31
|
import { runEdit } from "./commands/edit.js";
|
|
32
|
+
import { runFonts } from "./commands/fonts.js";
|
|
33
|
+
import { runTokens } from "./commands/tokens.js";
|
|
32
34
|
import { runHistory } from "./commands/history.js";
|
|
33
35
|
import { runRevert } from "./commands/revert.js";
|
|
34
36
|
import { runCompletion } from "./commands/completion.js";
|
|
@@ -110,6 +112,10 @@ async function main() {
|
|
|
110
112
|
return runSettings(args);
|
|
111
113
|
case "edit":
|
|
112
114
|
return runEdit(args);
|
|
115
|
+
case "fonts":
|
|
116
|
+
return runFonts(args);
|
|
117
|
+
case "tokens":
|
|
118
|
+
return runTokens(args);
|
|
113
119
|
case "history":
|
|
114
120
|
return runHistory(args);
|
|
115
121
|
case "revert":
|
|
@@ -23,6 +23,20 @@ export async function runExtensions(args) {
|
|
|
23
23
|
}
|
|
24
24
|
return EXIT_OK;
|
|
25
25
|
}
|
|
26
|
+
if (sub === "docs" || sub === "doc") {
|
|
27
|
+
const key = rest[1];
|
|
28
|
+
if (!key) {
|
|
29
|
+
console.error("Usage: frontpage extensions docs <key> [--site <slug>]");
|
|
30
|
+
return EXIT_USAGE;
|
|
31
|
+
}
|
|
32
|
+
const data = await v1Get(`/api/v1/sites/${encodeURIComponent(slug)}/extensions/${encodeURIComponent(key)}`);
|
|
33
|
+
console.log(`# ${data.key} (${data.name}) [${data.state}]`);
|
|
34
|
+
if (data.note)
|
|
35
|
+
console.log(data.note);
|
|
36
|
+
console.log("");
|
|
37
|
+
console.log(data.docs);
|
|
38
|
+
return EXIT_OK;
|
|
39
|
+
}
|
|
26
40
|
if (sub === "enable" || sub === "disable" || sub === "config") {
|
|
27
41
|
const key = rest[1];
|
|
28
42
|
if (!key) {
|
|
@@ -50,7 +64,7 @@ export async function runExtensions(args) {
|
|
|
50
64
|
console.log(JSON.stringify(data, null, 2));
|
|
51
65
|
return EXIT_OK;
|
|
52
66
|
}
|
|
53
|
-
console.error("Usage: frontpage extensions [list|enable|disable|config] …");
|
|
67
|
+
console.error("Usage: frontpage extensions [list|docs|enable|disable|config] …");
|
|
54
68
|
return EXIT_USAGE;
|
|
55
69
|
}
|
|
56
70
|
catch (err) {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runFonts(args: string[]): Promise<number>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { EXIT_OK, EXIT_USAGE, exitCodeForError, v1Get } from "../http/client.js";
|
|
2
|
+
import { emitErr, emitOk, isJson } from "../runtime.js";
|
|
3
|
+
function takeFlag(rest, name) {
|
|
4
|
+
const i = rest.indexOf(name);
|
|
5
|
+
if (i === -1)
|
|
6
|
+
return undefined;
|
|
7
|
+
const v = rest[i + 1];
|
|
8
|
+
rest.splice(i, 2);
|
|
9
|
+
return v;
|
|
10
|
+
}
|
|
11
|
+
function hasFlag(rest, name) {
|
|
12
|
+
const i = rest.indexOf(name);
|
|
13
|
+
if (i === -1)
|
|
14
|
+
return false;
|
|
15
|
+
rest.splice(i, 1);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
export async function runFonts(args) {
|
|
19
|
+
try {
|
|
20
|
+
const work = [...args];
|
|
21
|
+
let sub = work[0];
|
|
22
|
+
if (sub === "list" || sub === "search" || sub === "ls") {
|
|
23
|
+
work.shift();
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
sub = "list";
|
|
27
|
+
}
|
|
28
|
+
const slot = takeFlag(work, "--slot");
|
|
29
|
+
const query = takeFlag(work, "--query") ??
|
|
30
|
+
(sub === "search" ? work.shift() : undefined) ??
|
|
31
|
+
(work[0] && !work[0].startsWith("-") ? work.shift() : undefined);
|
|
32
|
+
const variableOnly = hasFlag(work, "--variable-only");
|
|
33
|
+
const limit = takeFlag(work, "--limit");
|
|
34
|
+
const offset = takeFlag(work, "--offset");
|
|
35
|
+
if (sub === "search" && !query) {
|
|
36
|
+
console.error("Usage: frontpage fonts search <query> [--slot …] [--variable-only] [--limit N]");
|
|
37
|
+
return EXIT_USAGE;
|
|
38
|
+
}
|
|
39
|
+
const q = new URLSearchParams();
|
|
40
|
+
if (slot)
|
|
41
|
+
q.set("slot", slot);
|
|
42
|
+
if (query)
|
|
43
|
+
q.set("query", query);
|
|
44
|
+
if (variableOnly)
|
|
45
|
+
q.set("variableOnly", "true");
|
|
46
|
+
if (limit)
|
|
47
|
+
q.set("limit", limit);
|
|
48
|
+
if (offset)
|
|
49
|
+
q.set("offset", offset);
|
|
50
|
+
const path = `/api/v1/fonts${q.toString() ? `?${q.toString()}` : ""}`;
|
|
51
|
+
const data = await v1Get(path);
|
|
52
|
+
if (isJson()) {
|
|
53
|
+
emitOk("fonts", data);
|
|
54
|
+
return EXIT_OK;
|
|
55
|
+
}
|
|
56
|
+
for (const f of data.fonts ?? []) {
|
|
57
|
+
const varMark = f.variable ? "var" : " ";
|
|
58
|
+
console.log(`${f.slot.padEnd(8)} ${varMark} ${f.family.padEnd(28)} ${f.value}`);
|
|
59
|
+
}
|
|
60
|
+
console.log(`(${data.returned}/${data.total} fonts${data.hasMore ? "; more available" : ""})`);
|
|
61
|
+
if (data.hint)
|
|
62
|
+
console.error(data.hint);
|
|
63
|
+
return EXIT_OK;
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
if (isJson())
|
|
67
|
+
return emitErr("fonts", err);
|
|
68
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
69
|
+
return exitCodeForError(err);
|
|
70
|
+
}
|
|
71
|
+
}
|
package/dist/commands/modules.js
CHANGED
|
@@ -19,6 +19,23 @@ export async function runModules(args) {
|
|
|
19
19
|
}
|
|
20
20
|
return EXIT_OK;
|
|
21
21
|
}
|
|
22
|
+
if (sub === "docs" || sub === "doc") {
|
|
23
|
+
const key = rest[1];
|
|
24
|
+
if (!key) {
|
|
25
|
+
console.error("Usage: frontpage modules docs <key> [--instance <id>] [--site <slug>]");
|
|
26
|
+
return EXIT_USAGE;
|
|
27
|
+
}
|
|
28
|
+
const work = rest.slice(2);
|
|
29
|
+
const instanceId = takeFlag(work, "--instance");
|
|
30
|
+
const q = instanceId ? `?instanceId=${encodeURIComponent(instanceId)}` : "";
|
|
31
|
+
const data = await v1Get(`/api/v1/sites/${encodeURIComponent(slug)}/modules/${encodeURIComponent(key)}${q}`);
|
|
32
|
+
console.log(`# ${data.key} (${data.status})`);
|
|
33
|
+
if (data.note)
|
|
34
|
+
console.log(data.note);
|
|
35
|
+
console.log("");
|
|
36
|
+
console.log(data.docs);
|
|
37
|
+
return EXIT_OK;
|
|
38
|
+
}
|
|
22
39
|
if (sub === "enable" || sub === "disable" || sub === "archive" || sub === "config") {
|
|
23
40
|
const key = rest[1];
|
|
24
41
|
if (!key) {
|
|
@@ -46,7 +63,7 @@ export async function runModules(args) {
|
|
|
46
63
|
console.log(JSON.stringify(data, null, 2));
|
|
47
64
|
return EXIT_OK;
|
|
48
65
|
}
|
|
49
|
-
console.error("Usage: frontpage modules [list|enable|disable|archive|config] …");
|
|
66
|
+
console.error("Usage: frontpage modules [list|docs|enable|disable|archive|config] …");
|
|
50
67
|
return EXIT_USAGE;
|
|
51
68
|
}
|
|
52
69
|
catch (err) {
|
package/dist/commands/search.js
CHANGED
|
@@ -1,29 +1,79 @@
|
|
|
1
1
|
import { resolveSlug } from "../site.js";
|
|
2
2
|
import { EXIT_OK, EXIT_USAGE, exitCodeForError, v1Get } from "../http/client.js";
|
|
3
|
+
import { emitErr, emitOk, isJson } from "../runtime.js";
|
|
4
|
+
function takeFlag(rest, name) {
|
|
5
|
+
const i = rest.indexOf(name);
|
|
6
|
+
if (i === -1)
|
|
7
|
+
return undefined;
|
|
8
|
+
const v = rest[i + 1];
|
|
9
|
+
rest.splice(i, 2);
|
|
10
|
+
return v;
|
|
11
|
+
}
|
|
12
|
+
function hasFlag(rest, name) {
|
|
13
|
+
const i = rest.indexOf(name);
|
|
14
|
+
if (i === -1)
|
|
15
|
+
return false;
|
|
16
|
+
rest.splice(i, 1);
|
|
17
|
+
return true;
|
|
18
|
+
}
|
|
3
19
|
export async function runSearch(args) {
|
|
4
20
|
try {
|
|
5
21
|
const { slug, rest } = await resolveSlug(args);
|
|
6
|
-
const
|
|
22
|
+
const work = [...rest];
|
|
23
|
+
const regex = hasFlag(work, "--regex");
|
|
24
|
+
const caseSensitive = hasFlag(work, "--case-sensitive");
|
|
25
|
+
const wholeWord = hasFlag(work, "--whole-word");
|
|
26
|
+
const filesOnly = hasFlag(work, "--files-only");
|
|
27
|
+
const contextLines = takeFlag(work, "--context-lines");
|
|
28
|
+
const maxResults = takeFlag(work, "--max-results");
|
|
29
|
+
const pattern = work[0];
|
|
7
30
|
if (!pattern) {
|
|
8
|
-
console.error("Usage: frontpage search <pattern> [--site <slug>]");
|
|
31
|
+
console.error("Usage: frontpage search <pattern> [path] [--regex] [--case-sensitive] [--whole-word] [--files-only] [--context-lines N] [--max-results N] [--site <slug>]");
|
|
9
32
|
return EXIT_USAGE;
|
|
10
33
|
}
|
|
34
|
+
const pathFilter = work[1] && !work[1].startsWith("-") ? work[1] : undefined;
|
|
11
35
|
const q = new URLSearchParams({ pattern });
|
|
12
|
-
const pathFilter = rest[1];
|
|
13
36
|
if (pathFilter)
|
|
14
37
|
q.set("path", pathFilter);
|
|
38
|
+
if (regex)
|
|
39
|
+
q.set("regex", "true");
|
|
40
|
+
if (caseSensitive)
|
|
41
|
+
q.set("caseSensitive", "true");
|
|
42
|
+
if (wholeWord)
|
|
43
|
+
q.set("wholeWord", "true");
|
|
44
|
+
if (filesOnly)
|
|
45
|
+
q.set("filesOnly", "true");
|
|
46
|
+
if (contextLines)
|
|
47
|
+
q.set("contextLines", contextLines);
|
|
48
|
+
if (maxResults)
|
|
49
|
+
q.set("maxResults", maxResults);
|
|
15
50
|
const data = await v1Get(`/api/v1/sites/${encodeURIComponent(slug)}/search?${q.toString()}`);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
51
|
+
if (isJson()) {
|
|
52
|
+
emitOk("search", data);
|
|
53
|
+
return EXIT_OK;
|
|
54
|
+
}
|
|
55
|
+
if (filesOnly || data.filesOnly) {
|
|
56
|
+
const files = data.files ?? [];
|
|
57
|
+
for (const f of files)
|
|
58
|
+
console.log(f);
|
|
59
|
+
if (files.length === 0)
|
|
60
|
+
console.error("(no matches)");
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
const matches = data.matches ?? [];
|
|
64
|
+
for (const m of matches) {
|
|
65
|
+
console.log(`${m.file}:${m.lineNumber}: ${m.line}`);
|
|
66
|
+
}
|
|
67
|
+
if (matches.length === 0)
|
|
68
|
+
console.error("(no matches)");
|
|
19
69
|
}
|
|
20
|
-
if (matches.length === 0)
|
|
21
|
-
console.error("(no matches)");
|
|
22
70
|
if (data.truncated || data.scanTruncated)
|
|
23
71
|
console.error("# results truncated");
|
|
24
72
|
return EXIT_OK;
|
|
25
73
|
}
|
|
26
74
|
catch (err) {
|
|
75
|
+
if (isJson())
|
|
76
|
+
return emitErr("search", err);
|
|
27
77
|
console.error(err instanceof Error ? err.message : String(err));
|
|
28
78
|
return exitCodeForError(err);
|
|
29
79
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runTokens(args: string[]): Promise<number>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { resolveSlug } from "../site.js";
|
|
2
|
+
import { EXIT_OK, EXIT_USAGE, exitCodeForError, v1Post } from "../http/client.js";
|
|
3
|
+
import { readState, writeState } from "../state/frontpage-state.js";
|
|
4
|
+
import { emitErr, emitOk, emitUsage, isJson } from "../runtime.js";
|
|
5
|
+
function takeFlag(rest, name) {
|
|
6
|
+
const i = rest.indexOf(name);
|
|
7
|
+
if (i === -1)
|
|
8
|
+
return undefined;
|
|
9
|
+
const v = rest[i + 1];
|
|
10
|
+
rest.splice(i, 2);
|
|
11
|
+
return v;
|
|
12
|
+
}
|
|
13
|
+
export async function runTokens(args) {
|
|
14
|
+
try {
|
|
15
|
+
const { slug, rest } = await resolveSlug(args);
|
|
16
|
+
const sub = rest[0];
|
|
17
|
+
if (sub !== "set") {
|
|
18
|
+
console.error("Usage: frontpage tokens set --group <colors|fonts|spacing|radii|article> --key <name> --value <…> [--site <slug>]");
|
|
19
|
+
return EXIT_USAGE;
|
|
20
|
+
}
|
|
21
|
+
const work = rest.slice(1);
|
|
22
|
+
const group = takeFlag(work, "--group");
|
|
23
|
+
const key = takeFlag(work, "--key");
|
|
24
|
+
const value = takeFlag(work, "--value");
|
|
25
|
+
if (!group || !key || value === undefined) {
|
|
26
|
+
return emitUsage("tokens", "Usage: frontpage tokens set --group <…> --key <…> --value <…> [--site <slug>]", EXIT_USAGE);
|
|
27
|
+
}
|
|
28
|
+
const cwd = process.cwd();
|
|
29
|
+
const state = await readState(cwd);
|
|
30
|
+
if (!state.baseCommitSha) {
|
|
31
|
+
return emitUsage("tokens", "No baseCommitSha in .frontpage/state.json. Run: frontpage pull", EXIT_USAGE);
|
|
32
|
+
}
|
|
33
|
+
const data = await v1Post(`/api/v1/sites/${encodeURIComponent(slug)}/tokens`, {
|
|
34
|
+
group,
|
|
35
|
+
key,
|
|
36
|
+
value,
|
|
37
|
+
baseCommitSha: state.baseCommitSha,
|
|
38
|
+
expectedHeadSha: state.baseCommitSha,
|
|
39
|
+
});
|
|
40
|
+
if (data.commitSha) {
|
|
41
|
+
await writeState({ ...state, slug, baseCommitSha: data.commitSha }, cwd);
|
|
42
|
+
}
|
|
43
|
+
if (isJson()) {
|
|
44
|
+
emitOk("tokens", { slug, ...data });
|
|
45
|
+
return EXIT_OK;
|
|
46
|
+
}
|
|
47
|
+
if (!data.changed) {
|
|
48
|
+
console.log(`No change (${group}.${key} already set).`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log(`Set ${group}.${key} → ${data.commitSha}`);
|
|
52
|
+
console.log("Updated .frontpage/state.json baseCommitSha");
|
|
53
|
+
}
|
|
54
|
+
if (data.warning)
|
|
55
|
+
console.error(`Warning: ${data.warning}`);
|
|
56
|
+
return EXIT_OK;
|
|
57
|
+
}
|
|
58
|
+
catch (err) {
|
|
59
|
+
if (isJson())
|
|
60
|
+
return emitErr("tokens", err);
|
|
61
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
62
|
+
return exitCodeForError(err);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
@@ -19,10 +19,12 @@ _frontpage_completions() {
|
|
|
19
19
|
runs) COMPREPLY=( $(compgen -W "list current wait cancel retry get" -- "\${cur}") ) ;;
|
|
20
20
|
deploy) COMPREPLY=( $(compgen -W "wait" -- "\${cur}") ) ;;
|
|
21
21
|
media) COMPREPLY=( $(compgen -W "list upload" -- "\${cur}") ) ;;
|
|
22
|
+
fonts) COMPREPLY=( $(compgen -W "list search" -- "\${cur}") ) ;;
|
|
23
|
+
tokens) COMPREPLY=( $(compgen -W "set" -- "\${cur}") ) ;;
|
|
22
24
|
seo|settings) COMPREPLY=( $(compgen -W "get set" -- "\${cur}") ) ;;
|
|
23
25
|
articles) COMPREPLY=( $(compgen -W "list content create-section create-article set-draft" -- "\${cur}") ) ;;
|
|
24
|
-
modules) COMPREPLY=( $(compgen -W "list enable disable archive config" -- "\${cur}") ) ;;
|
|
25
|
-
extensions) COMPREPLY=( $(compgen -W "list enable disable config" -- "\${cur}") ) ;;
|
|
26
|
+
modules) COMPREPLY=( $(compgen -W "list docs enable disable archive config" -- "\${cur}") ) ;;
|
|
27
|
+
extensions) COMPREPLY=( $(compgen -W "list docs enable disable config" -- "\${cur}") ) ;;
|
|
26
28
|
*) COMPREPLY=( $(compgen -W "--site --help --json --quiet --yes" -- "\${cur}") ) ;;
|
|
27
29
|
esac
|
|
28
30
|
}
|
|
@@ -45,8 +47,10 @@ _frontpage() {
|
|
|
45
47
|
runs) _values 'subcommand' current wait cancel retry get ;;
|
|
46
48
|
deploy) _values 'subcommand' wait ;;
|
|
47
49
|
media) _values 'subcommand' list upload ;;
|
|
50
|
+
fonts) _values 'subcommand' list search ;;
|
|
51
|
+
tokens) _values 'subcommand' set ;;
|
|
48
52
|
seo|settings) _values 'subcommand' get set ;;
|
|
49
|
-
modules|extensions) _values 'subcommand' list enable disable config ;;
|
|
53
|
+
modules|extensions) _values 'subcommand' list docs enable disable config ;;
|
|
50
54
|
esac
|
|
51
55
|
;;
|
|
52
56
|
esac
|
|
@@ -63,8 +67,10 @@ export function generateFishCompletion() {
|
|
|
63
67
|
`complete -c frontpage -n "__fish_seen_subcommand_from runs" -a "current wait cancel retry get"`,
|
|
64
68
|
`complete -c frontpage -n "__fish_seen_subcommand_from deploy" -a "wait"`,
|
|
65
69
|
`complete -c frontpage -n "__fish_seen_subcommand_from media" -a "list upload"`,
|
|
70
|
+
`complete -c frontpage -n "__fish_seen_subcommand_from fonts" -a "list search"`,
|
|
71
|
+
`complete -c frontpage -n "__fish_seen_subcommand_from tokens" -a "set"`,
|
|
66
72
|
`complete -c frontpage -n "__fish_seen_subcommand_from seo settings" -a "get set"`,
|
|
67
|
-
`complete -c frontpage -n "__fish_seen_subcommand_from modules extensions" -a "list enable disable config"`,
|
|
73
|
+
`complete -c frontpage -n "__fish_seen_subcommand_from modules extensions" -a "list docs enable disable config"`,
|
|
68
74
|
`complete -c frontpage -l site -d "Site subdomain slug"`,
|
|
69
75
|
];
|
|
70
76
|
return `${lines.join("\n")}\n`;
|
package/dist/registry.js
CHANGED
|
@@ -126,8 +126,47 @@ export const COMMANDS = [
|
|
|
126
126
|
{
|
|
127
127
|
name: "search",
|
|
128
128
|
summary: "Search remote text files",
|
|
129
|
-
usage: "frontpage search <pattern> [path] [--site <slug>]",
|
|
129
|
+
usage: "frontpage search <pattern> [path] [--regex] [--case-sensitive] [--whole-word] [--files-only] [--context-lines N] [--max-results N] [--site <slug>] [--json]",
|
|
130
130
|
topics: ["sync"],
|
|
131
|
+
flags: [
|
|
132
|
+
"--regex",
|
|
133
|
+
"--case-sensitive",
|
|
134
|
+
"--whole-word",
|
|
135
|
+
"--files-only",
|
|
136
|
+
"--context-lines <n>",
|
|
137
|
+
"--max-results <n>",
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: "fonts",
|
|
142
|
+
summary: "Browse or search the self-hosted font catalog",
|
|
143
|
+
usage: "frontpage fonts [list|search] [--slot sans|serif|mono|display] [--query …] [--variable-only] [--limit N] [--offset N] [--json]",
|
|
144
|
+
topics: ["site-building", "content"],
|
|
145
|
+
examples: [
|
|
146
|
+
"frontpage fonts --slot serif",
|
|
147
|
+
'frontpage fonts search "elegant script"',
|
|
148
|
+
"frontpage fonts --query Cinzel --json",
|
|
149
|
+
],
|
|
150
|
+
flags: [
|
|
151
|
+
"Use the exact `value` string in tokens.fonts.* (via frontpage tokens set or push)",
|
|
152
|
+
"No --site required — catalog is account/platform scoped",
|
|
153
|
+
],
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: "tokens",
|
|
157
|
+
summary: "Set a single design token surgically (CAS + active-run)",
|
|
158
|
+
usage: "frontpage tokens set --group <colors|fonts|spacing|radii|article> --key <name> --value <…> [--site <slug>] [--json]",
|
|
159
|
+
topics: ["site-building", "content"],
|
|
160
|
+
examples: [
|
|
161
|
+
'frontpage tokens set --group fonts --key sans --value "\\"Inter Variable\\", system-ui, sans-serif"',
|
|
162
|
+
],
|
|
163
|
+
dangers: [
|
|
164
|
+
"Requires prior pull (baseCommitSha)",
|
|
165
|
+
"Refused while an agent run is active (exit 3)",
|
|
166
|
+
"CAS fail if remote tip moved (exit 3) — pull and retry",
|
|
167
|
+
"Off-catalog font values warn but do not block",
|
|
168
|
+
],
|
|
169
|
+
seeAlso: ["fonts", "pull", "push"],
|
|
131
170
|
},
|
|
132
171
|
{
|
|
133
172
|
name: "status",
|
|
@@ -219,16 +258,18 @@ export const COMMANDS = [
|
|
|
219
258
|
},
|
|
220
259
|
{
|
|
221
260
|
name: "modules",
|
|
222
|
-
summary: "List or mutate modules (secret masks only)",
|
|
223
|
-
usage: "frontpage modules [list|enable|disable|archive|config] <key> [--instance <id>] [--config '{…}'] [--site <slug>]",
|
|
261
|
+
summary: "List, read docs, or mutate modules (secret masks only)",
|
|
262
|
+
usage: "frontpage modules [list|docs|enable|disable|archive|config] <key> [--instance <id>] [--config '{…}'] [--site <slug>]",
|
|
224
263
|
topics: ["agent", "content"],
|
|
264
|
+
examples: ["frontpage modules docs forms", "frontpage modules list"],
|
|
225
265
|
dangers: ["Secret values are never returned — masks only"],
|
|
226
266
|
},
|
|
227
267
|
{
|
|
228
268
|
name: "extensions",
|
|
229
|
-
summary: "List or mutate extensions (no secret values)",
|
|
230
|
-
usage: "frontpage extensions [list|enable|disable|config] <key> [--config '{…}'] [--site <slug>]",
|
|
269
|
+
summary: "List, read docs, or mutate extensions (no secret values)",
|
|
270
|
+
usage: "frontpage extensions [list|docs|enable|disable|config] <key> [--config '{…}'] [--site <slug>]",
|
|
231
271
|
topics: ["agent", "content"],
|
|
272
|
+
examples: ["frontpage extensions docs charts"],
|
|
232
273
|
},
|
|
233
274
|
{
|
|
234
275
|
name: "media",
|
|
@@ -352,7 +393,7 @@ export const TOPICS = {
|
|
|
352
393
|
frontpage push [--message …] # uploads allowlisted files; CAS + active-run guard
|
|
353
394
|
frontpage ls [prefix]
|
|
354
395
|
frontpage cat <path>
|
|
355
|
-
frontpage search <pattern>
|
|
396
|
+
frontpage search <pattern> [path] [--regex] [--case-sensitive] [--whole-word] [--files-only]
|
|
356
397
|
frontpage open # opens https://<slug>.frontpage.host/ (--prod is a no-op stub)
|
|
357
398
|
|
|
358
399
|
Local state: .frontpage/state.json { slug, baseCommitSha }
|
|
@@ -389,7 +430,8 @@ export const TOPICS = {
|
|
|
389
430
|
Tokens & fonts:
|
|
390
431
|
- Keep required colors/fonts/spacing/radii keys; style via CSS variables / token Tailwind.
|
|
391
432
|
- Setting fonts.sans is not enough — apply font-sans / font-serif / font-display on elements.
|
|
392
|
-
-
|
|
433
|
+
- Browse fonts: frontpage fonts [--slot serif] [--query elegant] — use the exact value string.
|
|
434
|
+
- Surgical token edit: frontpage tokens set --group fonts --key sans --value "…" (CAS like push).
|
|
393
435
|
|
|
394
436
|
Chrome / SEO / 404:
|
|
395
437
|
- Prefer src/components/Header.astro + Footer.astro (or chrome: { managed: true } in site.ts).
|
|
@@ -426,8 +468,10 @@ export const TOPICS = {
|
|
|
426
468
|
frontpage inbox [leads|subscribers|orders|…] [--mark-read] [--csv]
|
|
427
469
|
frontpage seo get|set --path /
|
|
428
470
|
frontpage articles list|content|create-section|create-article|set-draft|…
|
|
429
|
-
frontpage
|
|
430
|
-
frontpage
|
|
471
|
+
frontpage fonts [list|search] [--slot …] [--query …]
|
|
472
|
+
frontpage tokens set --group … --key … --value …
|
|
473
|
+
frontpage modules list|docs|enable|disable|archive|config <key>
|
|
474
|
+
frontpage extensions list|docs|enable|disable|config <key>
|
|
431
475
|
frontpage settings get|set
|
|
432
476
|
frontpage edit --path / --old "…" --new "…"
|
|
433
477
|
|
package/llms.txt
CHANGED
|
@@ -5,6 +5,9 @@
|
|
|
5
5
|
- Introspect: frontpage help | frontpage help --json | frontpage help <topic|command>
|
|
6
6
|
- Topics: quickstart, auth, sync, site-building, agent, content, history, isolation, exit-codes
|
|
7
7
|
- Site building: frontpage help site-building — Astro pages map, BaseLayout, tokens, no backends/fake forms
|
|
8
|
+
- Fonts: frontpage fonts [--slot] [--query] — use exact value; tokens: frontpage tokens set --group --key --value (CAS)
|
|
9
|
+
- Module/extension docs: frontpage modules docs <key> | frontpage extensions docs <key>
|
|
10
|
+
- Search flags: --regex --case-sensitive --whole-word --files-only --context-lines --max-results
|
|
8
11
|
- Auth: mint fp_live_ key in Frontpage UI (Developers); frontpage login KEY or FRONTPAGE_API_KEY
|
|
9
12
|
- Site id: subdomain only (frontpage use <subdomain>). Not custom domains.
|
|
10
13
|
- Staging: https://<subdomain>.frontpage.host — push/prompt/edit update staging; no separate staging deploy step for agents
|