Remove the MSS 2026 news page, homepage promo banner, and listing entries,
then rebuild listings/sitemap/llms.txt/search-index so no MSS references
remain. Keeps shared event CSS/JS intact for other events. MSS 2026 stays
on feat/no-code-cms for a later, separate publish.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bring CMS/event branch up to date with develop. Net incoming change is the
CI deploy runner config (install rsync/openssh); all other develop history
was already present via shared kristijan-dev lineage.
Meet Student Slovenia 2026 remains on this branch only (unpublished).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Regenerate assistant/index-{en,mk,si}.json to reflect real event photos
and Latinized titles.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace event-placeholder.svg with real .webp photos across all 2025-2026
event/project pages (EN/MK/SI), updating OG/Twitter/JSON-LD image refs,
inline article images, and content/events/*.md. Also Latinize EN/SI titles
(e.g. "Kafanska večer") and drop empty "In numbers" TOC sections.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add trilingual (EN/MK/SI) event pages for seven MSOS activities:
- Joint Walk "Path Around the Wire" (May 2025)
- Kafanska vecher (May 2025)
- Watching the Macedonia-Wales match (Nov 2025)
- Team-building and MSOS Hub opening (Feb 2026)
- SEPA webinar with the National Bank of RNM (May 2026)
- President Siljanovska-Davkova lecture at UL (May 2026)
- Morning Coffee in front of CTK, 4th edition (Jun 2026)
Each page uses a neutral placeholder image (images/event-placeholder.svg)
in every hero/inline/gallery slot, with captions describing the intended
photo so real images can be dropped in later. Pages follow the existing
event template (narrative sections + scrollspy + photo gallery); no
"At a glance" classification box.
Wires the events into the Projects hub (filter cards), News hub, sitemap,
bot-discovery files and the offline search index. Unrelated pages were
kept out of this commit to avoid build-tool encoding churn.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Update the Student Welcome Guide residence pages (EN/MK/SI):
- visa-and-residence-explained: clarify that visa D mainly applies to
study exchanges (e.g. Erasmus, up to one year) and is handled only by
the embassy, while degree students use the temporary residence permit
decided by the administrative unit (a permit, not a "visa").
- where-to-apply-for-residence: explain that the embassy only forwards
the application to the administrative unit (slower, costlier); present
applying directly at the administrative unit as usually faster and
cheaper with the same documents; replace vague checklist prompts with
concrete facts (appointment contact, standard document list, official
Slovenian translation, certification, criminal-record recency, fees);
keep the cautious lawful-stay wording and add a warning about leaving
Slovenia while the application is pending.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
These auto-generated Python caches were committed before .gitignore
listed __pycache__/ and *.pyc, so Git kept tracking them and they showed
up as spurious changes on every build. Untrack them (files stay on disk)
so .gitignore takes effect and they no longer appear in diffs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add a @media print block so event pages export cleanly to PDF/print:
keep faithful colours (print-color-adjust: exact), unstick the header,
hide screen-only chrome (chat bubble, cookie consent, sticky CTA, back
link, newsletter box, mobile nav), and reset the hero image to full
width. No effect on the on-screen layout.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Sources sections on the Welcome Days, accommodation-search and
Ad futura scholarship articles used bare <ul>/<ol> lists, which rendered
as default bullets/numbers with plain blue links instead of the site's
standard source-list style (chain icon, teal links, row dividers).
Add class="guide-linklist" to the Sources lists (converting Ad futura's
<ol> to <ul>) in the content/ source markdown and the generated en/mk/si
pages, matching the Student Welcome Guide. Edits scoped to the affected
articles to avoid unrelated build-tool reformatting churn.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The .event-banner rules were dropped during an _event.css rewrite, so the
homepage promo banner rendered unstyled (full-width dark text, no gradient).
Restored the banner styles and removed the em-dash from the banner copy.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Event page (Meet Student Slovenia 2026):
- Guide-style centred header with wide banner hero and caption
- Key facts on a plain background: When/Where side by side, subtle
live-stream line, centred Register CTA, full-width note
- Partner logos (NLB patron, Embassy support) + sponsor
Kapital Aset Menadžment DOOEL / Капитал асет менаџмент ДООЕЛ
- Inline photos between sections; em-dash removed from the subtitle
- "Support MSOS" call-out linking to the support page
Support page:
- Added the become-a-member supporter flow (supporter path only) via a
new data-only-flow="supporter" mode in member-form.js; submits to the
same combined Google Form tagged type=supporter
- Hero "Become a partner" button now scrolls to the form
- .ms-section carries its own brand vars so the form renders off the
member page
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Trilingual (EN/MK/SI) promo page for the upcoming "Meet Student Slovenia
2026" event, built through the content CMS (content/news/...) plus custom
sections styled to match the site.
- Guide-style centred header with a wide banner hero and caption
- Plain-background key facts (When/Where), subtle live-stream line,
centred Register CTA, and partner/patron/sponsor logos
(NLB Banka, Embassy of Slovenia; Capital Financial Center as text)
- Auto-scrolling "Moments from previous years" carousel + inline photos
- Embedded registration form (dropdowns, required study-plan fields,
multi-field study preferences) wired to a Google Form; left-hand
floating Register button
- Homepage promo banner (EN/MK/SI) + auto-listed in News hub, homepage
latest, sitemap, llms.txt and the offline search index
- New assets: css/pages/_event.css, event-register.js
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add tools/build_site.py: runs the full pipeline in dependency order
(build_content -> build_listings -> seo_inject --all --sitemap ->
build_botlinks -> build_search_index), each as a subprocess so a failing
step aborts the build before anything downstream runs (no partial
deploy). --check verifies non-destructively; --images also runs
optimize_images. This is what CI will run in U5.
Fix a build_content idempotence bug found via U4: the hero and
article-header regions were emitted with leading indentation while the
regex left the template's pre-tag whitespace in place, so indentation
compounded (+16 spaces) on every rebuild. First line is now unindented;
the full build is verified idempotent (identical git tree across two
runs). Added a fixpoint test (re-rendering a page's own output is
byte-identical) so this can't regress.
docs/local-preview.md: build + serve on :8000 in all three languages.
tools/README.md: document build_site + build_content.
26 tests pass.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the hand-maintained ARTICLE_DATES registry as the source of
truth with dates read from content/ front-matter, so publishing a post
via the CMS needs no manual registry edit (plan R4).
- tools/content_index.py: load_dates() reads content/ front-matter into
{source_folder/slug: {published|modified: iso}}. Standalone (os+yaml),
no import cycle with seo_inject.
- tools/seo_inject.py: ARTICLE_DATES is now {**static_fallback,
**content_dates}; content wins. The static table is kept only as a
fallback for entries not present in content/.
- migration now preserves the published-vs-modified distinction
(date_type), so the switch is byte-identical: content-derived dates
equal the old static table exactly (17/17, incl. the one 'modified').
Verified: full `seo_inject --all --sitemap` + build_listings +
build_botlinks run produces ZERO changes to any site page. build_content
--check still reproduces all 51 pages.
build_botlinks.py needs no change (it scrapes built pages, which are a
pure function of content/). Listings get content-driven dates for free
via seo_inject.ARTICLE_DATES.
tools/tests/test_content_index.py: 5 tests (dates == legacy registry,
merged registry unchanged, published/modified distinction, events key on
projects/<slug>, one ISO date per entry).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add tools/build_content.py: renders every content/ entry into its blog /
news / event detail page by self-templating the page's own chrome and
replacing only content-derived regions (title, article header, hero,
body, and — for new pages only — the scrollspy).
Faithful reproduction, proven against the live site:
- body_format: html fragments injected verbatim, so guide-boxes, inline
figures and event galleries render unchanged.
- scrollspy sidebars are preserved (labels are hand-curated, shorter than
the H2s); only generated when a page has none.
- <title> suffix derived per page, so EN/SI " - MSOS", MK " - МСОС", and
suffix-less event titles all reproduce exactly.
- hero /images/… rewritten to the page's ../../../ depth.
- ASCII-only console output (no cp1252 crash on Windows/CI).
tools/tests/test_build_content.py: 8 characterization tests; the core one
renders all 51 pages and asserts each is semantically equivalent
(whitespace/attr-order-insensitive) to the current page — the R5
no-regression guarantee.
Does NOT overwrite the committed pages; whether generated pages are
committed vs built fresh in CI is decided in U4/U5. Run:
python tools/build_content.py --check # verify equivalence
python tools/build_content.py --write # emit pages (for U4)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Establish content/ as the source of truth for editable content and
back-fill it from the existing detail pages, per U1 of the no-code CMS
plan.
- docs/content-model.md: front-matter schema (EN/MK/SI), body_format
html-vs-markdown, content/events -> projects/ output mapping.
- tools/migrate_pages_to_content.py: bs4/yaml extractor; pulls title,
subtitle, category, ISO date (from ARTICLE_DATES), hero image+caption;
preserves the article body PLUS trailing sibling sections (event
galleries) verbatim as body_format: html. Reports unparseable pages
instead of emitting half-formed files.
- content/**: 51 files (17 entries x EN/MK/SI), 0 skips.
- tools/tests/test_migrate_roundtrip.py: 12 characterization tests
(structured fields, news-has-no-subtitle, event gallery/lightbox
preserved, Cyrillic UTF-8 round-trip, every page parses).
- .gitignore: ignore __pycache__/ and *.pyc.
U1 is unblocked and standalone. U2 (render content -> pages) is next;
U5/U6 remain blocked on Open Question Q1 (Gitea<->GitHub topology).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>