Skip to content

Conversation

jjmata
Copy link
Collaborator

@jjmata jjmata commented Oct 1, 2025

TODOs:

  • A few interpolations have the wrong product vs. product_name token ... see comments
  • Search for "Welcome to Sure" and fix that hardcoded string in the trial/subscriptions flow

Desctiption

A bit ambitious, but let's see how people like this ... instead of changing all the Maybe strings into Sure decided to implement a white-labeling strategy that lets you change the product name if you hate it (like some do!) :-)

We define two strings with these defaults:

  • BRAND_NAME: FOSS
  • PRODUCT_NAME: Sure

... and sprinkle it all over the codebase with replacement tokens.

Thoughts?

Summary by CodeRabbit

  • New Features

    • App now supports configurable product and brand names from environment settings; titles, footer, PWA manifest, email sender, headers, and helpers expose them.
  • Localization

    • Parameterized product/brand across English, Norwegian (nb), and Turkish (tr); many labels, prompts, and email templates updated to use the product_name/brand_name.
  • Content

    • Onboarding copy changed to "What brings you here?"
  • Documentation

    • Docker verification command updated.
  • Tests

    • Tests updated to match revised onboarding text.

Copy link

coderabbitai bot commented Oct 1, 2025

Walkthrough

Adds configurable product and brand names via ENV and initializer, exposes helper accessors, updates mailer defaults and translation arguments, replaces hardcoded product strings across views and locales, adjusts provider User-Agent, removes one unused private method, and updates related tests and docs.

Changes

Cohort / File(s) Summary of changes
Branding config
/.env.example, config/initializers/brand.rb
Adds PRODUCT_NAME and BRAND_NAME env vars and initializes config.x.product_name and config.x.brand_name with defaults.
Helpers
/app/helpers/application_helper.rb
Adds product_name and brand_name helper accessors returning Rails.configuration.x values.
Application mailer
/app/mailers/application_mailer.rb
Uses dynamic brand_name/product_name for default from, adds before_action :assign_branding, exposes helper_methods and sets instance vars.
Mailers (subjects / args)
/app/mailers/email_confirmation_mailer.rb, app/mailers/invitation_mailer.rb, app/mailers/password_mailer.rb
Subject translation calls now include product_name/product: interpolation arguments.
Mailer templates
/app/views/invitation_mailer/invite_email.html.erb, /app/views/password_mailer/password_reset.html.erb
Translation calls updated to pass product: product_name (greeting/body updated).
Views / Layouts
/app/views/layouts/shared/_head.html.erb, /app/views/layouts/shared/_footer.html.erb, /app/views/layouts/auth.html.erb
Title/meta defaults, footer copyright, and auth no_account text now use product_name/brand_name.
UI templates (product text)
/app/views/...
accounts/_account_sidebar_tabs.html.erb, doorkeeper/authorizations/new.html.erb, import/confirms/_mappings.html.erb, invitations/new.html.erb, onboardings/goals.html.erb, pages/feedback.html.erb, settings/billings/show.html.erb, settings/hostings/_invite_code_settings.html.erb, settings/profiles/show.html.erb
Replace hardcoded product mentions with product_name interpolation; onboarding goals heading text updated to "What brings you here?".
PWA manifest
/app/views/pwa/manifest.json.erb
name, short_name, and description set dynamically via escaped product_name.
Provider header
/app/models/provider/simplefin.rb
User-Agent header now includes #{Rails.configuration.x.product_name}.
Demo generator
/app/models/demo/generator.rb
Removed unused private partner_email_for method; inline construction remains.
Locales — defaults & mailers
/config/locales/defaults/*.yml, /config/locales/mailers/**, /config/locales/views/email_confirmation_mailer/*
Add brand_name and product_name interpolation keys; mailer subjects/greetings/bodies parameterized with %{product_name} (some files gained YAML doc separators).
Locales — views (imports, layout, onboarding, settings, subscriptions)
/config/locales/views/**
Many translation keys updated to replace literal product names with %{product_name}; some keys renamed (e.g., maybe_mapping_labelsure_mapping_label) and strings re-quoted/adjusted per locale.
Docs
/docs/hosting/docker.md
Updated docker verification command container name (sure-db-1sure-postgres-1).
Tests
/test/controllers/onboardings_controller_test.rb, /test/system/onboardings_test.rb, /test/mailers/email_confirmation_mailer_test.rb
Updated expectations to reflect changed UI text and translation calls (onboarding heading and mailer subject now include/interpolate product_name).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User
  participant Controller
  participant View
  participant Helper as ApplicationHelper
  participant Config as Rails.config.x

  User->>Controller: GET page
  Controller->>View: render template
  View->>Helper: call product_name()
  Helper->>Config: read product_name
  Config-->>Helper: value
  Helper-->>View: product_name
  View-->>User: HTML with dynamic product/brand text
Loading
sequenceDiagram
  autonumber
  participant Mailer as ApplicationMailer
  participant Config as Rails.config.x
  participant I18n

  Mailer->>Config: read brand_name & product_name
  Mailer->>Mailer: set @brand_name/@product_name (before_action)
  Mailer->>Mailer: default from via email_address_with_name(brand_name, product_name)
  Mailer->>I18n: t(".subject", product: product_name, ...)
  Mailer-->>Mailer: build and deliver message
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • matthieuEv

Poem

A twitch, a hop — names now sing,
Brand and product take to wing.
Mail and views wear fresh new names,
Locales hop in tiny frames.
🐇✨ Hooray — the rabbit smiles and claims the spring.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly and accurately describes the primary change of making the application’s branding configurable rather than using hardcoded strings.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6c0c75 and 4077f6e.

📒 Files selected for processing (1)
  • app/views/password_mailer/password_reset.html.erb (1 hunks)
🧰 Additional context used
📓 Path-based instructions (14)
app/views/**/*.erb

📄 CodeRabbit inference engine (AGENTS.md)

app/views/**/*.erb: Keep heavy logic out of ERB views; prefer helpers/components instead
ERB templates are linted by erb-lint per .erb_lint.yml

Always use the icon helper (icon) for icons; never call lucide_icon directly

Files:

  • app/views/password_mailer/password_reset.html.erb
app/views/**/*.html.*

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

app/views/**/*.html.*: Use partials only for simple, context-specific, mostly static HTML content.
Prefer semantic HTML; use Turbo Frames where possible instead of client-side solutions.
Use query params for state, not localStorage or sessionStorage.
Always perform server-side formatting for currencies, numbers, and dates.

Files:

  • app/views/password_mailer/password_reset.html.erb
**/*.{html,erb,slim,js,jsx,ts,tsx,css,scss}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Always use functional design tokens (e.g., text-primary, bg-container) from the design system; do not use raw colors or ad-hoc classes.

Files:

  • app/views/password_mailer/password_reset.html.erb
**/app/**/*.erb

📄 CodeRabbit inference engine (CLAUDE.md)

Always use the icon helper for icons in templates; never use lucide_icon directly.

Files:

  • app/views/password_mailer/password_reset.html.erb
**/app/views/**/*.erb

📄 CodeRabbit inference engine (CLAUDE.md)

**/app/views/**/*.erb: Keep domain logic OUT of view templates; logic belongs in component files, not templates.
Use partials only for primarily static, simple HTML with minimal logic, and only when not likely to be reused.
Prefer native HTML over JavaScript components for UI elements (e.g., use <dialog>, <details><summary>).
Leverage Turbo frames for page sections over client-side JavaScript solutions.
Use query params (not localStorage/sessions) for client state management.
Perform server-side formatting for currencies, numbers, and dates in templates.

Files:

  • app/views/password_mailer/password_reset.html.erb
**/app/**/*.{rb,erb,js,css}

📄 CodeRabbit inference engine (CLAUDE.md)

Push Rails to its limits before adding new dependencies; a strong technical/business reason is required for new dependencies.

Files:

  • app/views/password_mailer/password_reset.html.erb
**/*.{rb,erb,haml,slim}

📄 CodeRabbit inference engine (.cursor/rules/general-rules.mdc)

**/*.{rb,erb,haml,slim}: Use Current.user for the current user; do not use current_user
Use Current.family for the current family; do not use current_family
Ignore i18n methods; hardcode strings in English for now (do not use I18n.t, t, or similar)

Files:

  • app/views/password_mailer/password_reset.html.erb
app/views/**/*.html.erb

📄 CodeRabbit inference engine (.cursor/rules/project-conventions.mdc)

app/views/**/*.html.erb: Prefer native HTML elements (e.g., ,

) over JS-based components
Leverage Turbo frames to break up pages instead of JS-driven client-side solutions
Prefer native client-side form validation when possible

Files:

  • app/views/password_mailer/password_reset.html.erb
app/{models,controllers,views}/**/*.{rb,erb}

📄 CodeRabbit inference engine (.cursor/rules/project-conventions.mdc)

Avoid N+1 queries

Files:

  • app/views/password_mailer/password_reset.html.erb
{app/javascript/controllers/**/*.{js,ts},app/views/**/*.erb,app/components/**/*.erb}

📄 CodeRabbit inference engine (.cursor/rules/stimulus_conventions.mdc)

Use declarative Stimulus actions in ERB (data-action) instead of imperative event listeners in controller lifecycle (e.g., avoid addEventListener in connect); controllers should just respond to actions

Files:

  • app/views/password_mailer/password_reset.html.erb
{app/components/**/*.{js,ts,erb},app/views/**/*.erb}

📄 CodeRabbit inference engine (.cursor/rules/stimulus_conventions.mdc)

Component-scoped Stimulus controllers in app/components must be used only within their component views, not in app/views

Files:

  • app/views/password_mailer/password_reset.html.erb
{app/views/**,app/helpers/**,app/javascript/controllers/**}

📄 CodeRabbit inference engine (.cursor/rules/ui-ux-design-guidelines.mdc)

{app/views/**,app/helpers/**,app/javascript/controllers/**}: Style UI using TailwindCSS v4.x with the custom design system defined in app/assets/tailwind/maybe-design-system.css
Always start by referencing app/assets/tailwind/maybe-design-system.css to understand available primitives, functional tokens, and component tokens before styling
Prefer functional tokens from the design system over raw Tailwind values (e.g., use text-primary, bg-container, border border-primary instead of text-white, bg-white, border-gray-200)

Files:

  • app/views/password_mailer/password_reset.html.erb
{app/views/**,app/helpers/**}

📄 CodeRabbit inference engine (.cursor/rules/ui-ux-design-guidelines.mdc)

Always generate semantic HTML

Files:

  • app/views/password_mailer/password_reset.html.erb
{app/views,app/components}/**/*.html.erb

📄 CodeRabbit inference engine (.cursor/rules/view_conventions.mdc)

{app/views,app/components}/**/*.html.erb: Keep domain logic out of ERB templates; compute values in component/controller code and reference them in the template
Integrate Stimulus declaratively in ERB: templates declare data-controller/data-action; controllers respond to those declarations
Pass data from Rails to Stimulus via data-*-value attributes, not inline JavaScript

Files:

  • app/views/password_mailer/password_reset.html.erb
🧠 Learnings (1)
📓 Common learnings
Learnt from: jjmata
PR: we-promise/sure#173
File: app/mailers/email_confirmation_mailer.rb:9-9
Timestamp: 2025-10-01T11:40:36.711Z
Learning: In the we-promise/sure repository, i18n (internationalization) is used throughout the application for translations. When making branding configurable (e.g., product names), it's appropriate to add parameters like `product: product_name` to existing `t()` translation calls rather than replacing them with hardcoded strings.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci / test
🔇 Additional comments (1)
app/views/password_mailer/password_reset.html.erb (1)

1-1: LGTM! Product name interpolation correctly implemented.

The addition of product_name: product_name to the translation call properly implements configurable branding. The helper method is available via ApplicationMailer's helper_method declaration, and the locale files have been updated to accept this parameter.


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 and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

♻️ Duplicate comments (4)
config/locales/views/password_mailer/nb.yml (1)

1-11: Locale file modification violates coding guidelines.

Same as the previous locale file, this modification contradicts the coding guideline: "Ignore i18n files; do not add or modify locale files".

Consider consolidating the branding strategy with the project's localization approach per coding guidelines.

config/locales/views/layout/nb.yml (1)

1-13: Locale file modification violates coding guidelines.

This locale file modification also contradicts the coding guideline about not modifying i18n files.

Align the implementation approach with the project's guidance on i18n handling.

config/locales/defaults/tr.yml (1)

3-5: Locale defaults modification violates coding guidelines.

Adding brand_name and product_name to the Turkish locale defaults also contradicts the coding guideline: "Ignore i18n files; do not add or modify locale files".

While these are default interpolation keys (which may be more fundamental than view-specific translations), the modification still conflicts with the stated guideline to hardcode strings in English for now.

app/mailers/application_mailer.rb (1)

8-15: Duplication flagged in ApplicationHelper review.

These private helper methods duplicate the public helpers in ApplicationHelper. See the review comment on app/helpers/application_helper.rb for a suggested refactoring approach.

🧹 Nitpick comments (4)
.env.example (1)

56-59: Reorder the new keys to match dotenv-linter expectations.

The linter flags that BRAND_NAME should precede PRODUCT_NAME. Please swap their order so the file stays lint-clean. citeturn0static_analysis_hints0

app/views/pages/feedback.html.erb (1)

7-17: Consider making GitHub and Discord URLs configurable for complete white-labeling.

The GitHub repository URLs (lines 7, 12) hardcode "we-promise/sure" and the Discord invite link (line 17) is also static. For a fully configurable white-label solution, these external community/support links should probably be driven by configuration as well (e.g., ENV["GITHUB_REPO"], ENV["DISCORD_INVITE"]), allowing forks to point to their own communities.

app/views/layouts/shared/_footer.html.erb (1)

3-3: Consider making the "community fork of Maybe Finance" text configurable.

The hardcoded reference "(community fork of Maybe Finance)" might also need to be configurable for complete white-labeling. Some forks may not want to reference the origin, or may want different attribution text. Consider using an optional ENV["FORK_ATTRIBUTION"] or similar.

app/helpers/application_helper.rb (1)

4-10: Consider extracting duplicated configuration accessors to a shared concern.

Both ApplicationHelper and ApplicationMailer define identical product_name and brand_name methods. While the duplication is minimal, consolidating these into a shared concern would improve maintainability and ensure consistency.

You could create a concern like app/models/concerns/brandable.rb:

module Brandable
  extend ActiveSupport::Concern

  def product_name
    Rails.configuration.x.product_name
  end

  def brand_name
    Rails.configuration.x.brand_name
  end
end

Then include it in both:

 module ApplicationHelper
   include Pagy::Frontend
+  include Brandable

-  def product_name
-    Rails.configuration.x.product_name
-  end
-
-  def brand_name
-    Rails.configuration.x.brand_name
-  end
 class ApplicationMailer < ActionMailer::Base
+  include Brandable
+
   default from: email_address_with_name(
     ENV.fetch("EMAIL_SENDER", "[email protected]"),
     "#{Rails.configuration.x.brand_name} #{Rails.configuration.x.product_name}"
   )
   layout "mailer"
-
-  private
-    def product_name
-      Rails.configuration.x.product_name
-    end
-
-    def brand_name
-      Rails.configuration.x.brand_name
-    end
 end
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7273878 and 60eb52b.

📒 Files selected for processing (55)
  • .env.example (1 hunks)
  • app/helpers/application_helper.rb (1 hunks)
  • app/mailers/application_mailer.rb (1 hunks)
  • app/mailers/email_confirmation_mailer.rb (1 hunks)
  • app/mailers/invitation_mailer.rb (1 hunks)
  • app/mailers/password_mailer.rb (1 hunks)
  • app/models/demo/generator.rb (0 hunks)
  • app/models/provider/simplefin.rb (1 hunks)
  • app/views/accounts/_account_sidebar_tabs.html.erb (1 hunks)
  • app/views/doorkeeper/authorizations/new.html.erb (1 hunks)
  • app/views/import/confirms/_mappings.html.erb (1 hunks)
  • app/views/invitation_mailer/invite_email.html.erb (1 hunks)
  • app/views/invitations/new.html.erb (1 hunks)
  • app/views/layouts/auth.html.erb (1 hunks)
  • app/views/layouts/shared/_footer.html.erb (1 hunks)
  • app/views/layouts/shared/_head.html.erb (2 hunks)
  • app/views/onboardings/goals.html.erb (1 hunks)
  • app/views/pages/feedback.html.erb (1 hunks)
  • app/views/password_mailer/password_reset.html.erb (1 hunks)
  • app/views/pwa/manifest.json.erb (2 hunks)
  • app/views/settings/billings/show.html.erb (1 hunks)
  • app/views/settings/hostings/_invite_code_settings.html.erb (1 hunks)
  • app/views/settings/profiles/show.html.erb (1 hunks)
  • config/initializers/brand.rb (1 hunks)
  • config/locales/defaults/en.yml (1 hunks)
  • config/locales/defaults/nb.yml (1 hunks)
  • config/locales/defaults/tr.yml (1 hunks)
  • config/locales/mailers/invitation_mailer/en.yml (1 hunks)
  • config/locales/mailers/invitation_mailer/nb.yml (1 hunks)
  • config/locales/mailers/invitation_mailer/tr.yml (1 hunks)
  • config/locales/views/email_confirmation_mailer/nb.yml (1 hunks)
  • config/locales/views/email_confirmation_mailer/tr.yml (1 hunks)
  • config/locales/views/imports/en.yml (1 hunks)
  • config/locales/views/imports/nb.yml (1 hunks)
  • config/locales/views/imports/tr.yml (1 hunks)
  • config/locales/views/invitation_mailer/en.yml (1 hunks)
  • config/locales/views/invitation_mailer/nb.yml (1 hunks)
  • config/locales/views/invitations/nb.yml (1 hunks)
  • config/locales/views/layout/en.yml (1 hunks)
  • config/locales/views/layout/nb.yml (1 hunks)
  • config/locales/views/onboardings/en.yml (1 hunks)
  • config/locales/views/onboardings/nb.yml (1 hunks)
  • config/locales/views/password_mailer/nb.yml (1 hunks)
  • config/locales/views/registrations/nb.yml (1 hunks)
  • config/locales/views/settings/api_keys/nb.yml (1 hunks)
  • config/locales/views/settings/en.yml (1 hunks)
  • config/locales/views/settings/hostings/nb.yml (1 hunks)
  • config/locales/views/settings/nb.yml (1 hunks)
  • config/locales/views/settings/tr.yml (1 hunks)
  • config/locales/views/subscriptions/en.yml (1 hunks)
  • config/locales/views/subscriptions/nb.yml (1 hunks)
  • config/locales/views/subscriptions/tr.yml (1 hunks)
  • docs/hosting/docker.md (1 hunks)
  • test/controllers/onboardings_controller_test.rb (1 hunks)
  • test/system/onboardings_test.rb (2 hunks)
💤 Files with no reviewable changes (1)
  • app/models/demo/generator.rb
🧰 Additional context used
📓 Path-based instructions (30)
app/**/*.rb

📄 CodeRabbit inference engine (AGENTS.md)

Place Rails application Ruby code (models, controllers, services, jobs, mailers, components) under app/

Files:

  • app/mailers/invitation_mailer.rb
  • app/mailers/password_mailer.rb
  • app/mailers/email_confirmation_mailer.rb
  • app/helpers/application_helper.rb
  • app/models/provider/simplefin.rb
  • app/mailers/application_mailer.rb
**/*.rb

📄 CodeRabbit inference engine (AGENTS.md)

Ruby style: 2-space indentation; snake_case for methods/variables; CamelCase for classes/modules

Files:

  • app/mailers/invitation_mailer.rb
  • app/mailers/password_mailer.rb
  • app/mailers/email_confirmation_mailer.rb
  • test/system/onboardings_test.rb
  • test/controllers/onboardings_controller_test.rb
  • app/helpers/application_helper.rb
  • app/models/provider/simplefin.rb
  • app/mailers/application_mailer.rb
  • config/initializers/brand.rb
**/*.{rb,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{rb,js,jsx,ts,tsx}: Make changes atomic, testable, and explain their impact briefly in code suggestions.
Respect existing tests and add tests when changing critical logic.

Files:

  • app/mailers/invitation_mailer.rb
  • app/mailers/password_mailer.rb
  • app/mailers/email_confirmation_mailer.rb
  • test/system/onboardings_test.rb
  • test/controllers/onboardings_controller_test.rb
  • app/helpers/application_helper.rb
  • app/models/provider/simplefin.rb
  • app/mailers/application_mailer.rb
  • config/initializers/brand.rb
**/app/**/*.{rb,erb,js,css}

📄 CodeRabbit inference engine (CLAUDE.md)

Push Rails to its limits before adding new dependencies; a strong technical/business reason is required for new dependencies.

Files:

  • app/mailers/invitation_mailer.rb
  • app/mailers/password_mailer.rb
  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/mailers/email_confirmation_mailer.rb
  • app/views/layouts/shared/_head.html.erb
  • app/helpers/application_helper.rb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/models/provider/simplefin.rb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/mailers/application_mailer.rb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
**/*.{rb,erb,haml,slim}

📄 CodeRabbit inference engine (.cursor/rules/general-rules.mdc)

**/*.{rb,erb,haml,slim}: Use Current.user for the current user; do not use current_user
Use Current.family for the current family; do not use current_family
Ignore i18n methods; hardcode strings in English for now (do not use I18n.t, t, or similar)

Files:

  • app/mailers/invitation_mailer.rb
  • app/mailers/password_mailer.rb
  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/mailers/email_confirmation_mailer.rb
  • test/system/onboardings_test.rb
  • app/views/layouts/shared/_head.html.erb
  • test/controllers/onboardings_controller_test.rb
  • app/helpers/application_helper.rb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/models/provider/simplefin.rb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/mailers/application_mailer.rb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
  • config/initializers/brand.rb
config/**

📄 CodeRabbit inference engine (AGENTS.md)

Store application and environment configuration under config/

Files:

  • config/locales/defaults/nb.yml
  • config/locales/views/subscriptions/en.yml
  • config/locales/views/settings/en.yml
  • config/locales/views/onboardings/nb.yml
  • config/locales/views/registrations/nb.yml
  • config/locales/views/settings/nb.yml
  • config/locales/views/layout/en.yml
  • config/locales/views/settings/tr.yml
  • config/locales/views/email_confirmation_mailer/tr.yml
  • config/locales/mailers/invitation_mailer/nb.yml
  • config/locales/views/imports/en.yml
  • config/locales/views/settings/hostings/nb.yml
  • config/locales/defaults/tr.yml
  • config/locales/views/invitation_mailer/en.yml
  • config/locales/mailers/invitation_mailer/tr.yml
  • config/locales/defaults/en.yml
  • config/locales/views/settings/api_keys/nb.yml
  • config/locales/views/email_confirmation_mailer/nb.yml
  • config/locales/views/layout/nb.yml
  • config/locales/views/invitations/nb.yml
  • config/locales/views/password_mailer/nb.yml
  • config/locales/views/imports/nb.yml
  • config/locales/views/imports/tr.yml
  • config/locales/views/subscriptions/tr.yml
  • config/locales/views/onboardings/en.yml
  • config/locales/views/subscriptions/nb.yml
  • config/locales/views/invitation_mailer/nb.yml
  • config/initializers/brand.rb
  • config/locales/mailers/invitation_mailer/en.yml
config/locales/**/*.{yml,yaml,json}

📄 CodeRabbit inference engine (.cursor/rules/general-rules.mdc)

Ignore i18n files; do not add or modify locale files

Files:

  • config/locales/defaults/nb.yml
  • config/locales/views/subscriptions/en.yml
  • config/locales/views/settings/en.yml
  • config/locales/views/onboardings/nb.yml
  • config/locales/views/registrations/nb.yml
  • config/locales/views/settings/nb.yml
  • config/locales/views/layout/en.yml
  • config/locales/views/settings/tr.yml
  • config/locales/views/email_confirmation_mailer/tr.yml
  • config/locales/mailers/invitation_mailer/nb.yml
  • config/locales/views/imports/en.yml
  • config/locales/views/settings/hostings/nb.yml
  • config/locales/defaults/tr.yml
  • config/locales/views/invitation_mailer/en.yml
  • config/locales/mailers/invitation_mailer/tr.yml
  • config/locales/defaults/en.yml
  • config/locales/views/settings/api_keys/nb.yml
  • config/locales/views/email_confirmation_mailer/nb.yml
  • config/locales/views/layout/nb.yml
  • config/locales/views/invitations/nb.yml
  • config/locales/views/password_mailer/nb.yml
  • config/locales/views/imports/nb.yml
  • config/locales/views/imports/tr.yml
  • config/locales/views/subscriptions/tr.yml
  • config/locales/views/onboardings/en.yml
  • config/locales/views/subscriptions/nb.yml
  • config/locales/views/invitation_mailer/nb.yml
  • config/locales/mailers/invitation_mailer/en.yml
app/views/**/*.erb

📄 CodeRabbit inference engine (AGENTS.md)

app/views/**/*.erb: Keep heavy logic out of ERB views; prefer helpers/components instead
ERB templates are linted by erb-lint per .erb_lint.yml

Always use the icon helper (icon) for icons; never call lucide_icon directly

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
app/views/**/*.html.*

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

app/views/**/*.html.*: Use partials only for simple, context-specific, mostly static HTML content.
Prefer semantic HTML; use Turbo Frames where possible instead of client-side solutions.
Use query params for state, not localStorage or sessionStorage.
Always perform server-side formatting for currencies, numbers, and dates.

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/invitation_mailer/invite_email.html.erb
**/*.{html,erb,slim,js,jsx,ts,tsx,css,scss}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Always use functional design tokens (e.g., text-primary, bg-container) from the design system; do not use raw colors or ad-hoc classes.

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
**/app/**/*.erb

📄 CodeRabbit inference engine (CLAUDE.md)

Always use the icon helper for icons in templates; never use lucide_icon directly.

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
**/app/views/**/*.erb

📄 CodeRabbit inference engine (CLAUDE.md)

**/app/views/**/*.erb: Keep domain logic OUT of view templates; logic belongs in component files, not templates.
Use partials only for primarily static, simple HTML with minimal logic, and only when not likely to be reused.
Prefer native HTML over JavaScript components for UI elements (e.g., use <dialog>, <details><summary>).
Leverage Turbo frames for page sections over client-side JavaScript solutions.
Use query params (not localStorage/sessions) for client state management.
Perform server-side formatting for currencies, numbers, and dates in templates.

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
app/views/**/*.html.erb

📄 CodeRabbit inference engine (.cursor/rules/project-conventions.mdc)

app/views/**/*.html.erb: Prefer native HTML elements (e.g., ,

) over JS-based components
Leverage Turbo frames to break up pages instead of JS-driven client-side solutions
Prefer native client-side form validation when possible

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/invitation_mailer/invite_email.html.erb
app/{models,controllers,views}/**/*.{rb,erb}

📄 CodeRabbit inference engine (.cursor/rules/project-conventions.mdc)

Avoid N+1 queries

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/models/provider/simplefin.rb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
{app/javascript/controllers/**/*.{js,ts},app/views/**/*.erb,app/components/**/*.erb}

📄 CodeRabbit inference engine (.cursor/rules/stimulus_conventions.mdc)

Use declarative Stimulus actions in ERB (data-action) instead of imperative event listeners in controller lifecycle (e.g., avoid addEventListener in connect); controllers should just respond to actions

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
{app/components/**/*.{js,ts,erb},app/views/**/*.erb}

📄 CodeRabbit inference engine (.cursor/rules/stimulus_conventions.mdc)

Component-scoped Stimulus controllers in app/components must be used only within their component views, not in app/views

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
{app/views/**,app/helpers/**,app/javascript/controllers/**}

📄 CodeRabbit inference engine (.cursor/rules/ui-ux-design-guidelines.mdc)

{app/views/**,app/helpers/**,app/javascript/controllers/**}: Style UI using TailwindCSS v4.x with the custom design system defined in app/assets/tailwind/maybe-design-system.css
Always start by referencing app/assets/tailwind/maybe-design-system.css to understand available primitives, functional tokens, and component tokens before styling
Prefer functional tokens from the design system over raw Tailwind values (e.g., use text-primary, bg-container, border border-primary instead of text-white, bg-white, border-gray-200)

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/helpers/application_helper.rb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
{app/views/**,app/helpers/**}

📄 CodeRabbit inference engine (.cursor/rules/ui-ux-design-guidelines.mdc)

Always generate semantic HTML

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/helpers/application_helper.rb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/pwa/manifest.json.erb
  • app/views/invitation_mailer/invite_email.html.erb
{app/views,app/components}/**/*.html.erb

📄 CodeRabbit inference engine (.cursor/rules/view_conventions.mdc)

{app/views,app/components}/**/*.html.erb: Keep domain logic out of ERB templates; compute values in component/controller code and reference them in the template
Integrate Stimulus declaratively in ERB: templates declare data-controller/data-action; controllers respond to those declarations
Pass data from Rails to Stimulus via data-*-value attributes, not inline JavaScript

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/invitations/new.html.erb
  • app/views/password_mailer/password_reset.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/doorkeeper/authorizations/new.html.erb
  • app/views/onboardings/goals.html.erb
  • app/views/settings/profiles/show.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/settings/billings/show.html.erb
  • app/views/layouts/auth.html.erb
  • app/views/pages/feedback.html.erb
  • app/views/invitation_mailer/invite_email.html.erb
app/views/**/_*.html.erb

📄 CodeRabbit inference engine (.cursor/rules/view_conventions.mdc)

Name partials with a leading underscore (e.g., _trend_change.html.erb, _form_errors.html.erb)

Files:

  • app/views/accounts/_account_sidebar_tabs.html.erb
  • app/views/import/confirms/_mappings.html.erb
  • app/views/layouts/shared/_head.html.erb
  • app/views/settings/hostings/_invite_code_settings.html.erb
  • app/views/layouts/shared/_footer.html.erb
test/**/*_test.rb

📄 CodeRabbit inference engine (AGENTS.md)

Name Minitest files with *_test.rb and mirror the app/ structure under test/

test/**/*_test.rb: ALWAYS use Minitest + fixtures + Mocha for tests; NEVER RSpec or FactoryBot.
Use Mocha for mocking in tests when necessary.
Use VCR for external API tests.

test/**/*_test.rb: Always use Minitest for tests; do not use RSpec
Do not use factories (e.g., FactoryBot) in tests; rely on fixtures instead
For tests needing many records, use Rails helpers to construct data and inline the creation in the test
Only write tests for critical and important code paths
Avoid tests that merely verify framework/ActiveRecord behavior
Test boundaries correctly: for queries, assert returned values; for commands, assert collaborators are called with correct params
Never test the implementation details of one class in another class’s test suite
Use the mocha gem for stubs and mocks
Prefer OpenStruct for mock instances; use a mock class for complex cases
Only mock what’s necessary; don’t mock return values unless they are under test

Files:

  • test/system/onboardings_test.rb
  • test/controllers/onboardings_controller_test.rb
**/test/**/*.rb

📄 CodeRabbit inference engine (CLAUDE.md)

**/test/**/*.rb: ALWAYS use Minitest and fixtures for Ruby tests; NEVER RSpec or factories.
Only test critical and important code paths; system tests should be used sparingly for critical user flows.

Files:

  • test/system/onboardings_test.rb
  • test/controllers/onboardings_controller_test.rb
test/system/**/*_test.rb

📄 CodeRabbit inference engine (.cursor/rules/testing.mdc)

Use system tests sparingly to keep the suite fast

Files:

  • test/system/onboardings_test.rb
app/views/layouts/**/*.erb

📄 CodeRabbit inference engine (.cursor/rules/project-conventions.mdc)

Be mindful of performance in global layouts (e.g., avoid loading large data payloads)

Files:

  • app/views/layouts/shared/_head.html.erb
  • app/views/layouts/shared/_footer.html.erb
  • app/views/layouts/auth.html.erb
**/application_helper.rb

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

Always use the icon helper in application_helper.rb for icons; never use lucide_icon directly.

Files:

  • app/helpers/application_helper.rb
**/app/helpers/application_helper.rb

📄 CodeRabbit inference engine (CLAUDE.md)

Always use the icon helper in application_helper.rb; never use lucide_icon directly.

Files:

  • app/helpers/application_helper.rb
app/{helpers,models}/**/*.rb

📄 CodeRabbit inference engine (.cursor/rules/project-conventions.mdc)

Format currencies, numbers, and dates on the server side (Ruby) before sending to the client

Files:

  • app/helpers/application_helper.rb
  • app/models/provider/simplefin.rb
app/models/**/*.rb

📄 CodeRabbit inference engine (.cursor/rules/project-design.mdc)

Domain models should not call Provider::Registry directly; use a Provided concern within the model’s namespace to select providers and expose convenience methods

Use ActiveRecord validations for forms and complex domain constraints.

app/models/**/*.rb: Place business logic in POROs and model classes under app/models
Models should answer questions about themselves (e.g., prefer account.balance_series over service objects)
Implement complex validations and business logic with ActiveRecord validations
Model-level validations may mirror DB constraints but are not strictly required

Files:

  • app/models/provider/simplefin.rb
app/models/provider/**/*.rb

📄 CodeRabbit inference engine (.cursor/rules/project-design.mdc)

Concrete provider classes must be under the Provider:: namespace, inherit from Provider, wrap calls with with_provider_response, and raise on invalid/unavailable data

Files:

  • app/models/provider/simplefin.rb
**/app/models/**/*.rb

📄 CodeRabbit inference engine (CLAUDE.md)

Business logic should primarily reside in models; use concerns and POROs for organization.

Files:

  • app/models/provider/simplefin.rb
🧬 Code graph analysis (7)
app/mailers/invitation_mailer.rb (2)
app/mailers/application_mailer.rb (1)
  • product_name (9-11)
app/helpers/application_helper.rb (1)
  • product_name (4-6)
app/mailers/password_mailer.rb (2)
app/mailers/application_mailer.rb (1)
  • product_name (9-11)
app/helpers/application_helper.rb (1)
  • product_name (4-6)
app/mailers/email_confirmation_mailer.rb (2)
app/mailers/application_mailer.rb (1)
  • product_name (9-11)
app/helpers/application_helper.rb (1)
  • product_name (4-6)
app/helpers/application_helper.rb (1)
app/mailers/application_mailer.rb (2)
  • product_name (9-11)
  • brand_name (13-15)
app/models/provider/simplefin.rb (2)
app/mailers/application_mailer.rb (1)
  • product_name (9-11)
app/helpers/application_helper.rb (1)
  • product_name (4-6)
app/mailers/application_mailer.rb (1)
app/helpers/application_helper.rb (2)
  • brand_name (8-10)
  • product_name (4-6)
config/initializers/brand.rb (3)
config/application.rb (1)
  • config (10-44)
app/mailers/application_mailer.rb (2)
  • product_name (9-11)
  • brand_name (13-15)
app/helpers/application_helper.rb (2)
  • product_name (4-6)
  • brand_name (8-10)
🪛 dotenv-linter (3.3.0)
.env.example

[warning] 58-58: [UnorderedKey] The BRAND_NAME key should go before the PRODUCT_NAME key

(UnorderedKey)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci / test
🔇 Additional comments (24)
test/controllers/onboardings_controller_test.rb (1)

85-85: LGTM! Test assertion correctly made brand-agnostic.

The test now validates the heading without hardcoding the product name, which properly supports the white-labeling strategy.

app/views/invitations/new.html.erb (1)

2-2: LGTM!

The dynamic product name interpolation is correctly implemented. The product_name helper is properly exposed via ApplicationHelper and passed to the translation as expected.

config/locales/views/settings/hostings/nb.yml (1)

6-6: LGTM!

The Norwegian translation correctly interpolates the dynamic product name using %{product_name}. This aligns with the project-wide branding strategy.

app/models/provider/simplefin.rb (1)

4-4: No changes needed: product_name is set in brand.rb (defaulting to "Sure") before any app code is loaded, so the User-Agent interpolation can never be nil.

config/locales/defaults/en.yml (1)

3-5: Replace circular placeholders or remove unused locale defaults
A search across .rb and .erb files didn’t find any references to defaults.product_name or defaults.brand_name, and their self-referential placeholders ("%{product_name}", "%{brand_name}") would render literally. Either remove these unused keys from config/locales/defaults/en.yml (lines 3–5) or replace them with real default values, and verify no other code relies on them.

app/views/doorkeeper/authorizations/new.html.erb (1)

74-74: Better approach: hardcoded English with helper interpolation.

Unlike the other files in this PR, this line hardcodes the English text and directly interpolates the product_name helper, which aligns better with the coding guideline to "hardcode strings in English" rather than using i18n translation methods. This approach is preferable to the t() method usage seen elsewhere in the PR.

As per coding guidelines.

app/views/pwa/manifest.json.erb (2)

2-3: LGTM!

Correct use of j (json_escape) helper for dynamic product_name in JSON manifest fields.


21-21: LGTM!

Proper JSON escaping of interpolated product_name in description field.

app/views/accounts/_account_sidebar_tabs.html.erb (1)

15-15: LGTM!

Clean integration of product_name helper into existing content. Proper use of helper rather than embedding logic in the view.

app/views/import/confirms/_mappings.html.erb (1)

46-46: Translation key embeds product name, defeating configurability.

The key changed from .maybe_mapping_label to .sure_mapping_label, hardcoding "sure" in the translation key itself. For true white-labeling, use a product-agnostic key like .product_mapping_label or .mapping_label, then interpolate product_name in the translation value.

Apply this diff:

-            <p><%= t(".sure_mapping_label", mapping: mapping_label(mapping_class), product_name: product_name) %></p>
+            <p><%= t(".product_mapping_label", mapping: mapping_label(mapping_class), product_name: product_name) %></p>

Likely an incorrect or invalid review comment.

app/views/pages/feedback.html.erb (1)

19-19: LGTM! Dynamic product name interpolation works well.

The use of product_name helper for dynamic branding is clean and consistent with the PR's white-labeling objectives.

app/views/password_mailer/password_reset.html.erb (1)

1-1: I18n usage conflicts with coding guidelines.

This view uses t(".request_made", product: product_name) for translation lookups. However, the coding guidelines explicitly state: "Ignore i18n methods; hardcode strings in English for now (do not use I18n.t, t, or similar)."

While the PR's white-labeling approach via i18n is technically sound, it contradicts the project's current stance on hardcoding English strings. Consider whether to continue with the i18n-based approach or align with guidelines by using direct string interpolation like "A password reset request was made for your #{product_name} account.".

As per coding guidelines

app/views/layouts/shared/_footer.html.erb (1)

3-3: Clean dynamic branding implementation.

The interpolation of brand_name and product_name helpers works well and avoids i18n methods, aligning with coding guidelines. The helper lookups have negligible performance impact in this global layout.

app/views/invitation_mailer/invite_email.html.erb (2)

1-1: LGTM: Clean integration of product branding.

The addition of product: product_name to the greeting translation is consistent with the white-labeling strategy and properly uses the helper method.


4-9: LGTM: Proper use of html_safe with developer-controlled translations.

The reformatted translation call correctly adds product_name and uses html_safe appropriately, since translation strings are developer-controlled and i18n handles interpolation safely.

app/views/layouts/shared/_head.html.erb (2)

2-2: LGTM: Dynamic title fallback.

Replacing the hardcoded "Sure" with product_name properly implements white-labeling for the page title while maintaining the existing fallback pattern.


21-21: LGTM: Consistent PWA branding.

The apple-mobile-web-app-title now uses product_name, ensuring consistent branding across web and PWA contexts.

test/system/onboardings_test.rb (2)

140-140: LGTM: Consistent test expectation.

This assertion matches the change at line 41, ensuring consistent expectations across different test scenarios.


41-41: Approve: Onboarding view updated to match generic test assertion
The goals onboarding view (app/views/onboardings/goals.html.erb:18) now displays “What brings you here?”, aligning with the updated system test.

app/mailers/invitation_mailer.rb (1)

8-12: LGTM: Consistent mailer branding.

The subject translation now includes product: product_name, matching the changes in the email view template and ensuring consistent dynamic branding across the invitation email.

config/initializers/brand.rb (1)

1-4: Approve: brand_name usage verified

brand_name is consumed in app/helpers/application_helper.rb, in the footer view (app/views/layouts/shared/_footer.html.erb), and in app/mailers/application_mailer.rb. No further changes required.

app/views/settings/billings/show.html.erb (2)

31-31: LGTM!

The dynamic product name substitution aligns with the white-labeling strategy and maintains consistency with the branding changes across the codebase.


24-24: No action needed: product_name has a default fallback
The brand initializer uses ENV.fetch("PRODUCT_NAME", "Sure") to set config.x.product_name, guaranteeing a valid string.

app/mailers/application_mailer.rb (1)

2-5: No changes needed for dynamic default from initialization order.

The brand.rb initializer runs before Rails loads mailer classes (both in autoload and eager_load modes), so the interpolated config.x.brand_name and config.x.product_name will be set when default from: is evaluated.

Comment on lines +18 to 19
<h1 class="text-2xl font-medium md:text-2xl">What brings you here?</h1>
<p class="text-secondary text-sm">Select one or more goals that you have with using Sure as your personal finance tool.</p>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Inconsistent branding removal.

Line 18 removes the product name from the heading, but line 19 still contains a hardcoded reference to "Sure". For a consistent white-labeling approach, line 19 should also use the dynamic product_name helper or be made generic.

Apply this diff to make the branding consistent:

-      <p class="text-secondary text-sm">Select one or more goals that you have with using Sure as your personal finance tool.</p>
+      <p class="text-secondary text-sm">Select one or more goals that you have with using <%= product_name %> as your personal finance tool.</p>
📝 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
<h1 class="text-2xl font-medium md:text-2xl">What brings you here?</h1>
<p class="text-secondary text-sm">Select one or more goals that you have with using Sure as your personal finance tool.</p>
<h1 class="text-2xl font-medium md:text-2xl">What brings you here?</h1>
<p class="text-secondary text-sm">Select one or more goals that you have with using <%= product_name %> as your personal finance tool.</p>
🤖 Prompt for AI Agents
In app/views/onboardings/goals.html.erb around lines 18 to 19, the heading was
changed to remove the product name but the paragraph still hardcodes "Sure";
update that paragraph to use the dynamic product_name helper or reword it to a
generic term (e.g., "your personal finance tool") so branding is consistent, and
ensure you use the ERB helper correctly (product_name) and preserve existing
HTML/CSS classes.

<div class="space-y-1">
<p class="text-sm"><%= t(".title") %></p>
<p class="text-secondary text-sm"><%= t(".description") %></p>
<p class="text-secondary text-sm"><%= t(".description", product: product_name) %></p>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify locale key parameter name matches.

The translation is passed product: product_name, but other locale files in this PR use %{product_name} as the placeholder. Ensure the corresponding locale file for this view uses %{product} (not %{product_name}) to match this parameter.

Run the following script to check the locale key:


🏁 Script executed:

#!/bin/bash
# Description: Find the locale key for invite_code_settings description to verify parameter name

# Search for the translation key in locale files
rg -n "invite_code_settings" --type yaml -A 5 -B 2

Length of output: 2353


Use the correct interpolation key
At app/views/settings/hostings/_invite_code_settings.html.erb:5, update the translation call to:

<p class="text-secondary text-sm">
  <%= t('.description', product_name: product_name) %>
</p>

so it aligns with the %{product_name} placeholder in nb.yml (and add a matching placeholder in en.yml/tr.yml if you want them to use interpolation).

🤖 Prompt for AI Agents
In app/views/settings/hostings/_invite_code_settings.html.erb around line 5, the
translation call uses the wrong interpolation key (`product:`) which doesn't
match the `%{product_name}` placeholder in nb.yml; update the t(...) call to
pass product_name: product_name so the interpolation key matches, and optionally
add the same `%{product_name}` placeholder to en.yml and tr.yml if those locales
should include the interpolated value.

Comment on lines +1 to 25
---
nb:
helpers:
label:
user:
invite_code: Invitasjonskode
submit:
user:
create: Fortsett
registrations:
create:
failure: Det oppsto et problem med registreringen.
invalid_invite_code: Ugyldig invitasjonskode, vennligst prøv igjen.
success: Du har blitt registrert.
new:
invitation_message: "%{inviter} har invitert deg til å bli med som %{role}"
join_family_title: Bli med i %{family}
role_admin: administrator
role_member: medlem
submit: Opprett konto
title: Opprett kontoen din
welcome_body: For å komme i gang må du registrere deg for en ny konto. Du vil
da kunne konfigurere flere innstillinger i appen.
welcome_title: Velkommen til Self Hosted %{product_name}!
password_placeholder: Angi passordet ditt
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Locale file modification violates coding guidelines.

The coding guidelines explicitly state: "Ignore i18n files; do not add or modify locale files" and "Ignore i18n methods; hardcode strings in English for now". This file modification contradicts that guidance.

Based on coding guidelines, consider whether the i18n approach aligns with the project's current localization strategy, or if branding should be implemented differently.

🤖 Prompt for AI Agents
In config/locales/views/registrations/nb.yml around lines 1 to 25, this locale
file change violates the project guideline to ignore i18n files; revert or
remove these modifications from the PR so no new/edited locale files are
committed, and instead ensure any UI text changes are made by hardcoding English
strings in the relevant view/controller code as per guidance; update the
branch/commit to drop this file change and include only English text edits where
needed.

docker volume rm sure_postgres-data # this is the name of the volume the DB is mounted to
docker compose up
docker exec -it sure-db-1 psql -U sure_user -d sure_production -c "SELECT 1;" # This will verify that the issue is fixed
docker exec -it sure-postgres-1 psql -U sure_user -d sure_production -c "SELECT 1;" # This will verify that the issue is fixed
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the container name matches the Docker Compose configuration.

The container name changed from sure-db-1 to sure-postgres-1. Ensure this matches the actual service name defined in the Docker Compose files.


🏁 Script executed:

#!/bin/bash
# Description: Verify the Postgres service name in Docker Compose files

# Search for the postgres service definition in compose files
rg -n "postgres:" --type=yaml -g "*compose*.yml" -A 5

# Also check for any references to the old container name
rg -n "sure-db-1" --type=md

Length of output: 283


🏁 Script executed:

#!/bin/bash
# List Docker Compose files in the repo
find . -type f \( -iname "*compose*.yml" -o -iname "*compose*.yaml" \)

# Extract service names (2-space indent) from Compose files
rg -nP '^\s{2}[a-zA-Z0-9_-]+:' -g "*compose*.yml"

# Check for any container_name overrides
rg -n 'container_name:' -g "*compose*.yml"

# Search for 'sure-postgres' references
rg -n 'sure-postgres' -g "*compose*.yml"

Length of output: 1091


🏁 Script executed:

#!/bin/bash
# Inspect .devcontainer/docker-compose.yml for services and container_name
rg -nP '^services:' -g ".devcontainer/docker-compose.yml" -A5
rg -nP '^ {2}[a-zA-Z0-9_-]+:' -g ".devcontainer/docker-compose.yml"
rg -n 'container_name:' -g ".devcontainer/docker-compose.yml"
rg -n 'sure-postgres' -g ".devcontainer/docker-compose.yml"

Length of output: 595


🏁 Script executed:

#!/bin/bash
# Show the first 200 lines of the devcontainer Docker Compose config
head -n 200 .devcontainer/docker-compose.yml

Length of output: 1269


🏁 Script executed:

#!/bin/bash
# Show the first 200 lines of compose.example.yml for service definitions
head -n 200 compose.example.yml

Length of output: 2963


Update the Docker exec command to match the actual db container
Replace the hard-coded sure-postgres-1 with the real container name—by default sure_db_1—or, better yet, use

docker-compose exec db psql -U sure_user -d sure_production -c "SELECT 1;"

to avoid manual name mismatches.

🤖 Prompt for AI Agents
In docs/hosting/docker.md around line 192 the docker exec command uses a
hard-coded container name "sure-postgres-1" which can be incorrect; update the
instruction to use the actual db service name instead (for example replace the
hard-coded container with the default "sure_db_1") or, preferably, replace the
command with a docker-compose-based invocation (e.g., use docker-compose exec db
...) so the example targets the service name and avoids manual container name
mismatches.

@jjmata jjmata self-assigned this Oct 1, 2025
@jjmata jjmata added the enhancement New feature or request label Oct 1, 2025
@jjmata jjmata added this to the v0.7.0 milestone Oct 1, 2025
@jjmata jjmata mentioned this pull request Oct 1, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
app/mailers/application_mailer.rb (1)

8-16: Consider removing redundant instance variable assignments.

The before_action :assign_branding creates instance variables @product_name and @brand_name, but since helper_method (line 10) already exposes the product_name and brand_name methods to views, the instance variables are redundant. Views can directly call product_name and brand_name without needing @product_name or @brand_name.

Removing the before_action and assign_branding method would simplify the code and provide a single, consistent way to access these values in mailer views.

Apply this diff to remove the redundant code:

-
- before_action :assign_branding
-
  helper_method :product_name, :brand_name

  private
-   def assign_branding
-     @product_name = product_name
-     @brand_name = brand_name
-   end
-
    def product_name
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 60eb52b and 8160327.

📒 Files selected for processing (1)
  • app/mailers/application_mailer.rb (1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
app/**/*.rb

📄 CodeRabbit inference engine (AGENTS.md)

Place Rails application Ruby code (models, controllers, services, jobs, mailers, components) under app/

Files:

  • app/mailers/application_mailer.rb
**/*.rb

📄 CodeRabbit inference engine (AGENTS.md)

Ruby style: 2-space indentation; snake_case for methods/variables; CamelCase for classes/modules

Files:

  • app/mailers/application_mailer.rb
**/*.{rb,js,jsx,ts,tsx}

📄 CodeRabbit inference engine (.github/copilot-instructions.md)

**/*.{rb,js,jsx,ts,tsx}: Make changes atomic, testable, and explain their impact briefly in code suggestions.
Respect existing tests and add tests when changing critical logic.

Files:

  • app/mailers/application_mailer.rb
**/app/**/*.{rb,erb,js,css}

📄 CodeRabbit inference engine (CLAUDE.md)

Push Rails to its limits before adding new dependencies; a strong technical/business reason is required for new dependencies.

Files:

  • app/mailers/application_mailer.rb
**/*.{rb,erb,haml,slim}

📄 CodeRabbit inference engine (.cursor/rules/general-rules.mdc)

**/*.{rb,erb,haml,slim}: Use Current.user for the current user; do not use current_user
Use Current.family for the current family; do not use current_family
Ignore i18n methods; hardcode strings in English for now (do not use I18n.t, t, or similar)

Files:

  • app/mailers/application_mailer.rb
🧠 Learnings (1)
📓 Common learnings
Learnt from: jjmata
PR: we-promise/sure#173
File: app/mailers/email_confirmation_mailer.rb:9-9
Timestamp: 2025-10-01T11:40:36.711Z
Learning: In the we-promise/sure repository, i18n (internationalization) is used throughout the application for translations. When making branding configurable (e.g., product names), it's appropriate to add parameters like `product: product_name` to existing `t()` translation calls rather than replacing them with hardcoded strings.
🧬 Code graph analysis (1)
app/mailers/application_mailer.rb (1)
app/helpers/application_helper.rb (2)
  • brand_name (8-10)
  • product_name (4-6)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: ci / test
🔇 Additional comments (2)
app/mailers/application_mailer.rb (2)

2-5: LGTM! Dynamic branding in the from address.

The use of Rails.configuration.x.brand_name and Rails.configuration.x.product_name for the sender name is correctly implemented. The ENV.fetch with a sensible default ensures the mailer has a valid from address even if the environment variable is not set.


18-24: LGTM! Helper methods provide clean access to branding config.

The private product_name and brand_name methods provide a clean interface to the Rails configuration values, and the helper_method declaration makes them accessible in mailer views.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

1 participant