CollectionsというOSSのヘッドレスCMSが良さそうだったのでAstro 4.0からの接続を試す

こちらの記事で知った Collections が素晴らしく自分向きっぽかったのでいろいろ試してみようと思います。

https://qiita.com/zane/items/2037f3b1078a80d7986b

# Collectionsのセットアップ

https://github.com/collectionscms/collections?tab=readme-ov-file#-installation

ひとまずドキュメント通りに起動していきます。

```
npx create-collections-app my-app
cd my-app
npm run dev
```

めちゃくちゃ簡単に起動しました :raised_hands: すごい :raised_hands: 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64098/6573b1de-214c-dcda-ac0c-d20bfebd3907.png)

テスト用のデータを追加しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64098/db8748c2-0466-d92c-8523-740a1b314e80.png)

# Astro 4.0のセットアップ

https://astro.build/blog/astro-4/

```
# Create a new Astro 4.0 project:
npm create astro@latest
cd tender-tower #勝手に付いたディレクトリ名
npm dev start
```

これも素晴らしく簡単に起動しますね。 :raised_hands: 

# Collectionsと接続

AstroにはヘッドレスCMSと接続する方法がいくつも用意されています。

https://docs.astro.build/en/guides/cms/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64098/2cf10f02-9aa1-d722-a776-bed33a5041e7.png)

しかし残念ながら この中に Collections はまだ載っていないため、独自に作っていきたいと思います。（そのうちサポートされれば嬉しいですね）

上のGuidesをいくつか見てみたところ、Prepr（どなたか存じないですが）への繋ぎ方が真似できそうなので参考にしていきます。

https://docs.prepr.io/connecting-front-end-apps/astro-quick-start-guide

```typescript:src/lib/collections.ts
export async function Collections(modelId: string): Promise<Response> {
    const endpoint: string = import.meta.env.COLLECTIONS_ENDPOINT as string;
    const token: string = import.meta.env.COLLECTIONS_TOKEN as string;
    const response: Response = await fetch(`${endpoint}/api/models/${modelId}/contents`, {
        method: 'GET',
        headers: {
            'Content-Type': 'application/json',
            'Authorization': `Bearer ${token}`
        },
    })
    return response
}
```

```.env
COLLECTIONS_ENDPOINT="http://localhost:4000"
COLLECTIONS_TOKEN="***************"
```

```src/env.d.ts
/// <reference types="astro/client" />
interface ImportMetaEnv {
    readonly COLLECTIONS_ENDPOINT: string
    readonly COLLECTIONS_TOKEN: string
}
```

```jsx:src/pages/index.astro
---
import Layout from '../layouts/Layout.astro';
import {Collections} from '../lib/collections';
import Card from '../components/Card.astro';

const response = await Collections(1)
const { data } = await response.json()
const articles = data
---

<Layout title="Welcome to Astro.">
	<main>
		<h1>Welcome to <span class="text-gradient">Astro</span></h1>
		<p class="instructions">
			To get started, open the directory <code>src/pages</code> in your project.<br />
			<strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
		</p>
		<ul role="list" class="link-card-grid">
			{
				articles.map((article) => (
					<Card
						href={article.slug}
						title={article.title}
						body={article.body}
					/>
				))
			}
        </ul>
	</main>
</Layout>
```

```jsx:src/pages/[...slug].astro
---
import Layout from '../layouts/Layout.astro';
import {Collections} from '../lib/collections';

export async function getStaticPaths() {
    const response = await Collections(1)
    const { data } = await response.json();
    return data.map((data: any) => { return {params: {slug: data.slug}} })
}

const { slug } = Astro.params;
const response = await Collections(1)
const { data } = await response.json()
const article = data.find((data: any) => data.slug === slug )
---

<Layout title="Welcome to Astro.">
	<main>
		<h1>Welcome to <span class="text-gradient">Astro</span></h1>
		<p class="instructions">
			To get started, open the file <code>src/pages/[...slug].astro</code> in your project.<br />
			<strong>Code Challenge:</strong> Tweak the "Welcome to Astro" message above.
		</p>
        <section>
            <h1>{article.title}</h1>
            <div>{article.body}</div>
        </section>
	</main>
</Layout>
```

# 完成

できました :raised_hands: 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64098/a378df09-8f23-2fbe-7d66-0030de5fe63c.png)

子ページにもアクセスできます。 :raised_hands: 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64098/fe58b34d-d385-512d-fcf7-921b149ac862.png)

## 新規ページ作成

ページを増やしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64098/7c70ba6c-dcab-e7bb-194a-5cabb0bfccd0.png)

反映されますね。 :raised_hands: 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64098/87035e68-3c69-0c75-1e37-b45b347a030c.png)

# 静的ビルド

ビルドも無事できてプレビューも確認できました。 :raised_hands: 

```
npm run build
npm run preview
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64098/d4a95dba-05e8-4c0b-be06-e3bac8dc3906.png)

# 素晴らしく自分向き とは？

ローカルで簡単に起動してデータはSQLiteで持ち運べるのが最高ですね。
コンテンツ編集もデザイン作成もローカルで出来て、そのままGitにコミットしてしまえるのが最高で最高ですね。

ちょっとしたサイトの構築が全てローカルで作業できて１リポジトリで完結しそうなので、この構成は今後すごく活躍しそうです。