Skip to content

Extract landing-page agents section into a swappable partial (COPLAN-3)#114

Merged
HamptonMakes merged 1 commit into
hampton/circle-49-50/landing-and-live-updatesfrom
hampton/coplan-3/landing-agents-partial
May 19, 2026
Merged

Extract landing-page agents section into a swappable partial (COPLAN-3)#114
HamptonMakes merged 1 commit into
hampton/circle-49-50/landing-and-live-updatesfrom
hampton/coplan-3/landing-agents-partial

Conversation

@HamptonMakes
Copy link
Copy Markdown
Collaborator

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 like coplan-square wants to tell users to run sq agents skills add coplan instead.

The existing landing_page_partial config 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

  • Extract the agents section into engine/app/views/coplan/welcome/_default_agents.html.erb
  • Add CoPlan.configuration.landing_agents_partial, defaulting to that partial
  • _default_landing.html.erb renders via the configured partial instead of inline
  • Request specs for the default render path and the override path, asserting that swapping only this partial leaves the hero and how-it-works sections untouched

Behavior unchanged by default — the engine renders the same paragraph it did before. Host-side change in coplan-square to 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_for slots, 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_partial at that point.

Testing

  • bundle exec rspec847 examples, 0 failures (added 2 new specs)
  • New specs cover both the default rendering and the override path

References


🤖 Generated with Amp

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>
@HamptonMakes HamptonMakes merged commit 4a0d345 into hampton/circle-49-50/landing-and-live-updates May 19, 2026
4 checks passed
@HamptonMakes HamptonMakes deleted the hampton/coplan-3/landing-agents-partial branch May 19, 2026 01:04
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>
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