Markdown

On this page

Content files are GitHub Flavored Markdown: tables, task lists, strikethrough, autolinks and footnotes work as on GitHub. Raw HTML passes through, but a <script> or an onclick attribute fails the build, because pages ship no JavaScript.

Code

Fenced code blocks are highlighted at build time with Shiki, in a light and a dark theme that follow the reader's system setting. No highlighter reaches the browser.

```ts
export const answer = 42;
```

An unknown language name gets a warning with the file and line, and the block stays plain. List languages you write on purpose in markdown.ignoreLanguages to silence it.

Every heading gets an id from its text, in ASCII: ## Çalışma notları becomes #calisma-notlari. Repeated headings get -1, -2. Put {#id} at the end of a heading to choose the id yourself, as this section does:

## Heading links {#heading-links}

kilim check fails on links to ids that do not exist, on this page or another. Themes get the headings as page.headings; the doc layout lists them under "On this page". Turn ids off with markdown: { headingIds: false }.

Images

Put images in public/ and link them from the root, e.g. ![A kilim](/images/kilim.jpg). Kilim reads their size, adds width, height and loading="lazy", writes AVIF and WebP versions in several widths and preloads the first image of a page (the images.lcp option). An empty alt text is a warning in kilim check; write alt="" in HTML for images that are only decoration.

Components

Components are pieces of HTML that themes and sites provide and Markdown uses through directives:

:::callout{type=tip}
Components render at build time, so they add **no JavaScript**.
:::

A container directive (:::name) wraps Markdown, a leaf directive (::name{prop=value}) stands on its own line, and a text directive (:name[text]) sits inside a sentence. Attributes in {} are the component's props, checked against its schema. kilim dev shows every component with its props and examples at /__kilim/blocks.

A site adds its own in components/, each file exporting defineComponent:

// components/badge.tsx
import { defineComponent, z } from "@kilim-dev/core";

export default defineComponent({
  props: z.object({ tone: z.enum(["new", "beta"]).default("new") }),
  render({ tone }, { children }) {
    return <span class={`badge badge-${tone}`}>{children}</span>;
  },
});

Pages made of blocks

A landing page is often a list of sections rather than prose. Add blocks to the collection schema with blocksSchema, then list the sections in the frontmatter:

---
title: Home
blocks:
  - type: hero
    title: Fast sites, checked
    text: Static pages with zero JavaScript.
    actions:
      - label: Get started
        url: /getting-started/
  - type: content
  - type: cta
    title: Ready?
    actions:
      - label: Install
        url: /getting-started/installation/
---

The body goes where the `content` block is.

Each block's props are checked against its schema, with the file and line of the mistake. The default theme has nine, from hero to faq (see Using a theme); a site adds its own in blocks/ with defineBlock. In kilim dev, the admin edits block pages on the theme's real rendering, with drag and drop.