Skip to content

Commit a5bd38e

Browse files
authored
Merge branch 'main' into feature/platform-multi-tenancy
Signed-off-by: Robert Smith <[email protected]>
2 parents 277927b + e808463 commit a5bd38e

File tree

624 files changed

+18688
-4900
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

624 files changed

+18688
-4900
lines changed

.github/copilot-instructions.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Better Together Community Engine – Rails App & Engine Guidelines
2+
3+
This repository contains the **Better Together Community Engine** (an isolated Rails engine under the `BetterTogether` namespace) and/or a host Rails app that mounts it. Use these instructions for all code generation.
4+
5+
## Core Principles
6+
7+
- **Accessibility first** (WCAG AA/AAA): semantic HTML, ARIA roles, keyboard nav, proper contrast.
8+
- **Hotwire everywhere**: Turbo for navigation/updates; Stimulus controllers for interactivity.
9+
- **Keep controllers thin**; move business logic to POROs/service objects or concerns.
10+
- **Prefer explicit join models** over polymorphic associations when validation matters.
11+
- **Avoid the term “STI”** in code/comments; use “single-table inheritance” or alternate designs.
12+
- **Use `ENV.fetch`** rather than `ENV[]`.
13+
- **Always add policy/authorization checks** on links/buttons to controller actions.
14+
- **i18n & Mobility**: every user-facing string must be translatable; include missing keys.
15+
16+
## Technology Stack
17+
18+
- **Rails 7.1+** (engine & current hosts) – compatible with Rails 8 targets
19+
- **Ruby 3.3+**
20+
- **PostgreSQL (+ PostGIS, pgcrypto)**
21+
- **Redis** for caching & Sidekiq queues
22+
- **Sidekiq** for background jobs (queue namespaced, e.g. `:metrics`)
23+
- **Hotwire (Turbo, Stimulus)**
24+
- **Bootstrap 5.3 & Font Awesome 6** (not Tailwind)
25+
- **Trix / Action Text** for rich text
26+
- **Active Record Encryption** for sensitive fields; encrypted Active Storage files
27+
- **Mobility** for attribute translations
28+
- **Elasticsearch 7** via `elasticsearch-rails`
29+
- **Importmap-Rails** for JS deps (no bundler by default)
30+
- **Dokku** (Docker-based PaaS) for deployment; Cloudflare for DNS/DDoS/tunnels
31+
- **AWS S3 / MinIO** for file storage (transitioning to self-hosted MinIO)
32+
- **Action Mailer + locale-aware emails**
33+
- **Noticed** for notifications
34+
35+
> Dev DB: PostgreSQL (not SQLite). Production: PostgreSQL. PostGIS enabled for geospatial needs.
36+
37+
38+
## Coding Guidelines
39+
40+
- **Ruby/Rails**
41+
- 2-space indent, snake_case methods, Rails conventions
42+
- Service objects in `app/services/`
43+
- Concerns for reusable model/controller logic
44+
- Strong params, Pundit/Policy checks (or equivalent) everywhere
45+
- Avoid fat callbacks; keep models lean
46+
- **Views**
47+
- ERB with semantic HTML
48+
- Bootstrap utility classes; respect prefers-reduced-motion & other a11y prefs
49+
- Avoid inline JS; use Stimulus
50+
- External links in `.trix-content` get FA external-link icon unless internal/mailto/tel/pdf
51+
- **Hotwire**
52+
- Use Turbo Streams for CRUD updates
53+
- Stimulus controllers in `app/javascript/controllers/`
54+
- No direct DOM manipulation without Stimulus targets/actions
55+
- **Background Jobs**
56+
- Sidekiq jobs under appropriate queues (`:default`, `:mailers`, `:metrics`, etc.)
57+
- Idempotent job design; handle retries
58+
- **Search**
59+
- Update `as_indexed_json` to include translated/plain-text fields as needed
60+
- **Encryption & Privacy**
61+
- Use AR encryption for sensitive columns
62+
- Ensure blobs are encrypted at rest
63+
- **Testing**
64+
- RSpec (if present) or Minitest – follow existing test framework
65+
- All RSpec specs **must use FactoryBot factories** for model instances (do not use `Model.create` or `Model.new` directly in specs).
66+
- **A FactoryBot factory must exist for every model**. When generating a new model, also generate a factory for it.
67+
- **Factories must use the Faker gem** to provide realistic, varied test data for all attributes (e.g., names, emails, addresses, etc.).
68+
- System tests for Turbo flows where possible
69+
70+
## Project Architecture Notes
71+
72+
- Engine code is namespaced under `BetterTogether`.
73+
- Host app extends/overrides engine components where needed.
74+
- Content blocks & page builder use configurable relationships (content areas, background images, etc.).
75+
- Journey/Lists features use polymorphic items but with care (or explicit join models).
76+
- Agreements system models participants, roles, terms, and timelines.
77+
78+
## Specialized Instruction Files
79+
80+
- `.github/instructions/rails_engine.instructions.md` – Engine isolation & namespacing
81+
- `.github/instructions/hotwire.instructions.md` – Turbo/Stimulus patterns
82+
- `.github/instructions/hotwire-native.instructions.md` – Hotwire Native patterns
83+
- `.github/instructions/sidekiq-redis.instructions.md` – Background jobs & Redis
84+
- `.github/instructions/search-elasticsearch.instructions.md` – Elasticsearch indexing patterns
85+
- `.github/instructions/i18n-mobility.instructions.md` – Translations (Mobility + I18n)
86+
- `.github/instructions/accessibility.instructions.md` – A11y checklist & patterns
87+
- `.github/instructions/notifications-noticed.instructions.md` – Notification patterns
88+
- `.github/instructions/deployment.instructions.md` – Dokku, Cloudflare, backups (S3/MinIO)
89+
- `.github/instructions/security-encryption.instructions.md` – AR encryption, secrets
90+
- `.github/instructions/bootstrap.instructions.md` – Styling, theming, icon usage
91+
- `.github/instructions/importmaps.instructions.md` – JS dependency management
92+
- `.github/instructions/view-helpers.instructions.md` – Consistency in Rails views
93+
94+
---
95+
96+
_If you generate code that touches any of these areas, consult the relevant instruction file and follow it._
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
applyTo: "**/*.erb,**/*.rb,**/*.js,**/*.scss"
3+
---
4+
# Accessibility (WCAG AA/AAA) Checklist
5+
6+
- Semantic HTML, correct landmarks (`<main>`, `<nav>`, `<aside>`).
7+
- Labels for every form input; visible or `aria-label`.
8+
- Keyboard navigable: no keyboard traps; visible focus states.
9+
- Announce dynamic content (ARIA live regions / role="status").
10+
- Color contrast ≥ 4.5:1 (text) / 3:1 (large text & UI).
11+
- Provide skip links and logical heading order.
12+
- Respect motion & color preference media queries.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
---
2+
applyTo: "**/*.erb,**/*.scss,**/*.css,**/*.html.erb"
3+
---
4+
# Bootstrap 5.3 & Font Awesome 6 Guidelines
5+
6+
## Styling
7+
- Use semantic HTML first; classes only enhance.
8+
- Respect prefers-reduced-motion, color contrast (AAA where possible).
9+
- Prefer Bootstrap utility classes (spacing, flex, grid) before custom CSS.
10+
11+
## Components
12+
- Build reusable partials/partials + Stimulus for interactive widgets.
13+
- Do not inline styles; keep SCSS organized by feature or component.
14+
15+
## Icons
16+
- Use `<i class="fa-solid fa-...">` or `<span class="fa-...">` with proper `aria-hidden="true"` and visually hidden text if icon conveys meaning.
17+
18+
## External Link Pattern
19+
- For `.trix-content` links not matching internal/mailto/tel/pdf, append FA external-link icon via CSS or helper.
20+
21+
## Theming
22+
- Override Bootstrap variables in host app theme SCSS; avoid duplicating entire Bootstrap build.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
applyTo: "**/*.rb,**/*.yml,**/Procfile,**/*.sh"
3+
---
4+
# Deployment: Dokku, Cloudflare, Backups
5+
6+
## Dokku
7+
- One app per service; use buildpacks or Dockerfile as needed.
8+
- Set env vars via `dokku config:set`.
9+
- Use `ps:scale` for web/worker separation.
10+
11+
## Cloudflare
12+
- DNS, DDoS, tunnels: document records & tunnel IDs.
13+
- Cache rules must respect auth-protected pages.
14+
15+
## Backups
16+
- Daily encrypted DB dumps to S3/MinIO.
17+
- Verify restore path regularly.
18+
19+
## Secrets
20+
- Store Rails master key, DB creds, etc. in Dokku/Cloudflare secrets, not repo.
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
---
2+
applyTo: "**/*.rb,**/*.js,**/*.html.erb"
3+
---
4+
# Hotwire Native Guidelines
5+
6+
## Core Concepts
7+
- Hotwire Native displays web content in a native shell with platform-specific navigation
8+
- Web content renders in a WebView with native-feeling transitions and behaviors
9+
- Link navigation is intercepted and handled by the native adapter
10+
- Build once for the web, deploy simultaneously to web and native mobile apps
11+
- Progressively enhance with native components where higher fidelity is needed
12+
13+
## Navigation Best Practices
14+
- Design web content to work across web, iOS, and Android
15+
- Links between pages become native screen transitions automatically
16+
- External links open in an in-app browser (SFSafariViewController on iOS, Custom Tabs on Android)
17+
- Use `data-turbo-action="replace"` to replace the current screen instead of pushing a new one
18+
- Ensure all screens are accessible via URLs for proper native navigation
19+
20+
## Path Configuration
21+
- Define platform-specific navigation rules in a JSON configuration file
22+
- Host configuration files at versioned URLs (e.g., `/configurations/ios_v1.json`)
23+
- Include both local (bundled) and remote (server-hosted) configurations
24+
- Use regex patterns to match URLs and apply specific behaviors
25+
- Configuration example:
26+
```json
27+
{
28+
"settings": {
29+
"feature_flags": [
30+
{
31+
"name": "enable_new_feature",
32+
"enabled": true
33+
}
34+
]
35+
},
36+
"rules": [
37+
{
38+
"patterns": [
39+
"/modal/.*"
40+
],
41+
"properties": {
42+
"context": "modal"
43+
}
44+
},
45+
{
46+
"patterns": [
47+
"/tabs/.*"
48+
],
49+
"properties": {
50+
"presentation": "refresh"
51+
}
52+
}
53+
]
54+
}
55+
```
56+
57+
## Bridge Components
58+
- Use Bridge Components for web-to-native communication
59+
- Components have both web (Stimulus) and native (Swift/Kotlin) counterparts
60+
- Register component handlers in your native app and attach web controllers in HTML
61+
- Use for native UI elements like top bar buttons, action sheets, and platform APIs
62+
- Web component implementation example:
63+
64+
```javascript
65+
// app/javascript/controllers/native_button_controller.js
66+
import { Controller } from "@hotwired/stimulus"
67+
import { BridgeComponent } from "@hotwired/bridge"
68+
69+
export default class extends Controller {
70+
static values = { title: String, style: String }
71+
72+
connect() {
73+
this.bridge = new BridgeComponent("button", this)
74+
this.bridge.send("connect", {
75+
title: this.titleValue,
76+
style: this.styleValue || "default"
77+
})
78+
}
79+
80+
disconnect() {
81+
this.bridge.send("disconnect")
82+
}
83+
84+
handleTap(message) {
85+
// Handle tap event from native
86+
const form = this.element.closest("form")
87+
if (form) form.requestSubmit()
88+
}
89+
}
90+
```
91+
92+
```html
93+
<!-- In your view -->
94+
<div data-controller="native-button"
95+
data-native-button-title-value="Save"
96+
data-native-button-style-value="primary">
97+
</div>
98+
```
99+
100+
## Native Screen Integration
101+
- Create fully native screens for high-fidelity interactions
102+
- Register URL routes that map to native screen controllers
103+
- Ensure each native screen has a corresponding URL for consistent navigation
104+
- Share data between web and native using URL parameters or Bridge Components
105+
- Follow platform design guidelines for native screens (Human Interface Guidelines for iOS, Material Design for Android)
106+
107+
## Progressive Enhancement Strategy
108+
- Start with web-only implementation to quickly ship features
109+
- Add Bridge Components for native UI elements and platform integrations
110+
- Build fully native screens only where high fidelity is required
111+
- Maintain a consistent navigation model across all screen types
112+
- Use feature flags in path configuration to enable native features gradually
113+
114+
## Mobile-Optimized HTML/CSS
115+
- Test all web pages in mobile viewports
116+
- Use responsive design principles for fluid layouts
117+
- Ensure tap targets are appropriately sized (minimum 44×44pt on iOS, 48×48dp on Android)
118+
- Optimize images and assets for mobile devices
119+
- Consider mobile-specific meta tags:
120+
```html
121+
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
122+
<meta name="apple-mobile-web-app-capable" content="yes">
123+
<meta name="turbo-visit-control" content="reload">
124+
```
125+
126+
## Performance Considerations
127+
- Keep initial page load fast (under 2 seconds)
128+
- Minimize JavaScript usage to conserve battery and performance
129+
- Optimize image sizes for mobile network conditions
130+
- Use Turbo Frames to load content incrementally
131+
- Consider offline capabilities with service workers where appropriate
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
---
2+
applyTo: "**/*.js,**/*.erb,**/*.html.erb"
3+
---
4+
# Hotwire (Turbo + Stimulus) Guidelines
5+
6+
## Core Ideas
7+
- Turbo for navigation/partial updates; Stimulus for behavior.
8+
- Progressive enhancement first; degrade gracefully.
9+
10+
## Turbo Drive/Frames/Streams
11+
- Use Frames to isolate sections, Streams for live updates (append, replace, morph, etc.).
12+
- Use `data-turbo-permanent` for elements that must persist across visits.
13+
- Prefer morphing refresh (`<meta name="turbo-refresh-method" content="morph">`).
14+
15+
## Stimulus
16+
- One responsibility per controller; name semantically.
17+
- Use `values`, `targets`, `classes` APIs; avoid manual DOM queries.
18+
- Attach behavior via `data-action` and `data-controller`, not inline JS.
19+
20+
## Integration Tips
21+
- Listen for Turbo lifecycle events in controllers (`turbo:load`, `turbo:before-frame-render`).
22+
- Cleanup in `disconnect` to avoid duplicates on Turbo nav.
23+
24+
## Accessibility
25+
- Keep dynamic focus management in mind.
26+
- Announce content updates to assistive tech (ARIA live regions where needed).
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
applyTo: "**/*.rb,**/*.yml,**/*.erb"
3+
---
4+
# I18n & Mobility Guidelines
5+
6+
## Keys & Locales
7+
- Use `better_together.*` namespace for engine translations.
8+
- Add missing keys in English first, then translate (fr, es, etc).
9+
10+
## Mobility
11+
- Translate model attributes; list them via helper methods.
12+
- Store rich text translations (Action Text) where needed.
13+
- Never rely on locale fallbacks for required content—seed defaults.
14+
15+
## Emails & Notifications
16+
- Determine locale from recipient record or preference.
17+
- Wrap copy in I18n.t calls; avoid string interpolation with HTML—use `%{}` placeholders.

0 commit comments

Comments
 (0)