kuroco-frontend-integration
npx skills add https://github.com/diverta/kuroco-skills --skill kuroco-frontend-integration
Agent 安装分布
Skill 文档
Kuroco ããã³ãã¨ã³ãçµ±åãã¿ã¼ã³
Kuroco HeadlessCMSã¨Nuxt.js/Next.jsãªã©ã®ããã³ãã¨ã³ããã¬ã¼ã ã¯ã¼ã¯ã®çµ±åãã¿ã¼ã³ã
ããã¥ã¡ã³ãåç
§: /kuroco-docs ã¹ãã«ã使ç¨ãã¦Kurocoå
¬å¼ããã¥ã¡ã³ããæ¤ç´¢ã»åç
§ã§ãã¾ãã
ç®æ¬¡
- ãµãã¼ããã¬ã¼ã ã¯ã¼ã¯
- ç°å¢è¨å®
- APIè¨å®ã®åææ¡ä»¶
- èªè¨¼å®è£
- Nuxt.jsçµ±å â 詳細㯠references/nuxt.md
- Next.jsçµ±å â 詳細㯠references/nextjs.md
ãµãã¼ããã¬ã¼ã ã¯ã¼ã¯
| ãã¬ã¼ã ã¯ã¼ã¯ | ãã¼ã¸ã§ã³ | æ¨å¥¨ã¦ã¼ã¹ã±ã¼ã¹ |
|---|---|---|
| Nuxt.js 3.x | Vue 3ç³» | æ°è¦ããã¸ã§ã¯ãï¼æ¨å¥¨ï¼ |
| Nuxt.js 2.x | Vue 2ç³» | æ¢åããã¸ã§ã¯ã |
| Next.js 13+ | React (App Router) | æ°è¦Reactããã¸ã§ã¯ã |
| Next.js (Pages) | React (Pages Router) | æ¢åReactããã¸ã§ã¯ã |
ç°å¢è¨å®
ç°å¢å¤æ°
# .env.local
NUXT_PUBLIC_API_BASE=https://example.g.kuroco.app
NEXT_PUBLIC_API_BASE=https://example.g.kuroco.app
API_ID=1
ããã¸ã§ã¯ãæ§æ
Nuxt.js:
pages/
âââ news/
â âââ index.vue # ä¸è¦§
â âââ [slug].vue # 詳細 (Nuxt3)
âââ login.vue
âââ profile.vue
composables/
âââ useAuth.ts
âââ useApi.ts
Next.js (App Router):
app/
âââ news/
â âââ page.tsx # ä¸è¦§
â âââ [slug]/page.tsx
âââ login/page.tsx
âââ profile/page.tsx
lib/
âââ auth.ts
âââ api.ts
APIè¨å®ã®åææ¡ä»¶
1. ã»ãã¥ãªãã£è¨å®ï¼Cookieèªè¨¼ï¼
- 管çç»é¢ â API â ã»ãã¥ãªã㣠â Cookieã鏿
- ããã³ãã¨ã³ãã¨APIãã¡ã¤ã³ããµããã¡ã¤ã³éãã«è¨å®
- ä¾:
www.example.comã¨api.example.com
- ä¾:
2. CORSè¨å®
管çç»é¢: [API] â [ã»ãã¥ãªãã£] â [CORSè¨å®]
CORS_ALLOW_ORIGINS:
- http://localhost:3000
- https://your-frontend-domain.com
CORS_ALLOW_CREDENTIALS: true
CORS_ALLOW_METHODS:
- GET
- POST
èªè¨¼å®è£
ãã°ã¤ã³
interface LoginResponse {
grant_token: string
status: number
member_id: number
}
async function login(email: string, password: string): Promise<LoginResponse> {
const response = await fetch(
'https://example.g.kuroco.app/rcms-api/1/login',
{
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
}
)
if (!response.ok) {
const error = await response.json()
throw new Error(error.errors?.[0]?.message || 'ãã°ã¤ã³ã«å¤±æãã¾ãã')
}
return response.json()
}
ãã°ã¢ã¦ã
async function logout(): Promise<void> {
await fetch('https://example.g.kuroco.app/rcms-api/1/logout', {
method: 'POST',
credentials: 'include'
})
}
ãã°ã¤ã³ç¶æ ã®ç¢ºèª
async function checkAuth(): Promise<ProfileResponse | null> {
try {
const response = await fetch(
'https://example.g.kuroco.app/rcms-api/1/profile',
{ credentials: 'include' }
)
if (!response.ok) return null
return response.json()
} catch {
return null
}
}
ä¼å¡ç»é²
async function signup(memberData: SignupData): Promise<void> {
const response = await fetch(
'https://example.g.kuroco.app/rcms-api/1/member/insert',
{
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(memberData)
}
)
if (!response.ok) {
const error = await response.json()
throw new Error(error.errors?.[0]?.message || 'ç»é²ã«å¤±æãã¾ãã')
}
}
Nuxt.jsçµ±å
詳細ãªå®è£ ä¾: references/nuxt.md ãåç §
ã¯ã¤ãã¯ã¹ã¿ã¼ãï¼Nuxt 3ï¼:
// composables/useKurocoApi.ts
export function useKurocoApi() {
const config = useRuntimeConfig()
async function get<T>(endpoint: string, params?: Record<string, any>): Promise<T> {
const query = params ? `?${new URLSearchParams(params)}` : ''
return await $fetch<T>(
`${config.public.apiBase}/rcms-api/${config.public.apiId}/${endpoint}${query}`,
{ credentials: 'include' }
)
}
return { get }
}
Next.jsçµ±å
詳細ãªå®è£ ä¾: references/nextjs.md ãåç §
ã¯ã¤ãã¯ã¹ã¿ã¼ãï¼App Routerï¼:
// lib/api.ts
export async function apiGet<T>(endpoint: string): Promise<T> {
const response = await fetch(
`${process.env.NEXT_PUBLIC_API_BASE}/rcms-api/1/${endpoint}`,
{ credentials: 'include', cache: 'no-store' }
)
if (!response.ok) throw new Error(`API Error: ${response.status}`)
return response.json()
}
KurocoPagesçµ±å
KurocoPagesã¯Kurocoãæä¾ããããã³ãã¨ã³ããã¹ãã£ã³ã°ãµã¼ãã¹ã
// kuroco_front.json
{
"rewrites": [
{ "source": "/(.*)", "destination": "/index.html" }
]
}
ãããã¤: 管çç»é¢ â ããã³ãã¨ã³ã â KurocoPages â GitHubãªãã¸ããªé£æº
注æäºé
ãµã¼ããã¼ãã£Cookieåé¡
Safariãªã©ã§ã¯ãµã¼ããã¼ãã£Cookieããããã¯ããã¾ãã
解決ç: APIãã¡ã¤ã³ã¨ããã³ãã¨ã³ããã¡ã¤ã³ãåä¸ãã¡ã¤ã³ï¼ãµããã¡ã¤ã³éãï¼ã«è¨å®
HTMLãµãã¿ã¤ãº
v-html ã dangerouslySetInnerHTML ã使ç¨ããéã¯XSSã«æ³¨æ:
import DOMPurify from 'dompurify'
const sanitizedHtml = DOMPurify.sanitize(htmlContent)
é¢é£ããã¥ã¡ã³ã
docs/tutorials/integrate-kuroco-with-nuxt.md– Nuxt.jsçµ±ådocs/tutorials/integrate-login.md– ãã°ã¤ã³å®è£docs/tutorials/signup.md– ä¼å¡ç»é²docs/tutorials/beginners-guide.md– ãã®ãã¼ãºã¬ã¤ãdocs/tutorials/corporate-sample-site-to-ssg.md– SSG対å¿