Skip to content
New: Customize your theme with an AI assistant. Read the guide

Contact, Booking & Contact Dock

Files: src/content/contact/<language>/-index.md, src/content/sections/<language>/contact-section.md, src/config/config.toml ([settings.contactInfo], [settings.contactDock]) · Skill level: Beginner

Margo gives visitors three ways to reach you: the contact form on /contact/, “Book a call” buttons that go to your scheduling page, and an optional contact dock at the bottom of the screen. The form’s fields and where it sends messages are on Forms.

The Contact Page

/contact/ shows the page header, the contact section, and a few questions (the FAQ section). It has no call to action above the footer. Its file is src/content/contact/<language>/-index.md:

pageHeader:
title: "Tell me about your *project*"
description: "**Start with a few lines.** The brand, the timing, and a rough budget are enough."
image: "/images/people/persona-designer-alt.jpg" # the portrait in the `split` layout
imageAlt: "Portrait of Hugo Merrin"
options:
layout: "split" # centered | left | split
contactSection:
options:
layout: "booking" # form | booking
faqSection:
items:
- question: "How soon will I hear back?"
answer: "Within a day on weekdays..."
options:
layout: "single"

The contact page file has no schema, so npm run astro-check doesn’t report a mistyped option there. Open /contact/ after each change.

The Contact Section

The default copy is in src/content/sections/<language>/contact-section.md: the heading (title), the line under it (description), the form, and what sits beside the form. Both layouts show the same form on the left.

LayoutBeside the formFields it reads
formRuled rows with your contact details, then a row of social iconsdetails, social
bookingA card with your availability, a short heading, a checklist, and a “Book a call” buttoncard

Contact details (form layout):

details:
- label: "Email"
url: "mailto:[email protected]"
copy: true # adds a "Copy email" button
- label: "Phone"
value: "+1 (555) 010-0199"
url: "tel:+15550100199"
- label: "Studio"
value: "Lisbon, Portugal" # no url: plain text
social:
label: "Elsewhere"
items:
- label: "Instagram"
icon: "/images/icons/social/instagram.svg" # an SVG drawn in the text color, or a Lucide name
url: "https://www.instagram.com/"

An empty social.items list hides the row.

The booking card (booking layout):

card:
enable: true
availability:
enable: true
label: "Open for new projects"
title: "Prefer a conversation?\nPick a *time* that works."
items:
- "A short video call, no slides and no preparation"
button:
enable: true
label: "Book a call"
url: "" # empty: your booking link from config.toml

These rows can differ per language, so change them in every language folder. A contactSection: block in a page file that has a schema (such as src/content/pages/ or about-us/) must include title, description, and form.

Set them once in config.toml:

[settings.contactInfo]
booking = "/contact/" # your scheduling page URL, or a page of your site

booking is where the “Book a call” buttons go when their own url is empty: the booking card on /contact/, the FAQ booking card, the call to action, the service pages, and the contact dock. Put the full https:// address of your scheduling page here, from any scheduling service. While it is /contact/, those buttons send visitors to the contact form, and the button on the contact page points at the page itself.

email feeds the “Copy email” button of the contact dock. phone, address, and officeHours are in the same table, but the theme’s layouts don’t show them. Keep them for your own components, or leave them as they are. The details beside the form come from contact-section.md, not from this table.

The Contact Dock

A small bar at the bottom center of the screen with an availability line and two buttons: Copy email and Book a call. It slides in once the first section of the page has scrolled away, and hides while the footer is in view. It is off by default.

[settings.contactDock]
enable = false # true shows it on every page
showAfter = "first-section"

To show or hide it on one page only, add contactDock: true or contactDock: false to that page’s frontmatter. The buttons use email and booking from [settings.contactInfo]; with neither set, the dock doesn’t show. Its labels are under dock in src/i18n/<language>.json, in every language.

The dock stays hidden while the cookie banner is open, and it needs JavaScript; the footer carries the same contact links for everyone. When the dock is on, the back-to-top button is not shown.

Do It With AI

Set up my contact page. My scheduling link is [URL] and my email is [EMAIL]: set booking and email
in [settings.contactInfo] of src/config/config.toml. In
src/content/sections/english/contact-section.md, set the details rows to [EMAIL, PHONE, CITY]
and the social items to [LINKS], and use the [form | booking] layout. Make the same changes in
the french and arabic files, translating the labels. [Turn on the contact dock in
[settings.contactDock].] Then open /contact/ and check it.
Type something to search...