n-seo 0.4.0 → 0.4.1

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/CHANGELOG.md CHANGED
@@ -8,6 +8,19 @@ uses [Semantic Versioning](https://semver.org/).
8
8
 
9
9
  Nothing yet.
10
10
 
11
+ ## [0.4.1] - 2026-09-13
12
+
13
+ ### Added
14
+ - **Every page says which engine built it.** The footer now carries
15
+ `n-seo <version>`, and when a newer one is published it carries the upgrade
16
+ command and a link to the release notes beside it. This matters most on a
17
+ published mirror: `/settings` is deliberately not exported, because it shows
18
+ local paths and the service-account email, so before this a mirror named no
19
+ version anywhere. The notice is baked in at export time from the file the
20
+ daily run writes — polling the registry from the browser would put every
21
+ viewer of a shared mirror onto npmjs.com on every page view, to learn
22
+ something that changes once a day.
23
+
11
24
  ## [0.4.0] - 2026-09-12
12
25
 
13
26
  Upgrading used to be something you found out about by accident. This release
@@ -388,7 +401,8 @@ First public release.
388
401
  `n-seo upgrade` gate — without changing the reported test counts, and an
389
402
  in-place install ran those assertions against the owner's live data.
390
403
 
391
- [Unreleased]: https://github.com/en-dash-consulting/n-seo/compare/v0.4.0...HEAD
404
+ [Unreleased]: https://github.com/en-dash-consulting/n-seo/compare/v0.4.1...HEAD
405
+ [0.4.1]: https://github.com/en-dash-consulting/n-seo/compare/v0.4.0...v0.4.1
392
406
  [0.4.0]: https://github.com/en-dash-consulting/n-seo/compare/v0.3.3...v0.4.0
393
407
  [0.3.3]: https://github.com/en-dash-consulting/n-seo/compare/v0.3.2...v0.3.3
394
408
  [0.3.2]: https://github.com/en-dash-consulting/n-seo/compare/v0.3.1...v0.3.2
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "n-seo",
3
- "version": "0.4.0",
3
+ "version": "0.4.1",
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)",
package/public/styles.css CHANGED
@@ -191,6 +191,10 @@ td.trunc { max-width: 380px; overflow: hidden; text-overflow: ellipsis; white-sp
191
191
  .flash { background: var(--good-soft); color: var(--good); font-weight: 600; font-size: 0.85rem; padding: 8px 14px; border-radius: 8px; }
192
192
 
193
193
  footer { max-width: 1480px; margin: 0 auto; padding: 16px 24px 40px; color: var(--muted); font-size: 0.75rem; border-top: 1px solid var(--line); }
194
+ footer .foot-ver { font-weight: 600; color: var(--ink); }
195
+ footer .foot-upd { background: var(--warn-soft); color: var(--warn); border-radius: 5px; padding: 1px 7px; font-weight: 600; }
196
+ footer .foot-upd code { background: rgba(0,0,0,0.06); color: inherit; }
197
+ footer .foot-upd a { color: inherit; text-decoration: underline; }
194
198
 
195
199
  /* ---- buttons + inline forms ---- */
196
200
  .btn {
package/src/views.tsx CHANGED
@@ -1,6 +1,6 @@
1
1
  /** Server-rendered views (hono/jsx). */
2
2
  import type { FC, PropsWithChildren } from "hono/jsx";
3
- import { SITES, config, loadConfig, USING_EXAMPLE_CONFIG, type SiteCfg } from "./config.js";
3
+ import { SITES, ENGINE_VERSION, config, loadConfig, USING_EXAMPLE_CONFIG, type SiteCfg } from "./config.js";
4
4
  import * as data from "./data.js";
5
5
  import { actionsFor, allActions, type Action } from "./actions.js";
6
6
  import { insights as loadInsights } from "./insights.js";
@@ -35,6 +35,7 @@ export const Layout: FC<PropsWithChildren<{ title: string; active: string }>> =
35
35
  loadConfig(); // refresh USING_EXAMPLE_CONFIG
36
36
  const cfg = config();
37
37
  const sites = cfg.sites;
38
+ const upd = data.updateCheck();
38
39
  return (
39
40
  <html lang="en">
40
41
  <head>
@@ -87,7 +88,26 @@ export const Layout: FC<PropsWithChildren<{ title: string; active: string }>> =
87
88
  )}
88
89
  <main>{children}</main>
89
90
  <footer>
90
- Local controller · refreshed by <code>ops/daily.py</code> · queue in <code>config/backlog.json</code> · nothing here posts or publishes for you
91
+ {/* Which engine produced this page. On the static mirror that is
92
+ the only place it appears — /settings is not exported, because
93
+ it shows local paths and the service-account email — so without
94
+ this a published mirror named no version at all.
95
+
96
+ The update notice is baked in at export time from the file the
97
+ daily run writes. Polling the registry from the browser instead
98
+ would put every viewer of a shared mirror onto npmjs.com on
99
+ every page view, to learn something that changes once a day. */}
100
+ <span class="foot-ver">n-seo {ENGINE_VERSION}</span>
101
+ {upd?.newer && (
102
+ <>
103
+ {" "}
104
+ <span class="foot-upd">
105
+ {upd.latest} available — upgrade with <code>n-seo upgrade</code>
106
+ {upd.notes && <> · <a href={upd.notes} target="_blank" rel="noopener noreferrer">what changed</a></>}
107
+ </span>
108
+ </>
109
+ )}
110
+ {" · "}refreshed by <code>ops/daily.py</code> · queue in <code>config/backlog.json</code> · nothing here posts or publishes for you
91
111
  </footer>
92
112
  <script dangerouslySetInnerHTML={{ __html: `document.addEventListener('click',function(e){var d=e.target.closest('dialog');if(d&&e.target===d)d.close();});` }} />
93
113
  </body>