Skip to content

Say what a page is, to anyone who did not open it - #122

Open
openipc-ai wants to merge 1 commit into
feat/design-foundationfrom
feat/layout-partials
Open

Say what a page is, to anyone who did not open it#122
openipc-ai wants to merge 1 commit into
feat/design-foundationfrom
feat/layout-partials

Conversation

@openipc-ai

Copy link
Copy Markdown
Collaborator

Third of five PRs rebasing the June 11 relaunch onto master.

Stacked on #121 — base is feat/design-foundation, because both rewrite
layouts/application.html.erb. Merge #121 first and GitHub will retarget this
to master.

Still no new pages and no IA change. The navigation content is untouched;
only its location and the <head> change.

The problem

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 appeared as a bare URL —
no summary, no image. For a project whose reach is almost entirely people
posting links to each other, that is the wrong thing to be missing.

What's added

A description, an OG/Twitter card set, a canonical and a theme colour. Three
details worth review attention:

  • The canonical carries the path, not the query string. ?locale=ru is a
    rendering of the same page, not a different one. Pointing all three
    translations at one canonical is what stops them competing for the same
    content.
  • og:image is absolute and lives in public/, not the asset pipeline.
    Crawlers don't resolve a relative og:image, and OG images are fetched once
    and cached by URL by every consumer that has seen the link — a fingerprint in
    the name would invalidate those caches for no gain.
  • crossorigin on the font preloads is required even same-origin. Fonts are
    fetched in CORS mode; a preload without it is simply fetched a second time.

What moves

layouts/_navbar.html.erb and layouts/_footer.html.erb, verbatim — same
links, same order, same locale switcher. 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 now means the relaunch can rewrite
navigation in one file a reviewer can read, rather than 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'd run edge to edge; pages that set nothing keep the wrapper they've always
had, and a test holds that.

Tests

test/controllers/page_metadata_test.rb asserts the ways a <head> actually
goes wrong: a missing or duplicated description, a description that came back as
"translation missing", a canonical that kept its query string, a relative
og:image, an og-default.png that isn't there, and a preload naming a font
file _fonts.scss does not generate.

check result
bin/rails test 238 runs, 903 assertions, 0 failures (231 → 238)
i18n-tasks missing none
i18n-tasks unused 102, unchanged — flat because the new key is used

The meta description is written in all three locales; the Chinese is
machine-quality and would benefit from a native-speaker pass.

🤖 Generated with Claude Code

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
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add localized page metadata and modular layout partials

✨ Enhancement 🧪 Tests 🕐 20-40 Minutes

Grey Divider

AI Description

• Add localized SEO and social metadata with stable canonical URLs and preview imagery.
• Preload primary fonts and support accessible, full-width page layouts.
• Extract navigation/footer partials and test metadata, assets, and wrapper compatibility.
Diagram

graph TD
  L["Application Layout"] --> H["Page Metadata"] --> C["Search and Social"]
  T["Locale Descriptions"] --> H
  L --> N["Navbar Partial"]
  L --> F["Footer Partial"]
  L --> M["Content Wrapper"]
Loading
High-Level Assessment

The inline layout metadata with localized defaults and an optional controller description is appropriate for this baseline, while partial extraction keeps unrelated navigation and footer markup reviewable. A dedicated metadata presenter or per-page content blocks would add flexibility, but are unnecessary until pages need distinct titles, images, or card types.

Files changed (7) +213 / -64

Enhancement (4) +52 / -64
application.html.erbAdd metadata, font preloads, and flexible page framing +49/-64

Add metadata, font preloads, and flexible page framing

• Adds localized descriptions, canonical and social metadata, theme color, and preload hints for primary fonts. It renders extracted shell partials, adds a skip link, and supports full-width content while preserving contained flashes and default page wrapping.

app/views/layouts/application.html.erb

en.ymlAdd the English default metadata description +1/-0

Add the English default metadata description

• Defines the English fallback description used by page, Open Graph, and search metadata.

config/locales/en.yml

ru.ymlAdd the Russian default metadata description +1/-0

Add the Russian default metadata description

• Defines a Russian fallback description so localized pages publish native metadata.

config/locales/ru.yml

zh.ymlAdd the Chinese default metadata description +1/-0

Add the Chinese default metadata description

• Defines a Chinese fallback description so localized pages publish native metadata.

config/locales/zh.yml

Refactor (2) +72 / -0
_footer.html.erbExtract the existing footer into a layout partial +27/-0

Extract the existing footer into a layout partial

• Moves the footer markup out of the application layout without changing its links or ordering. Social icons continue using asset_path so fingerprinted production assets resolve correctly.

app/views/layouts/_footer.html.erb

_navbar.html.erbExtract navigation into a dedicated layout partial +45/-0

Extract navigation into a dedicated layout partial

• Moves the existing navbar, dropdowns, and locale switcher into a focused partial. Navigation content and ordering remain unchanged.

app/views/layouts/_navbar.html.erb

Tests (1) +89 / -0
page_metadata_test.rbCover metadata integrity and layout compatibility +89/-0

Cover metadata integrity and layout compatibility

• Adds integration coverage for unique localized descriptions, query-free canonical URLs, absolute and existing preview imagery, valid font preloads, and preservation of the default content container.

test/controllers/page_metadata_test.rb

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

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

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

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