How-to library · Developer docs

How-to library

Task-shaped pages: a title that starts with a verb, the situation in a few lines, the steps, the working code in both engines, and why this way rather than another. Found from a search, done, and left.

Topic 23 how-tos

APIs and JavaScript

Call the REST API from the browser with the CSRF token A same-origin script sends the session cookie by itself; for a signed-in visitor the platform also wants the session's CSRF token on every write. Put _csrfToken in a meta tag, send it as X-Csrf-Token, and keep that page out of the cache. Fetch three entity types in one request with GraphQL A headless home page needs its navigation pages, the latest posts and the header menu. One POST to /cdna-api/graphql from your server returns all three with only the fields you render; this wraps the endpoint's rules in one function. Page through a large API result set without timing out A REST list with no limit returns everything in one response, which times out on a large site. Page by id instead: order by id, ask for ids above the last one seen, stop on a short page, and resume from the stored id next time. Create your own JSON endpoint with a synchronous job A synchronous web-event job is an endpoint built in the admin. Retrieve a record from the request, branch on whether it was found, and reply with encoded JSON: a 200 with the record or a 404 with an error, and nothing deployed. Seed JavaScript state from a template without a second request Data the template already rendered belongs in the page, not in a second request. Encode it into a JSON script tag, parse it once at start-up, and keep per-visitor data out of cached pages. Add a dynamic fragment to a page that is otherwise cached A cached page is served to everyone, so per-visitor content goes in a fragment: a small uncached page, fetched after the cached one has painted, replacing a safe default. One layout, one page per fragment, and one line that turns caching off. Show a live cart count on a cached page A cart count in a cached header is wrong for almost everyone. Leave it empty in the template, read the visitor's cart from /cdna-api/cart after load (a 404 means no cart), and re-render from the cart your own add-to-cart calls return. Show logged-in state on a cached page A cached page cannot know who is looking. Render the signed-out links, fetch an uncached account fragment after load, swap it in, and take the CSRF token from it for your API calls. Authenticate a server-to-server integration with an API key For an integration that uses an API key, the older option: the server calls the API with Authorization: Bearer and a key belonging to a backend user made for the integration. Choose that user's permissions carefully, limit the key by IP address, keep it in one module, and read the 403's message when it fails. A new integration uses OAuth instead. Connect an editor to a site's MCP server One configuration entry, a name and https://<site>/cdna-mcp, connects an AI assistant to a site; the client handles the OAuth sign-in. Put the development site in the repository's .mcp.json and production only in your own configuration. Read a page with its sections and images in one request One GET with properties returns a page's name, address, layout and every layout area, with the components and image paths inside them. Read it by path, walk the collection by component layout, and take each layout area's value from the key its input type uses. Send a long properties selector in a GET body When a selector is too long for a URL, send it as the raw body of the GET, braces and all, with the header X-Body-Has-Parameters: 1. Only properties travels this way: filters, limit and orderBy stay in the query string, and a browser's fetch cannot send a GET body at all. Change one area of a page without touching the rest patchRevision copies the live revision and changes only the layout areas you name. Send originRevision, the layout area as areaContent(name), and activeRevision: true inside the patch: the change goes live in one request, and every other area, collections included, stays as it was. Roll back a page to an earlier revision Every save keeps the revision before it. Find the one that was right and send its id as activeRevision on the page: it is live again at once, with no new revision. Then base the next edit on it with originRevision, or the edit brings back what you rolled back. Add, reorder or remove a section on many pages Adding a section is safe with an append or an insert, one patch per page. Reordering and removing are not, once a page's positions have drifted: read the collection, change the list in your code, and write it back whole with areaContent, which also renumbers it. Schedule a page to go live, and to come down A published date in the future schedules the go-live, and unpublishAt schedules the take-down. Send ISO dates with their offset, expect them back in UTC, and check signed out: until the date, the page answers 404 to visitors. Set and clear a custom URL through the API customUrl takes an object with url. Set it in a request after the record exists, start the path with a slash, clear it with an empty url rather than null, and expect a 422 when another record already holds the address. Upload an image and place it in an area POST the file to /cdna-api/files/upload-file as multipart form data, with a folder and type=image; the answer carries the image's id. Put that id in an image area, or an image custom field, and read the layout area back for the image's path. Connect a server integration with OAuth and keep its token fresh Register an OAuth client, sign in once as a backend user made for the integration, and keep the refresh token on the server. Refresh shortly before the four-hour access token expires, or on the 403 that says it has, and store the refresh token from every answer. Sync values from another system into custom fields Read the record type's field definitions from the input types, map the other system's attributes to field names, and send only the fields that changed as customFields on the record's edit route. Fields you do not name keep their values; read the record again to see what is stored. Import records so that running the import twice changes nothing Keep the source system's key in externalId, look each record up by it, update when it is found and create when it is not, and build the content from the source the same way every time. A rerun on unchanged data finds every record and adds no revisions. Submit a Core dna form from a React or Vue front end The front end posts the visitor's answers to a route on your own server, which sends them to the form's submission API, keeps the submission token in the visitor's session, and answers with done, the errors by field, or a payment to go to. A 207 means stored but not finished: the next attempt continues it. Add the platform's form scripts to a form layout Load js-forms.js and its stylesheet with the page's nonce, wrap the steps in a .coredna-js-form container, print the form's conditionals for js-forms-conditionals.js, add js-payment-element.js for a payment, and point the container at a result callback, so a failed submission shows its errors to the visitor.