# Creating a New Content Collection
This document explains how to create and configure a new content collection in our Astro-based website.
## What are Content Collections?
Content collections in Astro are a way to organize and validate content in your project. They allow you to:
- Group related content together
- Define a schema for validating content
- Query content with TypeScript type safety
- Support multiple languages (de/en)
## Step 1: Define the Collection Schema
First, you need to define the schema for your new collection in the `src/content/config.ts` file:
```typescript
// 1. Import the defineCollection and z functions
import { defineCollection, z } from 'astro:content';
// 2. Define your collection schema
const myNewCollection = defineCollection({
type: 'content',
schema: z.object({
title: z.string(),
description: z.string(),
lastUpdated: z.date(),
lang: z.enum(['de', 'en']),
// Add any other fields specific to your collection
category: z.string(),
order: z.number().optional(),
// Add custom fields as needed
customField: z.string().optional()
})
});
// 3. Add your collection to the collections export
export const collections = {
// Existing collections...
'myNewCollection': myNewCollection,
};
```
## Step 2: Create the Directory Structure
Create the necessary directories for your content collection:
```bash
mkdir -p src/content/my-new-collection/de src/content/my-new-collection/en
```
Our project organizes content by language, so we create separate directories for German (de) and English (en) content.
## Step 3: Add Content Files
Create content files in the appropriate language directories. We use `.mdx` files for content that includes Markdown with JSX components:
**German Example** (`src/content/my-new-collection/de/example.mdx`):
```markdown
---
title: "Beispieltitel"
description: "Eine Beispielbeschreibung"
lastUpdated: 2025-02-26
lang: "de"
category: "example"
order: 1
customField: "Beispielwert"
---
# Beispielinhalt
Dies ist ein Beispielinhalt für die neue Content Collection.
```
**English Example** (`src/content/my-new-collection/en/example.mdx`):
```markdown
---
title: "Example Title"
description: "An example description"
lastUpdated: 2025-02-26
lang: "en"
category: "example"
order: 1
customField: "Example value"
---
# Example Content
This is example content for the new content collection.
```
## Step 4: Create Components for Displaying Content
Create components to display your content. For example, create a component to display a list of items from your collection:
```astro
---
// src/components/MyCollectionList.astro
import { getCollection } from 'astro:content';
import { getLangFromUrl } from '../i18n/utils';
const lang = getLangFromUrl(Astro.url);
const items = await getCollection('my-new-collection', ({ data }) => {
return data.lang === lang;
});
// Sort items if needed
const sortedItems = [...items].sort((a, b) => {
return (a.data.order || 0) - (b.data.order || 0);
});
---
)}
```
### 4. Create Page Routes
We created the necessary page routes for both German and English:
**Listing Pages** (`src/pages/de/contracts/index.astro` and `src/pages/en/contracts/index.astro`):
```astro
---
import { getCollection, getEntry } from "astro:content";
import Layout from "../../../layouts/Layout.astro";
import ContractCard from "../../../components/ContractCard.astro";
import CallToAction from "../../../components/CallToAction.astro";
import { getLangFromUrl, useTranslations } from "../../../i18n/utils";
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
// Get contracts in current language
const contractEntries = await getCollection("contracts", ({ data }) => {
return data.lang === "de"; // or "en" for English version
});
// Sort contracts by category and then by order
const sortedContracts = [...contractEntries].sort((a, b) => {
// First sort by category
if (a.data.category !== b.data.category) {
return a.data.category.localeCompare(b.data.category);
}
// Then sort by order within the same category
const orderA = a.data.order || 0;
const orderB = b.data.order || 0;
return orderA - orderB;
});
// Group contracts by category
const contractsByCategory = sortedContracts.reduce((acc, contract) => {
const category = contract.data.category;
if (!acc[category]) {
acc[category] = [];
}
acc[category].push(contract);
return acc;
}, {});
const pageTitle = t('contracts.title');
const pageDescription = t('contracts.description');
---
))}
```
**Dynamic Routes** (`src/pages/de/contracts/[...slug].astro` and `src/pages/en/contracts/[...slug].astro`):
```astro
---
import { getCollection } from "astro:content";
import Layout from "../../../layouts/Layout.astro";
import { getLangFromUrl, useTranslations } from "../../../i18n/utils";
import ContractDetail from "../../../components/ContractDetail.astro";
import CallToAction from "../../../components/CallToAction.astro";
export async function getStaticPaths() {
const contracts = await getCollection("contracts", ({ data }) => {
return data.lang === "de"; // or "en" for English version
});
return contracts.map((contract) => {
return {
params: { slug: contract.slug.replace("de/", "") }, // or "en/" for English version
props: { contract },
};
});
}
const { contract } = Astro.props;
const lang = getLangFromUrl(Astro.url);
const t = useTranslations(lang);
// Check if content is in the correct language
if (contract.data.lang !== lang) {
// Get all contracts
const allContracts = await getCollection("contracts");
// Find matching content in the correct language
const localizedContract = allContracts.find(
(c) => c.data.slug === contract.data.slug && c.data.lang === lang
);
if (localizedContract) {
return Astro.redirect(`/${lang}/contracts/${localizedContract.data.slug}`);
}
}
---
```
### 5. Add Sample Content
We created sample contract files in both German and English:
**German Example** (`src/content/contracts/de/nutzungsbedingungen.mdx`):
```markdown
---
title: "Nutzungsbedingungen"
description: "Allgemeine Nutzungsbedingungen für unsere Plattform"
lastUpdated: 2025-02-26
lang: "de"
category: "legal"
order: 1
downloadUrl: "/downloads/nutzungsbedingungen.pdf"
previewEnabled: true
---
# Nutzungsbedingungen
## 1. Geltungsbereich
Diese Nutzungsbedingungen regeln die Nutzung unserer Plattform...
```
**English Example** (`src/content/contracts/en/terms-of-service.mdx`):
```markdown
---
title: "Terms of Service"
description: "General terms of service for our platform"
lastUpdated: 2025-02-26
lang: "en"
category: "legal"
order: 1
downloadUrl: "/downloads/terms-of-service.pdf"
previewEnabled: true
---
# Terms of Service
## 1. Scope
These Terms of Service govern the use of our platform...
```
### 6. Add Translations
We added translations for the contracts section in `src/i18n/ui.ts`:
```typescript
// German translations
'contracts.title': 'Verträge & Rechtliches',
'contracts.description': 'Alle rechtlichen Dokumente und Verträge für unsere Plattform',
'contracts.download': 'Als PDF herunterladen',
'contracts.lastUpdated': 'Zuletzt aktualisiert',
'contracts.backToOverview': 'Zurück zur Übersicht',
// English translations
'contracts.title': 'Contracts & Legal',
'contracts.description': 'All legal documents and contracts for our platform',
'contracts.download': 'Download as PDF',
'contracts.lastUpdated': 'Last updated',
'contracts.backToOverview': 'Back to overview',
```
### 7. Update Navigation
We added a link to the contracts page in the Footer component:
```astro
```
### 8. Testing
After implementing all these components, you should test the contracts pages by:
1. Building the site: `npm run build`
2. Checking for any TypeScript or schema validation errors
3. Previewing the site: `npm run preview`
4. Navigating to `/de/contracts` and `/en/contracts` to ensure they display correctly
5. Clicking on individual contracts to ensure the detail pages work properly
6. Testing the download functionality if you have PDF files available
### 9. Next Steps
To further enhance your contracts collection, consider:
1. Creating actual PDF files for download in the `/public/downloads/` directory
2. Adding more contract types (privacy policy, terms of use, etc.)
3. Implementing a search functionality for contracts
4. Adding version history for contracts to track changes over time