Kanorio

시작하기

Astro

Kanorio 콘텐츠로 빠른 Astro 사이트를 구축하세요. 정적 또는 서버 렌더링, 게시 시 재빌드, SEO 파일 및 에지 리다이렉트를 지원합니다.

Astro는 기본적으로 JavaScript를 포함하지 않으므로 브랜드 사이트나 블로그에 적합합니다. 컴포넌트의 프론트매터에서 fetch를 사용하여 Kanorio 콘텐츠를 불러옵니다. 정적 사이트의 경우 빌드 시점에, 서버 어댑터를 사용하는 경우 요청 시마다 불러옵니다.

1. 환경 변수

# .env
PUBLIC_KANORIO_SITE_URL="https://s-xxxxxxxxxxxx.kanorio.com"

사이트 설정 › 개발자에서 영구 시스템 URL을 사용하세요.

2. 컬렉션 목록 가져오기

---
// src/pages/projects.astro
const SITE_URL = import.meta.env.PUBLIC_KANORIO_SITE_URL;
const res = await fetch(`${SITE_URL}/api/v1/collections/projects/items?sort=-publishedAt&limit=20`);
const { data, assets } = await res.json();
---

<section>
  <h1>Projects</h1>
  {data.map((item) => {
    const cover = assets[item.fieldData.cover];
    return (
      <article>
        {cover && <img src={cover.url} alt={cover.alt ?? ""} width={cover.width} height={cover.height} loading="lazy" />}
        <h2>{item.fieldData.title}</h2>
        <p>{item.fieldData.summary}</p>
      </article>
    );
  })}
</section>

3. 블로그 게시물

정적 빌드의 경우 getStaticPaths가 nextCursor를 사용하여 블로그의 모든 페이지를 순회합니다.

---
// src/pages/blog/[slug].astro
const SITE_URL = import.meta.env.PUBLIC_KANORIO_SITE_URL;

export async function getStaticPaths() {
  const siteUrl = import.meta.env.PUBLIC_KANORIO_SITE_URL;
  const slugs = [];
  let cursor = null;
  do {
    const url = new URL(`${siteUrl}/api/v1/collections/blog/items`);
    url.searchParams.set("fields", "title");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("cursor", cursor);
    const page = await (await fetch(url)).json();
    slugs.push(...page.data.map((post) => post.slug));
    cursor = page.hasMore ? page.nextCursor : null;
  } while (cursor);
  return slugs.map((slug) => ({ params: { slug } }));
}

const { slug } = Astro.params;
const res = await fetch(`${SITE_URL}/api/v1/collections/blog/items/${encodeURIComponent(slug)}?expand=authors,categories&formats=html`);
if (!res.ok) return Astro.redirect("/404");
const { item, assets } = await res.json();
const cover = item.fieldData.cover_image ? assets[item.fieldData.cover_image] : null;
---

<article>
  <h1>{item.fieldData.title}</h1>
  {cover && <img src={cover.url} alt={cover.alt ?? ""} />}
  {item.toc?.length > 0 && (
    <nav aria-label="Contents">
      <ul>{item.toc.map((h) => <li data-level={h.level}><a href={`#${h.id}`}>{h.label}</a></li>)}</ul>
    </nav>
  )}
  <div class="prose" set:html={item.contentHtml} />
</article>

4. 폼 및 업데이트

  • 폼: Elements의 <kanorio-form>을 사용하거나 폼에 설명된 챌린지 및 제출 엔드포인트를 사용하세요. 허용된 출처에 도메인을 추가해야 합니다.
  • 정적 빌드: 호스트에서 배포 훅을 생성하고 사이트 설정 › Webhooks에 Webhook으로 추가하여 컬렉션 및 페이지 이벤트를 구독하세요. 게시할 때마다 재빌드가 트리거됩니다.
  • 서버 렌더링: @astrojs/cloudflare 또는 @astrojs/node를 사용하는 경우, 요청 시마다 읽고 X-Kanorio-Cache-Tags 응답 헤더로 캐시합니다. createRevalidateHandler로 구축된 Webhook 핸들러는 data.cacheTags의 태그를 제거합니다(동일한 어휘 사용, Webhooks 참조).

5. SEO 파일

Astro에는 프록시 재작성 기능이 없으며, 리다이렉트를 사용하면 크롤러가 다른 도메인으로 전송됩니다. 대신 엔드포인트에서 파일을 제공하세요. seoRewrites는 각 경로의 소스 URL을 반환합니다.

// src/lib/kanorio-seo.ts
import { seoRewrites } from "@kanorio/sdk";

const targets = seoRewrites({ siteUrl: import.meta.env.PUBLIC_KANORIO_SITE_URL, framework: "astro" });

export async function proxySeoFile(path: string): Promise<Response> {
  const res = await fetch(targets[path]);
  return new Response(res.body, {
    status: res.status,
    headers: { "Content-Type": res.headers.get("Content-Type") ?? "text/plain; charset=utf-8" },
  });
}
// src/pages/robots.txt.ts, and the same for sitemap.xml, llms.txt, llms-full.txt and feed.xml
import { proxySeoFile } from "../lib/kanorio-seo";

export const GET = () => proxySeoFile("/robots.txt");

fetchDeliveryJsonLd를 사용하여 각 페이지에 JSON-LD를 추가하세요.

---
import { fetchDeliveryJsonLd } from "@kanorio/sdk";

const jsonLd = await fetchDeliveryJsonLd({ siteUrl: import.meta.env.PUBLIC_KANORIO_SITE_URL, path: Astro.url.pathname });
---
{jsonLd && <script type="application/ld+json" set:html={jsonLd.scriptJson} />}

6. 리다이렉트 및 크롤러 규칙

서버 어댑터를 사용하는 경우, 미들웨어에서 관리 화면의 리다이렉트 및 AI 크롤러 규칙을 적용하고 IndexNow 키 파일을 제공하세요.

// src/middleware.ts
import { defineMiddleware } from "astro:middleware";
import { createKanorioMiddleware } from "@kanorio/sdk/edge";

const kanorioEdge = createKanorioMiddleware({ siteUrl: import.meta.env.PUBLIC_KANORIO_SITE_URL });

export const onRequest = defineMiddleware(async (context, next) => {
  const ctx = context.locals.runtime?.ctx; // Cloudflare adapter only
  const response = await kanorioEdge.handleRequest(context.request, {
    waitUntil: ctx ? (promise) => ctx.waitUntil(promise) : undefined,
  });
  return response ?? next();
});

정적 빌드에서는 미들웨어를 실행할 수 없습니다. 호스트에서 리다이렉트를 구성하고 /{key}.txt를 https://{site}/api/v1/seo/indexnow-key.txt로 전달하세요. 미들웨어는 전체 경로만 일치시키므로 와일드카드 리다이렉트는 astro.config의 redirects에 추가하세요.

7. 분석

레이아웃에서 Elements 스크립트를 한 번 로드하고 분석 요소를 추가하세요.

<script type="module" src="https://cdn.kanorio.com/elements/v1/kanorio-elements.js"></script>
<kanorio-analytics site-url="https://s-xxxxxxxxxxxx.kanorio.com"></kanorio-analytics>

페이지 뷰, 리퍼러, 캠페인 매개변수 및 AI 어시스턴트로부터의 방문이 관리 화면의 분석에 표시됩니다.