Extract landing-page agents section into a swappable partial (COPLAN-3)#114
Merged
HamptonMakes merged 1 commit intoMay 19, 2026
Conversation
The "Built for any AI agent" section on the landing page is the one piece hosts most often want to customize: generic CoPlan tells users to read /agent-instructions, but a deployment like coplan-square wants to tell its users to run `sq agents skills add coplan` instead. Rather than make hosts fork the entire landing page just to change that paragraph (which is what `landing_page_partial` would force them to do), expose a single config knob for just this section. - Extract the agents section into _default_agents.html.erb - Add CoPlan.configuration.landing_agents_partial, defaulting to it - _default_landing.html.erb renders via the configured partial - Add request specs for the default and the override path, asserting the rest of the landing page stays unchanged when only this section is swapped Behavior is unchanged by default — the engine renders the same agents paragraph it did before. Host-side change to actually use this hook will ship in coplan-square in a follow-up. Stacked on top of #113 (which introduced the landing page). Amp-Thread-ID: https://ampcode.com/threads/T-019e22e9-1c86-71bc-a076-f5e6d06b03d0 Co-authored-by: Amp <amp@ampcode.com>
4a0d345
into
hampton/circle-49-50/landing-and-live-updates
4 checks passed
HamptonMakes
added a commit
that referenced
this pull request
May 21, 2026
…50) (#113) * Add public landing page and live plan content updates (CIRCLE-49, CIRCLE-50) CIRCLE-49 — Public welcome / landing page - New GET /welcome route always shows a real landing page explaining what CoPlan is, with hero, three-step workflow, and an agents section. - "/" now routes to WelcomeController: - signed-in users with plans → redirected to /plans - anonymous visitors and signed-in users with no plans → see the landing page instead of an unexplained list of plans - ?force=1 escape hatch always renders the landing page - Added CoPlan.configuration.landing_page_partial so a host app (e.g. coplan-square) can override the default copy with its own partial. Default engine partial ships with generic copy. - Removed dead, unrouted DashboardController + view. - Updated session specs because "/" is intentionally public now; auth-gated redirect assertions point at /plans. CIRCLE-50 — Live plan content updates with dirty-draft protection - Root cause: every plan mutation path only broadcast header updates over Turbo Streams, so the document body never updated in open tabs. - Extracted the rendered plan markdown into _content_body.html.erb wrapped in #plan-content-body so it can be targeted by Turbo. - Added a custom Turbo Stream action coplan-replace-if-clean that: - replaces the body live when the local tab has no dirty draft - otherwise leaves the body alone and shows a sticky warning banner with a reload button, so an unsaved comment / reply is not clobbered - Wired all mutation paths to broadcast the new body partial: - Plans::ReplaceContent - Plans::CommitSession - Api::V1::OperationsController#broadcast_plan_update - PlansController#toggle_checkbox - Dirty-state detection is intentionally conservative: any textarea or [contenteditable=true] with trimmed non-empty text counts as dirty, which covers new-comment and reply forms without per-form wiring. Testing - bundle exec rspec → 845 examples, 0 failures - Manually verified locally: API-driven edit propagates into an open tab; with text typed into a reply, body stays stale and the warning banner appears without losing the typed text. Amp-Thread-ID: https://ampcode.com/threads/T-019e22e9-1c86-71bc-a076-f5e6d06b03d0 Co-authored-by: Amp <amp@ampcode.com> * Extract landing-page agents section into a swappable partial (COPLAN-3) (#114) The "Built for any AI agent" section on the landing page is the one piece hosts most often want to customize: generic CoPlan tells users to read /agent-instructions, but a deployment like coplan-square wants to tell its users to run `sq agents skills add coplan` instead. Rather than make hosts fork the entire landing page just to change that paragraph (which is what `landing_page_partial` would force them to do), expose a single config knob for just this section. - Extract the agents section into _default_agents.html.erb - Add CoPlan.configuration.landing_agents_partial, defaulting to it - _default_landing.html.erb renders via the configured partial - Add request specs for the default and the override path, asserting the rest of the landing page stays unchanged when only this section is swapped Behavior is unchanged by default — the engine renders the same agents paragraph it did before. Host-side change to actually use this hook will ship in coplan-square in a follow-up. Stacked on top of #113 (which introduced the landing page). Amp-Thread-ID: https://ampcode.com/threads/T-019e22e9-1c86-71bc-a076-f5e6d06b03d0 Co-authored-by: Amp <amp@ampcode.com> --------- Co-authored-by: Amp <amp@ampcode.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
The landing page from #113 has one section — "Built for any AI agent" — that hosts will almost always want to customize. Generic CoPlan points users at
/agent-instructions; a deployment likecoplan-squarewants to tell users to runsq agents skills add coplaninstead.The existing
landing_page_partialconfig lets hosts swap the entire landing page, but that forces them to duplicate the hero, the 3-step how-it-works section, and all the CSS just to change one paragraph. Heavy.This PR exposes a single config knob for just that section, so a host can change the agents callout without forking the rest.
What
engine/app/views/coplan/welcome/_default_agents.html.erbCoPlan.configuration.landing_agents_partial, defaulting to that partial_default_landing.html.erbrenders via the configured partial instead of inlineBehavior unchanged by default — the engine renders the same paragraph it did before. Host-side change in
coplan-squareto actually use this hook will ship as a follow-up PR.Design note: section-level partial swap
There are a handful of ways an engine can let hosts customize views (full partial swap,
content_forslots, view path prepending, config values, DSL). We considered building a structured slot framework, but the actual delta between generic and Square's landing page is a single paragraph — so a slot framework would be over-engineering.The pattern this PR lands instead: section-level partial swap. One config knob per section that needs customization, added incrementally as real needs appear. If a future section needs to differ (e.g. hero copy on Square's landing), we add
landing_hero_partialat that point.Testing
bundle exec rspec→ 847 examples, 0 failures (added 2 new specs)References
🤖 Generated with Amp