Solution: Room Enquiry Fields
Complete schema and template changes for a room-specific enquiry label and destination and a contact-page fallback.
This completes Add a Room Enquiry Link. Replace both files from the recipe with these versions. The original room keys remain unchanged.
Complete field schema
1import { defineEditable, getEditableDefaults, text, url } from "@forgewp/react"
2
3export const editable = defineEditable({
4 room_description: text({
5 label: "Room description",
6 default: "A light-filled room overlooking the courtyard.",
7 }),
8 room_capacity: text({
9 label: "Room capacity",
10 default: "2 guests",
11 }),
12 room_size: text({
13 label: "Room size",
14 default: "36 square metres",
15 }),
16 room_enquiry_label: text({
17 label: "Enquiry link label",
18 default: "Ask about this room",
19 }),
20 room_enquiry_url: url({
21 label: "Enquiry destination",
22 default: "/contact",
23 }),
24})
25
26export const defaults = getEditableDefaults(editable)Complete Page template
1import { useWpMeta, useWpTitle } from "@forgewp/react"
2import { defaults } from "../../../cms/editables/room-details"
3
4export function RoomDetails() {
5 const title = useWpTitle()
6 const description = useWpMeta("room_description", defaults.room_description)
7 const capacity = useWpMeta("room_capacity", defaults.room_capacity)
8 const size = useWpMeta("room_size", defaults.room_size)
9 const enquiryLabel = useWpMeta("room_enquiry_label", defaults.room_enquiry_label)
10 const enquiryUrl = useWpMeta("room_enquiry_url", defaults.room_enquiry_url)
11
12 return (
13 <main className="mx-auto max-w-4xl px-6 py-16">
14 <p className="text-sm font-semibold uppercase tracking-wide text-slate-500">
15 Make yourself at home
16 </p>
17 <h1 className="mt-3 text-4xl font-bold text-slate-950">{title}</h1>
18 <p className="mt-6 text-lg leading-relaxed text-slate-600">{description}</p>
19 <dl className="mt-10 grid gap-6 border-t border-slate-200 pt-8 sm:grid-cols-2">
20 <div>
21 <dt className="text-sm font-semibold text-slate-500">Capacity</dt>
22 <dd className="mt-2 text-xl text-slate-950">{capacity}</dd>
23 </div>
24 <div>
25 <dt className="text-sm font-semibold text-slate-500">Room size</dt>
26 <dd className="mt-2 text-xl text-slate-950">{size}</dd>
27 </div>
28 </dl>
29 <a
30 href={enquiryUrl}
31 className="mt-10 inline-flex bg-slate-950 px-6 py-3 font-semibold text-white focus-visible:outline-2 focus-visible:outline-offset-4"
32 >
33 {enquiryLabel}
34 </a>
35 </main>
36 )
37}Why it works
The schema supplies both editor metadata and defaults. Each useWpMeta call uses the same saved key as its schema field. The Page component reads the current Page's values, so another room Page can use different content with the same template.
The URL field provides a destination control in the generated ACF group. The link uses the saved room-specific destination, or the schema's /contact fallback when the field is unset or empty. Create that contact Page on the test site, or set the default to the site's actual contact URL before exporting.
Verify in WordPress
pnpm typecheck
pnpm forgewp export --validate --strict- Update the test theme, open a Page using the Room Details template, and confirm ACF is active.
- Check the new controls in Room Details Content and confirm the original room values remain present.
- Enter a real contact Page URL and a label such as Enquire about the Garden Suite.
- Save, reload the editor, and test the link on the visitor page using pointer and keyboard.
- Clear the destination, save, and confirm the link uses the configured contact fallback while the room facts remain visible.
- Use a second room Page to verify independent values.
For larger content models, see Page Content Slots and Editable Fields. Return to Build Editable Room Details to compare the original three-field version.