Skip to content

Rebrand/miez UI - #55

Merged
flvvius merged 19 commits into
mainfrom
rebrand/miez-ui
Jul 12, 2026
Merged

Rebrand/miez UI#55
flvvius merged 19 commits into
mainfrom
rebrand/miez-ui

Conversation

@flvvius

@flvvius flvvius commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features
    • Rebranded the app as Miez across web and native experiences.
    • Added first-visit onboarding with localized guidance.
    • Added contact forms, administrator message handling, and funding/methodology pages.
    • Added installable web app metadata and refreshed icons.
  • Improvements
    • Updated story views with clearer core and perspective-axis presentation.
    • Refreshed branding, colors, logos, sharing cards, and SEO metadata.
    • Added methodology guidance beneath source coverage and improved sharing text.
  • Bug Fixes
    • Updated saved theme and search preferences to work with the new branding.

flvvius and others added 16 commits July 12, 2026 00:02
Replace the blue brand primary (reads as a party colour) with a neutral
warm-graphite ink, and introduce the Miez camp system:
- --camp-a (reformist, teal), --camp-b (suveranist, terracotta), --core
  (neutral sand/gold), each with -fg and -surface variants, in :root + .dark
  and exposed as Tailwind utilities via @theme inline.
- Camps tuned to near-equal lightness/chroma so neither reads as louder.
- Rename theme storage key biviant-theme-preference -> miez-theme-preference
  (constant + e2e spec).
- design-system.test: assert camp tokens exist and stay perceptually symmetric.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Single source packages/i18n/brand.ts: BRAND_NAME = "Miez" (cascades to all
  interpolated web + native strings, titles, SEO strings).
- BrandLogo: replace dual-PNG lockup with an inline-SVG wordmark in
  currentColor (theme-adaptive, no image swap); the "e" is the sliced-disc
  core motif (ring + centre dot). Drop old logo-biviant*.png.
- Add public/favicon.svg (core mark) + public/manifest.webmanifest
  (name/short_name/theme_color/icons/lang=ro); wire both into <head>, update
  theme-color to the new dark base.
- Rename cosmetic literals: data-export filename, feed recent-search storage
  key, JSON-LD logo path.
- Native: app.json display name -> Miez (bundle IDs + SecureStore biviant.*
  keys deliberately retained; see docs/MIEZ_REBRAND.md).
- docs/MIEZ_REBRAND.md: raster-asset TODOs + intentionally-retained identifiers
  (BiviantBot crawler token, storage keys, bundle IDs, domains -> MIEZ-9).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Re-layout EventDetailTabs to the Miez model, current data only, no new API:
- Promote the neutral summary to a "Miezul" core block up top (core-token
  tinted); falls back to the pending state with a TODO(backend) for a
  dedicated common-summary field.
- Split reformist/suveranist into two equal-weight camp-tinted crusts
  ("Coaja reformistă" / "Coaja suveranistă"): side by side on desktop
  (grid), tab-switched on mobile — single DOM (forceMount) so both stay
  crawlable. Reformist takes the fixed left slot (documented arbitrary axis
  order); mobile opens on a per-session-random crust so neither is default.
- Respect v7: a non-diverging side stays hidden; a lone crust renders full
  width. CASE D (perspectiveApplicable=false) keeps the no-axis note.
- Sources stay shared below both crusts (API has no per-perspective source
  attribution — per-crust lists would fabricate a camp→source mapping;
  TODO(backend) noted). Global impact demoted to the bottom (MIEZ-4).
- Add event.core / event.crustReformist / event.crustSuveranist strings.
- Rewrite the component test for the new structure (8 passing).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Replace the always-open "Ce înseamnă asta" section with a collapsed-by-
  default native <details> accordion labelled "Context global", below the
  crusts and off the initial viewport. No backend change.
- Add a guarded captureEvent() helper on the PostHog singleton; fire
  "global_impact_expand" (with eventId) once per expand so there's data to
  justify killing or fixing the section later.
- Add event.globalContext string; test asserts closed-on-load + expand event.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Centralize the Miez vocabulary in packages/i18n (ro + en):
- Rework SEO title/description to "fiecare știre, din ambele tabere" — drop
  the old "analizată fapt cu fapt" tagline; no "adevărul"/"obiectiv"
  self-description.
- feed.none -> "Nicio știre nouă. Miezul se coace."; feed.loading ->
  "Tăiem coaja…".
- Add axis.reformist/suveranist/tooltip/methodologyCta (MIEZ-6),
  onboarding.valueLine (MIEZ-8), share.eventText (share sheet), and the
  MIEZ-7 footer.methodology/funding labels.
- Share sheet now uses "Vezi miezul acestei știri:" + URL; drop the unused
  summary prop from ShareEventButton and its call site.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add /metodologie (axis placement is per-outlet not per-article, orientation
  separate from reliability, axis calculated not decreed, how to contest a
  placement) and /finantare (funding transparency; no invented business
  details, real specifics left as a marked TODO per FOOTER_TODO convention).
- Both use the shared StaticPage components, are indexable (staticPageHead,
  no noindex), and are linked from the footer (methodology under Resources,
  funding under About). The methodology is also linked from the axis
  explanation under sources (MIEZ-6).
- Regenerate routeTree.gen.ts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- BiasIndicator becomes the camp axis: camp-a (reformist) → --core centre
  zone → camp-b (suveranist) gradient, the source dot coloured by camp/core,
  and equal-type end labels "Reformist"/"Suveranist" tinted with the matched
  camp -fg tokens. Symmetric by construction (reformist pinned left since
  bias runs -5→+5; documented as an arbitrary fixed choice). Renders at
  list-item (sm) and detail (lg) sizes; track carries the axis.tooltip title.
- SourceCoverageSummary shows the axis explanation + "Vezi metodologia" link
  once under the axes (only when sources exist), wiring the tooltip to
  /metodologie.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add MiezOnboarding: a single dismissible screen shown exactly once per
  device (localStorage miez-onboarding-v1), rendered at the root. The
  three-beat pitch ("Presa s-a rupt în două tabere" / "Miez îți arată ambele"
  / "Gratuit, fără cont") over the sliced-disc motif (two camps + core),
  CTA "Vezi miezul zilei" into the feed. Skippable (skip button, backdrop,
  Escape); no account prompt anywhere. Renders nothing on SSR / for returning
  devices, so no flash.
- Fire onboarding_dismiss with the dismissal reason.
- Add onboarding.miez.* strings (ro + en). Test covers show-once, dismiss,
  CTA navigation, and the no-account guarantee.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- seo.ts: canonical/og host -> https://www.miez.news (og:image too); JSON-LD
  org becomes NewsMediaOrganization (name/logo already Miez). og:site_name is
  Miez via BRAND_NAME.
- Story <title> pattern -> "«story» | Miez".
- sitemap.ts default host -> www.miez.news.
- Event share card (shareAssetsNode.ts): drop the blue "B" mark/BIVIANT
  wordmark for the Miez core mark (gold ring + dot) + "MIEZ", gold accents
  instead of party-blue, tagline "Every story, from both camps", footer
  "Shared from miez.news".
- Native lib/site.ts SITE_URL -> miez.news (+ test, comments).
- Email/auth infra domains intentionally deferred to the infra cutover
  (needs DNS + email verification + auth origins); documented in
  docs/MIEZ_REBRAND.md.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Land the real Miez mark: logo-mark.png (512, teal/coral disc + core) and
  apple-touch-icon.png (180). BrandLogo now renders the PNG mark + "miez"
  wordmark (wordmark hidden on mobile in the header, mark-only); apple-touch
  points at the dedicated icon.
- manifest.webmanifest: add id, categories:["news"], and the 512 PNG icon
  alongside the SVG so the PWA install prompt has a real raster icon.
- docs/MIEZ_REBRAND.md: record the store-listing text (title "Miez – știri
  din ambele tabere", short description, 4 screenshots, adaptive icon —
  managed in App Store Connect / Play Console, no in-repo files) and the
  remaining raster TODOs (og-image verify, PWA screenshots, native icons).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add docs/MIEZ_QA.md — the signed-off checklist for the Biviant → Miez UI
rebrand. Automated gates green: web tsc + 84 tests + production build,
backend 272, native 39, design-system symmetry/dark-parity enforcement.
Leftover-Biviant grep clean except the documented BiviantBot crawler token.
Records neutrality/diacritics/dark-mode checks and the known follow-ups
(crawler rename, email/auth domain cutover, raster TODOs, backend TODOs).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The Miezul-core + two-crust layout didn't land visually. Restore the original
perspective tabs (reformist / centre / suveranist) with their exact styling —
underline triggers, forceMount panels, AI disclosure placement, CASE D note —
and only relabel the centre "Neutră" tab to "Miezul" (event.core). The MIEZ-4
global-impact accordion is kept. Test restored to the 3-tab behaviour + the
accordion case.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Restore the plain "Ce înseamnă asta" (event.meaning) global-impact section
instead of the collapsed "Context global" <details> accordion; drop the
expand analytics + unused captureEvent import. Test updated to assert the
section renders.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The feed event-card distribution bar (and the source-coverage bar) render from
the --bias-* tokens, which were still the old indigo/amber. Repoint them to the
reformist–suveranist camp palette: left = camp-a teal, right = camp-b
terracotta, centre = neutral core (light + dark), kept near-equal L/C so
neither side reads louder. Update the design-system test description.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a general contact form on /contact that persists messages for admins and
emails the operators on arrival.

- Schema: contactMessages table (name/email/subject/message/status) indexed
  by_status_createdAt.
- convex/contact.ts: submitContactMessage (public, validated, rate-limited
  per-sender + global), listContactMessagesForAdmin + markContactMessageHandled
  (admin-guarded).
- convex/emails.ts: sendContactMessageEmail internal action → ADMIN_EMAILS,
  reply-to set to the sender so admins answer directly.
- /admin/contact dashboard route: read messages, mark handled, quick reply.
- ContactForm component wired into the /contact page (no account needed).
- Tests: contact.test.ts (store + schedule email + validation + rate limit);
  footer-pages.test stubs useMutation so the page still renders provider-less.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
news Error Error Jul 12, 2026 7:55am
news-web Ready Ready Preview, Comment Jul 12, 2026 7:55am

@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@flvvius, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 22 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4302e7d7-2661-4e44-a69b-9cab146bc65d

📥 Commits

Reviewing files that changed from the base of the PR and between a21578c and e0fe12e.

⛔ Files ignored due to path filters (1)
  • apps/web/src/routeTree.gen.ts is excluded by !**/routeTree.gen.ts
📒 Files selected for processing (26)
  • apps/web/src/components/MiezOnboarding.test.tsx
  • apps/web/src/components/MiezOnboarding.tsx
  • apps/web/src/components/contact-form.tsx
  • apps/web/src/index.css
  • apps/web/src/routes/__root.tsx
  • apps/web/src/routes/bot.tsx
  • apps/web/src/routes/event.$slug.tsx
  • apps/web/src/routes/llms[.]txt.ts
  • apps/web/src/routes/publishers.tsx
  • apps/web/src/routes/reset-password.tsx
  • packages/backend/convex/auth.ts
  • packages/backend/convex/brand.ts
  • packages/backend/convex/compliance.test.ts
  • packages/backend/convex/config.ts
  • packages/backend/convex/contact.ts
  • packages/backend/convex/emails.ts
  • packages/backend/convex/events.ts
  • packages/backend/convex/feeds.smoke.test.ts
  • packages/backend/convex/lib/articleExtraction.ts
  • packages/backend/convex/lib/botIdentity.ts
  • packages/backend/convex/lib/consent.ts
  • packages/backend/convex/lib/tdmPolicy.ts
  • packages/backend/convex/politeFetch.test.ts
  • packages/backend/convex/shareAssets.ts
  • packages/backend/convex/tdmPermissions.test.ts
  • packages/i18n/src/strings.ts

Walkthrough

The PR rebrands the applications from Biviant to Miez, adds onboarding and contact workflows, introduces funding and methodology pages, updates camp-axis presentation, and revises web metadata, sharing, localization, and design tokens.

Changes

Miez product update

Layer / File(s) Summary
Identity and branding
apps/native/*, apps/web/public/*, apps/web/src/components/BrandLogo.tsx, apps/web/src/lib/*, apps/web/src/routes/__root.tsx, apps/web/src/routes/event.$slug.tsx, apps/web/src/routes/feed.tsx, packages/backend/convex/shareAssetsNode.ts, packages/backend/convex/sitemap.ts, packages/i18n/src/*
Application names, domains, metadata, logos, share assets, storage keys, and brand copy now use Miez identifiers and URLs.
Camp axis presentation
apps/web/src/components/bias-indicator.tsx, apps/web/src/components/feed/*, apps/web/src/design-system.test.ts, apps/web/src/index.css, packages/i18n/src/strings.ts
Camp/core tokens, bias-axis labels, event sections, methodology messaging, and localized copy are updated and tested for symmetry.
First-run onboarding flow
apps/web/src/components/MiezOnboarding.tsx, apps/web/src/components/MiezOnboarding.test.tsx, apps/web/src/lib/posthog.tsx, apps/web/src/routes/__root.tsx
A localized device-level onboarding modal supports dismissal paths, persistence, telemetry, CTA navigation, and automated coverage.
Contact submission and administration
packages/backend/convex/schema.ts, packages/backend/convex/contact.ts, packages/backend/convex/emails.ts, packages/backend/convex/contact.test.ts, apps/web/src/components/contact-form.tsx, apps/web/src/routes/contact.tsx, apps/web/src/routes/admin.contact.tsx
Contact messages are validated, rate-limited, persisted, emailed to administrators, listed in an admin route, and marked handled.
Public information pages and navigation
apps/web/src/routes/finantare.tsx, apps/web/src/routes/metodologie.tsx, apps/web/src/components/layout/Footer.tsx, apps/web/src/routes/contact.tsx, apps/web/src/routes/footer-pages.test.tsx
Funding and methodology pages are added, footer links are extended, and contact-page rendering tests are updated.
Event sharing and validation documentation
apps/web/src/components/share-event-button.tsx, apps/web/src/routes/event.$slug.tsx, docs/MIEZ_QA.md, docs/MIEZ_REBRAND.md
Event sharing uses localized text without the summary prop, while QA and rebrand requirements are documented.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • flvvius/news#3: Updates the same SEO metadata and organization schema.
  • flvvius/news#6: Intersects with the bias-indicator threshold and presentation changes.
  • flvvius/news#51: Overlaps with the contact-page user flow.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 36.36% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main theme of the changes: a Miez UI rebrand across web, native, and related assets.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rebrand/miez-ui

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/src/components/contact-form.tsx`:
- Around line 1-131: Replace the hardcoded user-facing Romanian strings in
ContactForm, including validation toasts, labels, button states, and success
confirmation text, with translations obtained through the app’s established
useT() i18n hook. Add the hook to the component and use translation keys for
every rendered or toasted message while preserving the existing form behavior.
- Around line 63-79: Update the confirmation container returned by the sent
state in the contact form to include an appropriate ARIA live-region attribute
and status role, ensuring screen readers announce the successful submission
while preserving the existing content and behavior.

In `@apps/web/src/components/MiezOnboarding.test.tsx`:
- Around line 50-52: Update the text assertions in the onboarding dialog test to
use case-insensitive regular expressions with word boundaries instead of bare
toContain checks. Ensure “cont” matches as a standalone word regardless of
punctuation or spacing, and “sign” does not match words such as “design” or
“signal”; preserve the existing prohibition on “log in.”

In `@apps/web/src/components/MiezOnboarding.tsx`:
- Around line 59-72: Add a JavaScript focus trap to the outer dialog in
MiezOnboarding, using a modal ref and the existing onKeyDown handler. Keep focus
cycling between the dialog’s first and last focusable elements when Tab or
Shift+Tab reaches either boundary, and attach the ref to the element with
role="dialog" so keyboard focus cannot escape the onboarding modal.

In `@apps/web/src/index.css`:
- Line 143: Update the inline comment on the --bias-right CSS variable to
include whitespace before the closing comment delimiter, preserving the variable
value and existing comment text.

In `@apps/web/src/routes/__root.tsx`:
- Line 114: Update the theme-color metadata in the root document head to use the
actual light and dark background token values instead of the hard-coded `#17181c`.
Add separate prefers-color-scheme-scoped entries so browser chrome follows the
active light or dark theme, while preserving the existing metadata structure.

In `@apps/web/src/routes/contact.tsx`:
- Line 3: Update ContactForm so every input and textarea has an appropriate
aria-label, and mark the successful-submit status message with the required role
and aria-live attributes. Preserve the existing form behavior and message
content while ensuring assistive technology announces both fields and submission
results.

In `@packages/backend/convex/contact.ts`:
- Around line 117-118: Update requireAdminUser in lib/betaAccess to return a
type that explicitly includes the administrator’s email, preserving its existing
authentication and authorization behavior. Then update the handledByEmail
assignment in the contact flow to access admin.email directly without a type
assertion, while retaining appropriate null/undefined handling if the helper
permits it.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 2a24921a-a7fe-4342-9690-6ec99613de60

📥 Commits

Reviewing files that changed from the base of the PR and between 003f7b0 and a21578c.

⛔ Files ignored due to path filters (7)
  • apps/web/public/apple-touch-icon.png is excluded by !**/*.png
  • apps/web/public/favicon.svg is excluded by !**/*.svg
  • apps/web/public/logo-biviant-dark.png is excluded by !**/*.png
  • apps/web/public/logo-biviant.png is excluded by !**/*.png
  • apps/web/public/logo-mark.png is excluded by !**/*.png
  • apps/web/src/routeTree.gen.ts is excluded by !**/routeTree.gen.ts
  • packages/backend/convex/_generated/api.d.ts is excluded by !**/_generated/**, !**/_generated/**
📒 Files selected for processing (40)
  • apps/native/app.json
  • apps/native/lib/site.test.ts
  • apps/native/lib/site.ts
  • apps/web/e2e/theme.spec.ts
  • apps/web/public/manifest.webmanifest
  • apps/web/src/components/BrandLogo.tsx
  • apps/web/src/components/MiezOnboarding.test.tsx
  • apps/web/src/components/MiezOnboarding.tsx
  • apps/web/src/components/bias-indicator.tsx
  • apps/web/src/components/contact-form.tsx
  • apps/web/src/components/feed/event-detail-tabs.test.tsx
  • apps/web/src/components/feed/event-detail-tabs.tsx
  • apps/web/src/components/feed/source-coverage-summary.tsx
  • apps/web/src/components/header.tsx
  • apps/web/src/components/layout/Footer.tsx
  • apps/web/src/components/profile/AuthenticatedProfile.tsx
  • apps/web/src/components/share-event-button.tsx
  • apps/web/src/design-system.test.ts
  • apps/web/src/index.css
  • apps/web/src/lib/posthog.tsx
  • apps/web/src/lib/seo.ts
  • apps/web/src/lib/theme/index.ts
  • apps/web/src/routes/__root.tsx
  • apps/web/src/routes/admin.contact.tsx
  • apps/web/src/routes/contact.tsx
  • apps/web/src/routes/event.$slug.tsx
  • apps/web/src/routes/feed.tsx
  • apps/web/src/routes/finantare.tsx
  • apps/web/src/routes/footer-pages.test.tsx
  • apps/web/src/routes/metodologie.tsx
  • docs/MIEZ_QA.md
  • docs/MIEZ_REBRAND.md
  • packages/backend/convex/contact.test.ts
  • packages/backend/convex/contact.ts
  • packages/backend/convex/emails.ts
  • packages/backend/convex/schema.ts
  • packages/backend/convex/shareAssetsNode.ts
  • packages/backend/convex/sitemap.ts
  • packages/i18n/src/brand.ts
  • packages/i18n/src/strings.ts

Comment thread apps/web/src/components/contact-form.tsx
Comment thread apps/web/src/components/contact-form.tsx
Comment on lines +50 to +52
expect(dialog.textContent?.toLowerCase()).not.toContain("cont ");
expect(dialog.textContent?.toLowerCase()).not.toContain("log in");
expect(dialog.textContent?.toLowerCase()).not.toContain("sign");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Use word-boundary matching instead of bare substring checks.

not.toContain("sign") would false-positive on words like "design" or "signal", and not.toContain("cont ") misses "cont," or "cont." — both creating fragile test assertions. Use regex with word boundaries for accuracy.

💚 Proposed fix
-    expect(dialog.textContent?.toLowerCase()).not.toContain("cont ");
-    expect(dialog.textContent?.toLowerCase()).not.toContain("log in");
-    expect(dialog.textContent?.toLowerCase()).not.toContain("sign");
+    expect(dialog.textContent?.toLowerCase()).not.toMatch(/\bcont\b/);
+    expect(dialog.textContent?.toLowerCase()).not.toMatch(/\b(log in|sign in|sign up)\b/);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
expect(dialog.textContent?.toLowerCase()).not.toContain("cont ");
expect(dialog.textContent?.toLowerCase()).not.toContain("log in");
expect(dialog.textContent?.toLowerCase()).not.toContain("sign");
expect(dialog.textContent?.toLowerCase()).not.toMatch(/\bcont\b/);
expect(dialog.textContent?.toLowerCase()).not.toMatch(/\b(log in|sign in|sign up)\b/);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/components/MiezOnboarding.test.tsx` around lines 50 - 52, Update
the text assertions in the onboarding dialog test to use case-insensitive
regular expressions with word boundaries instead of bare toContain checks.
Ensure “cont” matches as a standalone word regardless of punctuation or spacing,
and “sign” does not match words such as “design” or “signal”; preserve the
existing prohibition on “log in.”

Comment thread apps/web/src/components/MiezOnboarding.tsx
Comment thread apps/web/src/index.css Outdated
Comment thread apps/web/src/routes/__root.tsx Outdated
@@ -1,5 +1,6 @@
import { createFileRoute } from "@tanstack/react-router";
import { StaticPage, StaticSection } from "@/components/layout/StaticPage";
import { ContactForm } from "@/components/contact-form";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Make the embedded contact form announceable to assistive technology.

ContactForm omits aria-label on its inputs/textarea, and its successful-submit message has no role or aria-live; users of screen readers may not receive the submission result.

Proposed fix
-      <div className="rounded-lg border border-border bg-muted/30 p-4 text-sm">
+      <div
+        role="status"
+        aria-live="polite"
+        className="rounded-lg border border-border bg-muted/30 p-4 text-sm"
+      >
...
         <Input
           id="contact-name"
+          aria-label="Nume"
...
         <Input
           id="contact-email"
+          aria-label="E-mail"
...
         <Input
           id="contact-subject"
+          aria-label="Subiect"
...
         <textarea
           id="contact-message"
+          aria-label="Mesaj"

As per coding guidelines, “Forms must have aria-label on inputs and ARIA live regions (aria-live, role) on status messages.” As per path instructions, “Focus on web performance and accessibility.”

Also applies to: 23-30

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/src/routes/contact.tsx` at line 3, Update ContactForm so every input
and textarea has an appropriate aria-label, and mark the successful-submit
status message with the required role and aria-live attributes. Preserve the
existing form behavior and message content while ensuring assistive technology
announces both fields and submission results.

Sources: Coding guidelines, Path instructions

Comment thread packages/backend/convex/contact.ts Outdated
Comment on lines +117 to +118
handledByEmail:
(admin as { email?: string } | null | undefined)?.email ?? undefined,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Replace type assertion with proper typing for handledByEmail.

The cast (admin as { email?: string } | null | undefined)?.email bypasses TypeScript's type system. If requireAdminUser's return type doesn't include email, this silently yields undefined instead of a compile error. The root cause is likely that requireAdminUser returns a generic or incomplete type. Fix the return type of requireAdminUser to include email, then access admin.email directly.

As per path instructions for packages/backend/**: "Check for proper error handling" and "Verify authentication and authorization logic."

♻️ Proposed refactor
-    await ctx.db.patch(messageId, {
-      status: "handled",
-      handledAt: Date.now(),
-      handledByEmail:
-        (admin as { email?: string } | null | undefined)?.email ?? undefined,
-    });
+    await ctx.db.patch(messageId, {
+      status: "handled",
+      handledAt: Date.now(),
+      handledByEmail: admin?.email ?? undefined,
+    });

(Requires requireAdminUser to return a type with email: string — verify and update its signature in ./lib/betaAccess.)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/backend/convex/contact.ts` around lines 117 - 118, Update
requireAdminUser in lib/betaAccess to return a type that explicitly includes the
administrator’s email, preserving its existing authentication and authorization
behavior. Then update the handledByEmail assignment in the contact flow to
access admin.email directly without a type assertion, while retaining
appropriate null/undefined handling if the helper permits it.

Source: Path instructions

SEO / AI accessibility:
- Add /llms.txt (llmstxt.org index) so AI crawlers can discover and cite
  the site, its sections, and how the AI-generated summaries relate to
  the original publications.
- Consolidate event-page structured data to a single NewsArticle block in
  <head> (was two conflicting Article + NewsArticle blocks); keep the L1
  AI-Act IPTC generation marking + isBasedOn source list; inLanguage=ro.
- Add noindex,nofollow to the tokenized reset-password route.

Rebrand crawler + email from Biviant to Miez:
- Crawler UA BiviantBot -> MiezBot, info URL -> https://www.miez.news/bot
  (tdmPolicy, botIdentity, articleExtraction, /bot page, /publishers,
  footer string, and all crawler tests).
- Backend BRAND_NAME Biviant -> Miez (was out of sync with i18n).
- Email hello@biviant.com -> hello@miez.news; site/unsub/share URLs and
  link text -> www.miez.news (config, emails, auth).
- Waitlist consent text -> Miez, version bumped to 2026-07-12.v1 to keep
  prior signups tied to their original wording.

Apple bundle ids (com.biviant.*) and the native iOS project are left
unchanged (separate rebrand; changing them breaks native auth).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@flvvius
flvvius merged commit 8d3f9af into main Jul 12, 2026
4 of 5 checks passed
@flvvius
flvvius deleted the rebrand/miez-ui branch July 12, 2026 07:56
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