Writing Content (Markdown, MDX & Shortcodes)
Writing Content
Skill level: Beginner · Used in: blog posts, service pages, project stories, legal and text pages
The text below the frontmatter of a content file is written in Markdown. Files that end in .mdx can also use shortcodes: small components such as buttons and notices. The /components/ page of the theme shows them (source: src/content/pages/english/components.mdx).
Markdown Basics
## A section heading### A smaller heading
Plain text. **Bold**, _italic_, and [a link](/pricing/).
- A list item- Another item
1. A numbered step2. Another step
> A quote.- Start headings at
##. The page title is already the#heading. - Links to other sites open in a new tab automatically.
- In the Markdown body, an image path that starts with
/points to thepublic/folder:/images/my-photo.jpgispublic/images/my-photo.jpg, served as it is. Frontmatter image fields such asimageare different: they read fromsrc/assets/images/and are optimized. See Icons & Images.
Heading Sizes
Add a class in square brackets at the end of a heading to set its size without changing its level:
## Power your home with panels sized to the way you live [.h4]
### Why homeowners choose us [.h5]The heading stays an h2 or h3 for search engines and screen readers, but is drawn at the h4 or h5 size. The service pages and project stories use this to keep headings compact.
Shortcodes
Three shortcodes are available in every .mdx file without an import: Button, Notice, and MonitoringPanel (see Monitoring Panel below).
Button: a theme button, with the same options as buttons in content files.
<Button label="Get a free quote" url="/contact/" variant="fill" class="mt-4" />Notice: a highlighted note. type is info, warning, success, or error; title is optional.
<Notice type="info" title="Good to know"> Panels still produce on cloudy days, just less.</Notice>Images in posts. A post can show an optimized image from src/assets/images/ with the image component. Import it under the frontmatter, as src/content/blog/english/post-1.mdx does:
import OptimizedImage from "@/components/utilities/OptimizedImage.astro";
<OptimizedImage src="/images/photos/my-photo.jpg" alt="Describe the photo" />Monitoring Panel
A drawing of a monitoring app, coded in HTML and SVG (no screenshot): a header with a title and a “Live” pill, up to three tiles (for example energy produced, self-use, and battery level), a chart of production against home usage over the day, and a status line. The numbers count up when the panel scrolls into view. The maintenance and repair service page shows it under its first paragraphs.
Put it anywhere in the body of a .mdx file, such as a service page, a project story, or a blog post:
<MonitoringPanel />It doesn’t work in .md files. Its text and numbers are in src/content/sections/english/monitoring-panel.md (and the other language folders):
---enable: truetitle: "Home system · 6.4 kWp"subtitle: "Today, updated 2 min ago"badge: "Live"stats: - label: "Produced today" value: "24.6 kWh" icon: "Sun" - label: "Battery" value: "86%" icon: "BatteryCharging" progress: 86chart: title: "Production vs usage" unit: "kW" summary: "Line chart of today from 06:00 to 21:00. Production peaks at 4.6 kW at 13:00..." labels: ["06:00", "09:00", "12:00", "15:00", "18:00", "21:00"] production: label: "Production" values: [0, 0.3, 1.1, 2.2, 3.2, 3.9, 4.4, 4.6, 4.3, 3.7, 2.8, 1.8, 0.9, 0.3, 0.1, 0] usage: label: "Home usage" values: [0.6, 1.1, 1.0, 0.6, 0.5, 0.8, 1.2, 0.7, 0.5, 0.5, 0.7, 1.0, 1.6, 2.4, 2.0, 1.2]status: text: "All panels producing" detail: "16 of 16 panels online"caption: "What you see in the app after we service your system."---| Key | What it does |
|---|---|
enable | false hides the panel on every page that uses it |
title, subtitle, badge | The header of the app: a title, a muted line under it, and a small pill on the right |
stats | Up to three tiles, each with a label, a value, and an optional Lucide icon. Write value as a number with an optional unit, such as "24.6 kWh" or "78%", so it can count up. progress (0 to 100) adds a level bar under the value |
chart.title, chart.unit | The chart’s heading and the unit of its scale, for example "kW" |
chart.labels | The time marks under the chart, spread evenly from the first value to the last |
chart.production, chart.usage | Each line’s label and its values, one number per reading. The scale follows the highest value |
chart.summary | What the chart shows, in words. Screen readers read it instead of the drawing, so update it when you change the values |
status | The line at the bottom: text, and an optional muted detail |
caption | An optional line under the panel |
The sample numbers are an illustration, not readings from a real system. Change them to fit your offer, or describe them as an example in the caption.
To change some fields on one page only, pass them in content. The other fields come from the file:
<MonitoringPanel content={{ title: "Farm system · 48 kWp", badge: "Example" }} />Do It With AI
Write a [blog post | service page | project story] about [TOPIC] as an .mdx file insrc/content/[blog | services | projects]/english/. Match the frontmatter of the other files in thatfolder. Use ## headings with [.h4] or [.h5] like the existing files, one <Notice type="info"> whereuseful, and end with a <Button> to /contact/. Keep it under [N] words, and use only facts I give you.