---
title: Sections
description: Create and use reusable content blocks across your site.
---

import { Aside, Steps, Tabs, TabItem } from "@astrojs/starlight/components";

Sections are reusable content blocks that editors can insert into any content via slash commands. Use them for common patterns like CTAs, testimonials, feature grids, or any content that appears across multiple pages.

## Querying Sections

### getSection

Fetch a single section by slug:

```typescript
import { getSection } from "emdash";

const cta = await getSection("newsletter-cta");

if (cta) {
  console.log(cta.title);    // "Newsletter CTA"
  console.log(cta.content);  // PortableTextBlock[]
}
```

### getSections

Fetch multiple sections with optional filters:

```typescript
import { getSections } from "emdash";

// Get all sections
const { items: all } = await getSections();

// Filter by source
const { items: themeSections } = await getSections({ source: "theme" });

// Search by title/keywords
const { items: results } = await getSections({ search: "newsletter" });
```

`getSections` returns `{ items: Section[], nextCursor?: string }` following the standard pagination pattern.

## Section Structure

```typescript
interface Section {
  id: string;
  slug: string;
  title: string;
  description?: string;
  keywords: string[];
  content: PortableTextBlock[];
  previewUrl?: string;
  source: "theme" | "user" | "import";
  themeId?: string;
  createdAt: string;
  updatedAt: string;
}
```

### Source Types

| Source   | Description                                      |
| -------- | ------------------------------------------------ |
| `theme`  | Defined in seed file, managed by theme           |
| `user`   | Created by editors in admin                      |
| `import` | Imported from WordPress (reusable blocks)        |

## Using Sections in Content

Editors insert sections using the `/section` slash command in the rich text editor:

<Steps>

1. Type `/section` (or `/pattern`, `/block`, `/template`)

2. Search or browse available sections

3. Click to insert the section's content at the cursor position

</Steps>

The section's Portable Text content is copied into the document. This means:

- Changes to the section don't affect already-inserted content
- Editors can customize the inserted content
- Content remains self-contained

<Aside type="tip">
  For content that should stay synchronized, consider using [Widget Areas](/guides/widgets/) with component widgets instead.
</Aside>

## Creating Sections

### In the Admin UI

1. Navigate to **Sections** in the admin sidebar

2. Click **New Section**

3. Fill in:
   - **Title** - Display name for the section
   - **Slug** - URL identifier (auto-generated from title)
   - **Description** - Help text for editors

4. Add content using the rich text editor

5. Optionally set keywords for easier discovery

### Via Seed Files

Include sections in your theme's seed file:

```json
{
  "sections": [
    {
      "slug": "hero-centered",
      "title": "Centered Hero",
      "description": "Full-width hero with centered heading and CTA",
      "keywords": ["hero", "banner", "header"],
      "content": [
        {
          "_type": "block",
          "style": "h1",
          "children": [{ "_type": "span", "text": "Welcome to Our Site" }]
        },
        {
          "_type": "block",
          "children": [{ "_type": "span", "text": "Your tagline goes here." }]
        }
      ]
    },
    {
      "slug": "newsletter-cta",
      "title": "Newsletter CTA",
      "keywords": ["newsletter", "subscribe", "email"],
      "content": [
        {
          "_type": "block",
          "style": "h3",
          "children": [{ "_type": "span", "text": "Subscribe to our newsletter" }]
        }
      ]
    }
  ]
}
```

### Via WordPress Import

WordPress reusable blocks (`wp_block` post type) are automatically imported as sections:

- Source is set to `"import"`
- Gutenberg content converted to Portable Text

## Rendering Sections Programmatically

For server-rendered section content outside the editor:

```astro
---
import { getSection } from "emdash";
import { PortableText } from "emdash/ui";

const newsletter = await getSection("newsletter-cta");
---

{newsletter && (
  <aside class="cta-box">
    <PortableText value={newsletter.content} />
  </aside>
)}
```

## Admin UI Features

The Sections library (`/_emdash/admin/sections`) provides:

- **Grid view** with section previews
- **Search** by title and keywords  
- **Filter** by source
- **Quick copy** slug to clipboard
- **Edit** section content and metadata
- **Delete** with confirmation (warns for theme sections)

## API Reference

### `getSection(slug)`

Fetch a section by slug.

**Parameters:**
- `slug` — The section's unique identifier (string)

**Returns:** `Promise<Section | null>`

### `getSections(options?)`

List sections with optional filters.

**Parameters:**
- `options.source` — Filter by source: `"theme"`, `"user"`, or `"import"`
- `options.search` — Search title and keywords

**Returns:** `Promise<Section[]>`

## REST API

### List Sections

```http
GET /_emdash/api/sections
GET /_emdash/api/sections?source=theme
GET /_emdash/api/sections?search=newsletter
```

### Get Section

```http
GET /_emdash/api/sections/newsletter-cta
```

### Create Section

```http
POST /_emdash/api/sections
Content-Type: application/json

{
  "slug": "my-section",
  "title": "My Section",
  "description": "Optional description",
  "keywords": ["keyword1", "keyword2"],
  "content": [...]
}
```

### Update Section

```http
PUT /_emdash/api/sections/my-section
Content-Type: application/json

{
  "title": "Updated Title",
  "content": [...]
}
```

### Delete Section

```http
DELETE /_emdash/api/sections/my-section
```

## Next Steps

- [Working with Content](/guides/working-with-content/) - Learn about the rich text editor
- [Widget Areas](/guides/widgets/) - For synchronized dynamic content
- [Content Import](/migration/content-import/) - Import WordPress reusable blocks
