Skip to content

Serve the relaunched site - #124

Merged
openipc-ai merged 5 commits into
masterfrom
feat/ia-cutover
Aug 28, 2026
Merged

Serve the relaunched site#124
openipc-ai merged 5 commits into
masterfrom
feat/ia-cutover

Conversation

@openipc-ai

Copy link
Copy Markdown
Collaborator

Last of five. Stacked on #123#122#121#120. This is the one that
changes what a visitor sees.

Root becomes pages#home, the navigation becomes
Get Started | Hardware | Low Latency | Ecosystem▾ | For Business | Community▾,
and the single copyright line becomes a four-column footer.

Redirects, not deletions

The pre-relaunch URLs are in search results, forum posts and the wiki, and none
of that is ours to edit. 301 where the destination is settled, so what's indexed
transfers rather than competes. 302 for /about alone — it's meant to become
a page of its own, and a 301 is cached by browsers indefinitely, so it would
outlive the decision.

There's a test per redirect, plus one that every target resolves — a redirect
to a path that has itself gone still answers 301 and lands the visitor on the
homepage.

Two routes that answered 500

Building the new menu meant checking every URL it would link. Two had never
worked:

  • /tools/bandwidth-calculatorpages#bandwidth_calculator. No action, no
    template. Every request raised AbstractController::ActionNotFound — a 500 in
    production.
  • /tools/timelaps-interval-calculatorpages#timelaps_interval_calculator,
    which likewise doesn't exist. The template is there but named with hyphens, so
    nothing could render it, and it has no translations either.

Both routes are removed, so an inbound link reaches the homepage rather than an
error page. Neither is linked from the new navigation. The unfinished timelapse
template is left in the tree
— finishing it is a decision for whoever started
it, not something to settle with a routing change.

A third bug, found by testing the upload API

Cameras POST to /snapshots; the gallery moved to /open-wall and the API did
not move at all, so there's a test that nothing shadows it. It failed:
Snapshot read credentials.mac.blacklisted directly, so without
config/master.key — which a fresh checkout and the test environment have —
every upload raised NoMethodError
rather than simply having nothing to
blacklist. Production has the key, so it never showed there; it made the API
impossible to exercise anywhere else. It digs now.

Tidying

Replaced pages, their translations and their nav entries are deleted:
i18n-tasks unused goes 102 → 72, below where it started rather than up.
pages/_legacy.scss loses two of three rules with the pages they styled.

Two white stripes showed up where one dark band met the next — the CTA band and
the footer both carried a top margin on top of their own padding. Both dropped.

Verification

check result
bin/rails test 289 runs, 1276 assertions, 0 failures
i18n-tasks missing none, across en/ru/zh
i18n-tasks unused 102 → 72
rubocop 734 / 114 files vs 742 / 111 on master
rendered in a browser all 7 pages + hardware browser, in all 3 languages

That last row earned its place: it's how the footer stylesheet turned out never
to have been imported — the suite was green while the footer rendered on white.

Still open for you

🤖 Generated with Claude Code

https://claude.ai/code/session_015hvzXBErEjEGMyRme2K3hi

openipc-ai and others added 4 commits August 25, 2026 15:02
The site's CSS was one 200-line file appended to Bootstrap, and the order it
was written in hid a bug. Our theme values landed *after* the Bootstrap import,
where Bootstrap's own !default declarations had already won, so $primary stayed
at Bootstrap's #0d6efd while :root separately declared --bs-blue: #4c60d8. The
page carried two blues: buttons and links in one, headings and the navbar in the
other. Nobody had written the wrong colour anywhere -- the file just could not
express the intent in that order.

So the entry point is now only an ordering statement: fonts, Bootstrap's
functions, our variables, Bootstrap, then our own partials. --bs-primary and
--bs-btn-bg both compile to #4c60d8 now. $blue is set alongside $primary because
--bs-blue is what the pre-relaunch rules colour headings with, and leaving it at
the default would have reproduced the same split from the other side.

The partials that arrive here are the ones that style pages which exist today.
Components and page styles belonging to the new pages come with those pages,
rather than sitting in the tree as dead CSS in the meantime. pages/_legacy.scss
holds the rules that belong to the pre-relaunch pages, kept verbatim and kept
together so the cutover can delete a file instead of picking rules apart. One of
them is the CSS that hides the Russian integrators from non-Russian visitors on
/introduction: the replacement is a Ruby helper, but until that page goes this
rule is the only thing enforcing it, and dropping it early would show that logo
wall to everyone.

The other legacy rule worth naming is the h2 title style. _base.scss gives
article headings the new treatment; the legacy selector is longer and therefore
wins, and it applies exactly to pages rendered inside the .container wrapper --
which is every page that is not full-bleed. The two rules split along the same
line the layout's fullwidth switch will.

FONTS. The stylesheet opened with three @import url() lines: two to
fonts.googleapis.com and one to cdn.jsdelivr.net. Every visitor announced
themselves to two third parties before the page could paint, and first paint sat
behind DNS lookups we do not control. This is the same argument that moved the
legacy logo off a maintainer's personal CDN in d60729a. IBM Plex and
bootstrap-icons are now served from public/fonts, subset to latin, latin-ext and
cyrillic; Chinese falls back to the system stack, because IBM Plex has no CJK
glyphs and the families that do are megabytes. The files are committed, since
public/ bypasses Sprockets and a generated file would have to exist before
assets:precompile in the image and before CI renders a page, for no benefit.
tools/copy-fonts.mjs regenerates them from the @fontsource packages and fails
loudly if a file the stylesheet asks for is missing.

JAVASCRIPT. One window.onload handler becomes modules under app/javascript/src.
That handler assigned window.onload rather than adding a listener, so any second
assignment would have silently replaced all of it, and it waited on every image
-- on the Open Wall, the whole gallery -- before anything became interactive.
It is DOMContentLoaded now.

The zoom initialiser called `new bootstrap.Modal(document.getElementById(...))`
unconditionally. Most pages have no zoomable image and so no #modalZoom, the
constructor threw on null, and because every initialiser shared the one handler,
the throw took external links, timestamps and confirmations down with it on
those pages. It returns early now.

@hotwired/turbo-rails and @hotwired/stimulus are removed: neither was ever
imported. The layout's data-turbo-track goes with them, having been inert. The
lockfile is regenerated with Yarn 4 -- it must never be rewritten by a v1 yarn,
which produces a format `yarn install --immutable` in the Dockerfile cannot read.

Bootstrap is imported per component rather than wholesale. 189.4 KB to 181.8 KB
unminified, which is a small win; the point is the import list, which now states
what the markup actually depends on. Audited against the views first: dropdown,
collapse, offcanvas, carousel and Modal are used, and nothing uses tooltip,
popover, tab, alert or scrollspy.

Verified: 231 runs, 873 assertions, 0 failures. Diffing the compiled selector
set against master's leaves exactly one difference -- label.required:after,
which is now spelled ::after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hvzXBErEjEGMyRme2K3hi
The <head> carried a title and nothing else. A link to openipc.org shared in
Telegram, in a forum post, or shown in a search result therefore appeared as a
bare URL with no summary and no image -- for a project whose reach is almost
entirely word of mouth between people posting links to each other.

Added: a description, an OG/Twitter card set, a canonical, and a theme colour.
Three of those have a detail worth keeping:

The canonical carries the path and not the query string. ?locale=ru is a
rendering of the same page rather than a different one, and pointing all three
translations at one canonical is what stops them competing with each other for
the same content.

og:image is absolute, because crawlers do not resolve a relative one, and it
lives in public/ rather than the asset pipeline. OG images are fetched once and
cached by URL by every consumer that has ever seen the link, so a fingerprint in
the name would invalidate those caches for no gain.

The two font faces every page renders body text in are preloaded. crossorigin is
required even though they are same-origin -- fonts are fetched in CORS mode, and
a preload without it is simply fetched a second time.

The navbar and footer move into layouts/ partials. Nothing about them changes:
same links, same order, same locale switcher, and the footer's icons still
resolve through asset_path, which is not cosmetic -- production runs with
config.assets.compile = false, so a literal /assets/... path is a 404, and
2ec9baa fixed exactly these lines. Extracting them now means the relaunch can
rewrite the navigation in one file a reviewer can read, instead of inside a diff
that also touches <head>.

<main> gains a content_for(:fullwidth) switch for pages that lay out their own
full-bleed sections. Flash messages keep the container in both branches, or they
would run edge to edge. Pages that set nothing keep the wrapper they have always
had, and a test holds that.

The tests are the ones that would have caught each way a <head> goes wrong: a
missing or duplicated description, a description that came back as "translation
missing", a canonical that kept the query string, a relative og:image, an
og-default.png that is not there, and a preload naming a font file the
stylesheet does not generate.

238 runs, 903 assertions, 0 failures. i18n-tasks reports no missing keys and
102 unused, unchanged -- the new key being used is what keeps that number flat.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hvzXBErEjEGMyRme2K3hi
Seven pages -- home, get-started, low-latency, ecosystem, business, community,
donate -- plus the shared partials they are built from. They answer on their own
URLs from this commit, but the root route and the navigation still serve the
pre-relaunch structure, so nothing a visitor sees changes. The cutover is a
separate change, and this one can go to dev.openipc.org and be looked at first.

The copy is written in all three locales the site now serves. English and
Russian are as drafted; the Chinese was written for this commit and has not been
read by a native speaker -- it should be, before it is linked to. i18n-tasks
reports 347 keys in each of the three files and no missing translations.

Not everything from the draft survived contact with the current tree, and the
rendering tests are what found each one.

/get-started hardcoded four WebUI screenshots by filename --
webui/preview.jpg and three others. The gallery was reshot at twice the
resolution in 0f42514 and every one of those files stopped existing; the page
raised on render. It now takes them from WebuiGallery, the same manifest
/web-interface reads and the same one tools/webui-gallery photographs from, so
the two cannot disagree about what exists. Tile and full-resolution copy are
passed as a pair, which is what data-zoom in src/zoom.js is for.

Every link in the new copy that pointed at wiki.openipc.org now points at
github.com/OpenIPC/wiki. That host is retired; 2842ffa and 73c0961 removed the
last references to it and this copy would have put four of them back.

The partner wall moves out of the markup into PagesHelper, transcribed from
/introduction as it stands today rather than from the June draft, which was ten
entries out of date. Entries that page has commented out are commented out here
too, with their URLs, so nothing appears or disappears silently when
/introduction goes.

  REVIEW POINT: the Russian integrator block is currently commented out on
  /introduction, so no visitor sees any of it. Rendering it for :ru brings it
  back. That is what the relaunch plan asks for and it is gated to :ru as the
  maintainers asked, but it is a content decision -- say so if it should stay
  hidden.

Worth knowing: the CSS that was supposed to enforce that gate,
`html:not([lang="ru"]) article.introduction .col.logo.ru`, has never matched
anything. No logo on that page carries the `ru` class it selects on. The gate
being in Ruby now is what makes it testable, and there is a test.

/open-wall is uncommented. It was commented out in ed0e025, a bulk tidy-up,
while five places that redirect to it were left in place -- twice in
snapshots_controller, once in admin/snapshots_controller, and the breadcrumb on
three views. All five fell through the catch-all and answered a 302 to the
homepage. This exposes nothing new: `resources :snapshots` has served the same
gallery at /snapshots throughout.

Snapshot.latest_per_camera lifts the correlated subquery out of
SnapshotsController#index, because the homepage mosaic wants the same list and
two copies of that query is one too many.

pages.donate belonged to the band rendered under every page. It is now the
/donate page's, and the band's two keys moved to pages.donate_band -- otherwise
lazy lookup in the partial and the new page's title would have fought over the
same key, and the band would have lost its please_support string.

272 runs, 1223 assertions, 0 failures. Each page is rendered in each of the
three locales and checked for "translation missing"; every internal link on
them is followed and required not to land on the catch-all; the homepage is
rendered against an empty database, which is what a fresh checkout has. rubocop
is unchanged at 53 offences across the files this touches, and the two new files
add none.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hvzXBErEjEGMyRme2K3hi
The root becomes pages#home, the navigation becomes Get Started | Hardware |
Low Latency | Ecosystem | For Business | Community, and the single copyright
line becomes a four-column footer. Everything that has been building up over the
last four changes is now what a visitor sees.

The pre-relaunch URLs redirect rather than disappear. They are in search
results, in forum posts and in the wiki, and none of that is ours to edit: 301
for the ones whose destination is settled, so what is indexed transfers instead
of competing, and 302 for /about alone, because it is meant to become a page of
its own and a 301 is cached by browsers indefinitely -- it would outlive the
decision. There is a test per redirect, and a test that every target resolves,
because a redirect to a path that has itself gone still answers 301 here and
lands the visitor on the homepage.

TWO ROUTES THAT ANSWERED 500. Building the new menu meant looking at every URL
it would link, and two of them had never worked:

  /tools/bandwidth-calculator routed to pages#bandwidth_calculator. There is no
  such action and no such template. Every request raised
  AbstractController::ActionNotFound, which in production is a 500.

  /tools/timelaps-interval-calculator routed to pages#timelaps_interval_
  calculator, which likewise does not exist -- the template is there but named
  with hyphens, so nothing could render it, and it has no translations either.

Both routes are removed, so an inbound link now reaches the homepage rather than
an error page. Neither page is linked from the new navigation, and the
unfinished timelapse template is left in the tree: finishing it is a decision
for whoever started it, not something to settle with a routing change.

The upload API keeps its own test. Cameras POST to /snapshots and the gallery
moved to /open-wall; the API did not move at all, and nothing in the relaunch
may shadow it.

That test found a third thing. Snapshot read
Rails.application.credentials.mac.blacklisted directly, so without
config/master.key -- which is what a fresh checkout and the test environment
have -- credentials.mac is nil and every upload raised NoMethodError rather than
simply having nothing to blacklist. Production has the key, so it never showed
there; it made the API impossible to exercise anywhere else. It digs now.

The pages that were replaced are deleted, along with their translations and the
navigation entries that pointed at them: i18n-tasks unused goes from 102 to 72,
below where it started, rather than up. pages/_legacy.scss loses two of its
three rules with the pages they styled -- including the CSS territory gate that
never matched anything.

Two white stripes showed up in the rendered page where one dark band met the
next: the CTA band and the footer both carried a top margin on top of their own
padding. Both dropped.

289 runs, 1276 assertions, 0 failures. i18n-tasks reports no missing
translations across en, ru and zh. rubocop is 734 offences over 114 files
against 742 over 111 on master. Every page was rendered in a browser in all
three languages before this was committed, which is how the footer stylesheet
turned out never to have been imported.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015hvzXBErEjEGMyRme2K3hi
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Cut over to the relaunched site with legacy redirects

✨ Enhancement 🐞 Bug fix 🧪 Tests 🕐 40+ Minutes

Grey Divider

AI Description

• Cuts over the root, navigation, and footer to the multilingual relaunched site.
• Preserves legacy traffic with tested redirects and removes routes that returned 500 errors.
• Keeps snapshot uploads functional without encrypted credentials and verifies API routing.
Diagram

graph TD
  U["Site visitor"] --> R["Rails routes"] --> P["Relaunch pages"] --> L["Site layout"] --> I["Locale strings"]
  R --> D["Legacy redirects"] --> P
  R --> S["Snapshot API"] --> M["Snapshot model"]
Loading
High-Level Assessment

The PR’s explicit Rails redirects, removal of obsolete page implementations, and integration coverage are the appropriate cutover strategy. Retaining duplicate legacy pages would prolong translation and maintenance drift, while custom redirect middleware would add unnecessary indirection over native route declarations.

Files changed (20) +363 / -533

Enhancement (6) +185 / -60
application.bootstrap.scssLoad the relaunched footer styles +1/-0

Load the relaunched footer styles

• Imports the new footer component into the compiled application stylesheet so the dark footer renders correctly in production.

app/assets/stylesheets/application.bootstrap.scss

_footer.scssStyle the new four-column footer +49/-0

Style the new four-column footer

• Adds dark-theme typography, links, lists, social icon treatment, and footer-bottom separation for the relaunched footer.

app/assets/stylesheets/components/_footer.scss

_footer.html.erbReplace the copyright strip with a site footer +64/-18

Replace the copyright strip with a site footer

• Introduces localized Platform, Ecosystem, Project, and Community columns plus social links, licensing copy, tagline, and disclaimer. Asset-pipeline paths remain in use for production-safe icons.

app/views/layouts/_footer.html.erb

_navbar.html.erbPublish the relaunched navigation hierarchy +38/-24

Publish the relaunched navigation hierarchy

• Replaces the legacy menus with Get Started, Hardware, Low Latency, Ecosystem, Business, and Community navigation. It also adds GitHub access, sticky positioning, and an extra-wide collapse breakpoint.

app/views/layouts/_navbar.html.erb

donate.html.erbUse donation-specific accounting copy +1/-1

Use donation-specific accounting copy

• Replaces a dependency on the retired support-page translation with copy owned by the current donation page.

app/views/pages/donate.html.erb

routes.rbCut over routes and preserve legacy traffic +32/-17

Cut over routes and preserve legacy traffic

• Makes pages#home the root, maps retired URLs to replacement pages with deliberate 301 or 302 statuses, and redirects sponsor traffic to Donate. Removes two broken calculator routes so they fall through safely while preserving the snapshot upload and Open Wall routes.

config/routes.rb

Bug fix (2) +8 / -3
snapshot.rbHandle absent upload credential lists +7/-2

Handle absent upload credential lists

• Reads MAC blacklist and IP whitelist values with nested credential lookup and empty-list fallbacks. Fresh checkouts and tests can now process uploads without a master key.

app/models/snapshot.rb

_cta_band.html.erbRemove the CTA band top gap +1/-1

Remove the CTA band top gap

• Drops the top margin from dark CTA sections to eliminate a white stripe between adjacent dark bands.

app/views/shared/_cta_band.html.erb

Refactor (3) +14 / -68
_legacy.scssRemove styles belonging to retired pages +14/-32

Remove styles belonging to retired pages

• Drops obsolete title and partner-wall rules while retaining the heading treatment still used by surviving legacy pages. Comments now document the reduced scope.

app/assets/stylesheets/pages/_legacy.scss

pages_controller.rbRemove retired page actions +0/-30

Remove retired page actions

• Deletes controller actions for About, Introduction, channels, projects, software, and support pages now replaced by relaunch destinations and redirects.

app/controllers/pages_controller.rb

application.html.erbRemove the site-wide legacy donation band +0/-6

Remove the site-wide legacy donation band

• Stops rendering the obsolete donation partial beneath every page, allowing page content to meet the new footer directly.

app/views/layouts/application.html.erb

Tests (3) +90 / -8
page_metadata_test.rbKeep wrapper coverage on a surviving page +5/-2

Keep wrapper coverage on a surviving page

• Moves the container-wrapper assertion from the retired Introduction page to Our Team and tightens the selector to distinguish the layout wrapper from full-width page containers.

test/controllers/page_metadata_test.rb

redirects_test.rbCover cutover redirects and protected routes +79/-0

Cover cutover redirects and protected routes

• Adds status and destination coverage for permanent and temporary redirects, then verifies every destination resolves. It also guards the removed calculator URL, snapshot upload API, and Open Wall gallery routing.

test/controllers/redirects_test.rb

relaunch_pages_test.rbExercise the relaunched homepage at root +6/-6

Exercise the relaunched homepage at root

• Updates homepage, empty-database, full-width layout, and locale-specific integrator tests to use the root URL. Wrapper coverage now uses the surviving Our Team page.

test/controllers/relaunch_pages_test.rb

Other (6) +66 / -394
en.ymlLocalize the English relaunch chrome +21/-34

Localize the English relaunch chrome

• Adds English navbar and footer labels, updates links to current community and donation pages, and removes translations only used by the retired Telegram page.

config/locales/en.yml

pages.en.ymlPrune retired English page translations +1/-96

Prune retired English page translations

• Moves transparent-accounting copy under the donation page and removes keys for deleted introduction, channels, projects, software, support, and donation-band views.

config/locales/pages.en.yml

pages.ru.ymlPrune retired Russian page translations +1/-96

Prune retired Russian page translations

• Adds donation-owned accounting copy and removes Russian translations for the retired pre-relaunch pages and global donation band.

config/locales/pages.ru.yml

pages.zh.ymlPrune retired Chinese page translations +1/-96

Prune retired Chinese page translations

• Adds donation-owned accounting copy and removes Chinese translations for the retired pre-relaunch pages and global donation band.

config/locales/pages.zh.yml

ru.ymlLocalize the Russian relaunch chrome +21/-36

Localize the Russian relaunch chrome

• Adds Russian navbar and footer labels, repoints community and donation links, and removes translations tied to the retired Telegram page.

config/locales/ru.yml

zh.ymlLocalize the Chinese relaunch chrome +21/-36

Localize the Chinese relaunch chrome

• Adds Chinese navbar and footer labels, repoints community and donation links, and removes translations tied to the retired Telegram page.

config/locales/zh.yml

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Legacy redirects drop locale 🐞 Bug ≡ Correctness
Description
The new fixed-string legacy redirects discard ?locale=ru/?locale=zh before any controller
callback can persist it, so a direct localized legacy link can land on the replacement page in the
browser/default language. This regresses URLs that previously rendered their explicitly requested
locale.
Code

config/routes.rb[22]

+  get '/introduction',        to: redirect('/')
Evidence
The locale switcher encodes language in the query string, while set_locale only consumes and
stores that parameter during controller processing. The changed route redirects use fixed target
strings and therefore bypass that callback without carrying the query value forward.

app/views/layouts/_locale_switcher.html.erb[23-29]
app/controllers/concerns/multilang.rb[78-89]
config/routes.rb[21-31]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The route-level legacy redirects discard the incoming `locale` query parameter, so localized legacy links can land in the wrong language.

## Issue Context
Locale selection is handled by the controller `around_action`, but route redirects bypass it; redirect targets must explicitly retain supported locale parameters.

## Fix Focus Areas
- config/routes.rb[21-31]
- app/controllers/concerns/multilang.rb[78-89]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Upload test permits 500 🐞 Bug ☼ Reliability
Description
The new /snapshots regression test accepts HTTP 500 as a valid request error, so a
route/controller regression that explicitly returns an internal-server-error response still passes
despite the test claiming cameras can POST successfully. Empty invalid uploads are already handled
as 415 by SnapshotsController#create, making 500 an erroneous outcome rather than an expected
validation response.
Code

test/controllers/redirects_test.rb[R69-71]

+    assert_not response.redirect?, 'the camera upload API was shadowed by a redirect'
+    assert_includes [400, 415, 422, 500], response.status,
+                    "expected a request error for an empty upload, got #{response.status}"
Evidence
The test's accepted status list explicitly includes 500, while the create action returns 415 when
the empty snapshot fails validation; production's generic error handler uses 500 for unhandled
exceptions.

test/controllers/redirects_test.rb[64-71]
app/controllers/snapshots_controller.rb[15-32]
app/controllers/concerns/rescue_handler.rb[26-30]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The upload-route regression test permits HTTP 500, allowing an internal server failure to satisfy the test.

## Issue Context
`SnapshotsController#create` returns 415 for an empty invalid upload; the test should assert the concrete expected client-error response while still checking that no redirect shadows the API.

## Fix Focus Areas
- test/controllers/redirects_test.rb[66-71]
- app/controllers/snapshots_controller.rb[15-32]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can hide the parts of a finding you never read, like the evidence or the agent prompt

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread config/routes.rb
Comment thread test/controllers/redirects_test.rb
@openipc-ai
openipc-ai changed the base branch from feat/new-pages to master August 28, 2026 08:57
# Conflicts:
#	app/assets/stylesheets/application.bootstrap.scss
#	app/assets/stylesheets/pages/_legacy.scss
#	app/controllers/pages_controller.rb
#	app/views/layouts/_footer.html.erb
#	app/views/layouts/_navbar.html.erb
#	app/views/layouts/application.html.erb
#	app/views/pages/_donate.html.erb
#	app/views/pages/donate.html.erb
#	app/views/shared/_cta_band.html.erb
#	config/locales/pages.en.yml
#	config/locales/pages.ru.yml
#	config/locales/pages.zh.yml
#	config/routes.rb
#	test/controllers/page_metadata_test.rb
#	test/controllers/relaunch_pages_test.rb
@openipc-ai
openipc-ai merged commit b95bd73 into master Aug 28, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant