n-seo 0.3.1 → 0.3.3
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/ingest/__pycache__/analyze_metadata.cpython-312.pyc +0 -0
- package/ingest/__pycache__/google_auth.cpython-312.pyc +0 -0
- package/ingest/__pycache__/http_util.cpython-312.pyc +0 -0
- package/ingest/__pycache__/seo_config.cpython-312.pyc +0 -0
- package/ops/__pycache__/daily.cpython-312.pyc +0 -0
- package/ops/__pycache__/daily_diff.cpython-312.pyc +0 -0
- package/ops/__pycache__/demo_data.cpython-312.pyc +0 -0
- package/ops/__pycache__/export_static.cpython-312.pyc +0 -0
- package/ops/__pycache__/llm.cpython-312.pyc +0 -0
- package/ops/__pycache__/publish.cpython-312.pyc +0 -0
- package/ops/daily.py +16 -8
- package/package.json +1 -1
- package/probes/__pycache__/site_probe.cpython-312.pyc +0 -0
- package/public/styles.css +4 -2
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/ops/daily.py
CHANGED
|
@@ -202,6 +202,15 @@ def main():
|
|
|
202
202
|
wait_for_network()
|
|
203
203
|
|
|
204
204
|
results, failures = [], []
|
|
205
|
+
|
|
206
|
+
def write_last_run():
|
|
207
|
+
seo_config.DATA.mkdir(parents=True, exist_ok=True)
|
|
208
|
+
(seo_config.DATA / "last-run.json").write_text(json.dumps({
|
|
209
|
+
"ts": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%MZ"),
|
|
210
|
+
"failures": "; ".join(failures),
|
|
211
|
+
"steps": results,
|
|
212
|
+
}, indent=1), encoding="utf-8")
|
|
213
|
+
|
|
205
214
|
if run_hooks_flag:
|
|
206
215
|
run_hooks("before", hooks["beforeRun"], results, failures)
|
|
207
216
|
for name, script in todo:
|
|
@@ -221,17 +230,16 @@ def main():
|
|
|
221
230
|
failures.append(name)
|
|
222
231
|
log(f"{name} FAILED")
|
|
223
232
|
results.append({"name": name, "ok": ok, "seconds": round(time.time() - t0, 1)})
|
|
233
|
+
# After every step, not just at the end. static-export is itself a
|
|
234
|
+
# step, so a record written after the loop is not yet on disk when the
|
|
235
|
+
# export reads it — every published page carried the *previous* run's
|
|
236
|
+
# timestamp and said the daily run had not happened today. It also
|
|
237
|
+
# means the dashboard's status reflects a long run while it is still
|
|
238
|
+
# going, rather than staying stale for its full duration.
|
|
239
|
+
write_last_run()
|
|
224
240
|
if run_hooks_flag:
|
|
225
241
|
run_hooks(name, hooks["afterStep"].get(name, []), results, failures, step=name)
|
|
226
242
|
|
|
227
|
-
def write_last_run():
|
|
228
|
-
seo_config.DATA.mkdir(parents=True, exist_ok=True)
|
|
229
|
-
(seo_config.DATA / "last-run.json").write_text(json.dumps({
|
|
230
|
-
"ts": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%MZ"),
|
|
231
|
-
"failures": "; ".join(failures),
|
|
232
|
-
"steps": results,
|
|
233
|
-
}, indent=1), encoding="utf-8")
|
|
234
|
-
|
|
235
243
|
write_last_run()
|
|
236
244
|
if run_hooks_flag and hooks["afterRun"]:
|
|
237
245
|
# afterRun sees a complete last-run.json (a mirror sync wants it), and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "n-seo",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"description": "Agentic, local-first SEO / AEO / GEO control plane: pulls Search Console + GA4, probes your sites, and ranks the next moves. Your LLM writes the proposals; your coding agent works the queue over MCP.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "En Dash Consulting (https://endash.us)",
|
|
Binary file
|
package/public/styles.css
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
--topbar-ink: rgba(255, 255, 255, 0.78);
|
|
22
22
|
--heat: 55, 87, 214;
|
|
23
23
|
--mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
24
|
+
--display: "Montserrat", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
24
25
|
|
|
25
26
|
/* Traffic-source groups. Okabe-Ito derived: vermillion / indigo / green /
|
|
26
27
|
pink stay separable under deuteranopia and protanopia, and no pair of
|
|
@@ -85,7 +86,7 @@ body {
|
|
|
85
86
|
line-height: 1.55;
|
|
86
87
|
}
|
|
87
88
|
main { max-width: 1480px; margin: 0 auto; padding: 28px 24px 80px; }
|
|
88
|
-
h1, h2, h3 { font-family:
|
|
89
|
+
h1, h2, h3 { font-family: var(--display); line-height: 1.2; letter-spacing: -0.01em; }
|
|
89
90
|
h1 { font-size: 1.8rem; font-weight: 800; margin: 0.5em 0; }
|
|
90
91
|
h2 { font-size: 1.05rem; font-weight: 700; margin: 2em 0 0.6em; text-transform: uppercase; letter-spacing: 0.06em; }
|
|
91
92
|
h2 small { font-weight: 500; color: var(--muted); font-size: 0.75rem; text-transform: none; letter-spacing: 0; }
|
|
@@ -100,12 +101,13 @@ a { color: var(--accent); }
|
|
|
100
101
|
padding: 11px 24px; background: var(--topbar);
|
|
101
102
|
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
102
103
|
}
|
|
103
|
-
.brand { display: flex; align-items: center; gap: 9px; font-weight: 800; color: #fff; text-decoration: none; letter-spacing: -0.01em; }
|
|
104
|
+
.brand { display: flex; align-items: center; gap: 9px; font-family: var(--display); font-weight: 800; color: #fff; text-decoration: none; letter-spacing: -0.01em; }
|
|
104
105
|
.brand-mark { flex-shrink: 0; display: block; } /* the mark carries its own brand colors */
|
|
105
106
|
.brand-name { max-width: 24ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
106
107
|
.brand-sub { color: var(--topbar-ink); font-weight: 500; font-size: 0.8rem; }
|
|
107
108
|
.topbar nav { display: flex; gap: 4px; flex-wrap: wrap; }
|
|
108
109
|
.topbar nav a, .nav-menu summary {
|
|
110
|
+
font-family: var(--display);
|
|
109
111
|
color: var(--topbar-ink); text-decoration: none; font-size: 0.82rem; font-weight: 600;
|
|
110
112
|
padding: 4px 10px; border-radius: 99px;
|
|
111
113
|
}
|