feat: offline in-browser "Ask MSOS" assistant (no API, zero cost)

A privacy-friendly help widget that answers visitor questions from the
site's own content and links to the full page — runs 100% in the browser,
no API, no server, no per-token cost.

- tools/build_search_index.py: parses every EN/MK/SI page into ~720
  heading-level chunks per language -> assistant/index-<lang>.json
  (lazy-loaded only when the chat is opened; gzips to ~80 KB).
- assistant.js: dependency-free BM25 search + multilingual stopword
  filtering + a curated short-answer layer for common questions, plus an
  accessible chat widget (role=dialog, keyboard, aria). CSP-safe (self only).
- assistant.css: scoped .msa-* styles in the site's teal palette;
  responsive (full-screen panel on mobile).
- Injected on 208 pages (blog WIP excluded; picks it up when that lands).

Verified in a headless browser across EN/MK/SI: curated answers, search
fallback with correct ranking (rare terms win), correct deep links,
Cyrillic + Slovene diacritics, and zero console errors. Curated MK/SI
answers are machine-drafted — proofread before launch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
popovskikandClaude Opus 4.8 committed 2026-08-04 01:29:22 +02:00
1 parent cca6fd18aa
commit f7f297bd65
214 files changed
+876

No files matched your search

@@ -378,5 +378,7 @@
<!-- END_FOOTER -->
<script src="../../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>
@@ -320,5 +320,7 @@
<!-- END_FOOTER -->
<script src="../../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>
@@ -331,5 +331,7 @@
<!-- END_FOOTER -->
<script src="../../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>
+2
View File
@@ -427,5 +427,7 @@
<!-- Povezava do glavne JS datoteke -->
<script src="../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>
@@ -363,5 +363,7 @@
<!-- END_FOOTER -->
<script src="../../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>
@@ -404,5 +404,7 @@
<!-- END_FOOTER -->
<script src="../../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>
@@ -383,5 +383,7 @@
<!-- END_FOOTER -->
<script src="../../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>
@@ -349,5 +349,7 @@
<!-- END_FOOTER -->
<script src="../../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>
@@ -360,5 +360,7 @@
<!-- END_FOOTER -->
<script src="../../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>
@@ -346,5 +346,7 @@
<!-- END_FOOTER -->
<script src="../../../main.js"></script>
<link rel="stylesheet" href="/assistant.css">
<script src="/assistant.js" defer></script>
</body>
</html>