Feature: Integration screen As a verified RenewCMS owner I want /integration to show my site's base API URL and ready-to-use endpoint examples So that I, or the developer who builds my public site, can wire it up without reading the source Background: Given /integration is a verified route (meta.auth "verified") rendered as IntegrationPage inside DashboardShell, per docs/design/routes.md And the screen makes no /v1 calls; api: none (static) And the PageHeader shows title "Connect your website", description "A guide for the developer who builds your public site.", breadcrumb "Integration" (mobile title "Integration"), and no actions And an introductory paragraph reads "RenewCMS is headless: it stores and publishes your articles but doesn't show them to visitors. Your website fetches published articles from the two addresses below and displays them in its own design." And a "Base URL" row shows window.location.origin in a monospace box, with a "Copy" button (icon copy) beside it And two EndpointCard entries follow, in this order: | method | path | description | | GET | /v1/article/ | Lists every online article. | | GET | /v1/article/{id} | Returns one online article. Drafts and unknown ids both return 404. | And each EndpointCard's fetch example uses the current origin as the base of its URL: | path | fetch example | | /v1/article/ | const res = await fetch('{origin}/v1/article/')\nconst articles = await res.json() | | /v1/article/{id} | const res = await fetch('{origin}/v1/article/12')\nif (res.status === 404) return notFound()\nconst article = await res.json() | And each EndpointCard has fetch, curl and Response tabs, with fetch active by default, and its CodeBlock is labelled "JavaScript" with its own ghost "Copy" button And the curl tab's content is a plain curl command built from the current origin (e.g. "curl {origin}/v1/article/" and "curl {origin}/v1/article/12"), and the Response tab's content is a JSON sample built from the real domain Article fields; neither tab is active by default, and neither is visually checked, since the fetch tab is the one shown in the board And three info notes follow the endpoint cards, in this order: - "Anonymous callers only ever get online articles. Drafts stay private until you publish them." - "Images in body use paths like /static/uploadedImages/.png. Prefix them with the base URL before rendering." - "Browsers can only call the API from origins listed in the server's CORS setting. Ask whoever runs the server to add your site's address." Scenario: Default — the page loads with the app's own origin Given the app is served from origin "{origin}" When the user navigates to /integration Then the Base URL row shows exactly "{origin}" And the Base URL "Copy" button reads "Copy", not "Copied" And both EndpointCards' fetch examples use "{origin}" as the base of their URL Scenario: Copied — the Base URL copy button Given the user is on /integration, served from origin "{origin}" When the user activates the Base URL row's "Copy" button Then "{origin}" is written to the clipboard And the button's icon changes to check and its text changes to "Copied" And the change is announced to assistive technology When 2 seconds elapse without a further click Then the button reverts to icon copy and text "Copy" Scenario: Each EndpointCard's own Copy button is independent of the Base URL's Given the user is on /integration When the user activates the "/v1/article/" EndpointCard's "JavaScript" code block's "Copy" button Then that card's own code is written to the clipboard, and only that button reads "Copied" And the Base URL row's "Copy" button and the other EndpointCard's "Copy" button are unaffected