Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions starter/cms-sanity-graphql-fragments/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
SANITY_STUDIO_PROJECT_ID=<SANITY_STUDIO_PROJECT_ID>
SANITY_STUDIO_DATASET=<SANITY_STUDIO_DATASET>
SANITY_API_TOKEN=<SANITY_API_TOKEN>
NEXT_PUBLIC_SANITY_GRAPHQL_URL=<NEXT_PUBLIC_SANITY_GRAPHQL_URL>

# Webhook secret for on-demand revalidation
SANITY_REVALIDATE_SECRET=<SANITY_REVALIDATE_SECRET>
45 changes: 45 additions & 0 deletions starter/cms-sanity-graphql-fragments/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*
!.env.example

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts

# sanity
.sanity
133 changes: 133 additions & 0 deletions starter/cms-sanity-graphql-fragments/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Agent Guidelines for cms-graphql-fragments

## Commands
- **Build**: `npm run build` (uses Next.js with Turbopack)
- **Dev**: `npm run dev` (development server with Turbopack)
- **Lint**: `npm run lint` (Biome linter)
- **Format**: `npm run format` (Biome formatter)
- **Sanity Studio**: `npm run sanity:dev` (start Sanity Studio development server)
- **Deploy GraphQL**: `npm run sanity:deploy` (deploy GraphQL API to Sanity)
- **Generate Types**: `npm run schema:generate` (generate GraphQL types from Sanity schema)
- **No test command configured** - check with user if tests are needed

## Code Style
- **Formatter**: Biome with 2-space indentation
- **Imports**: Auto-organized by Biome, use `@/*` for src imports
- **Types**: Strict TypeScript, explicit types for props/exports
- **Naming**: camelCase for variables/functions, PascalCase for components
- **Component Files**: Use kebab-case for component filenames (e.g., `my-component.tsx`)
- **Components**: Function declarations with explicit return types when complex
- **Error Handling**: Use TypeScript strict mode, handle async errors properly

### Biome Configuration
- **Import Organization**: Automatically enabled on save/format
- **Domain Rules**: Next.js and React recommended rules enabled
- **Ignored Files**: `node_modules`, `.next`, `dist`, `build`, `.sanity`, `lib/generated`
- **VCS Integration**: Git integration enabled with ignore file support

## Framework Specifics
- Next.js 15 App Router with React 19
- Tailwind CSS for styling
- Use `next/image` for images, `next/font` for fonts
- Export metadata objects for SEO
- Use `className` prop for styling

## GraphQL & Data Fetching
- **Client**: URQL with `@urql/next/rsc` for React Server Components
- **Type Safety**: gql.tada with GraphQL introspection from `src/lib/generated/graphql-env`
- **Client Setup**: Use `createGraphQLClient()` from `@/lib/graphql`
- **Query Pattern**:
```typescript
import { registerUrql } from "@urql/next/rsc";
import { createGraphQLClient, graphql } from "@/lib/graphql";

const { getClient } = registerUrql(createGraphQLClient);

const QUERY = graphql(`
query QueryName($param: String!) {
field
}
`);

const { data, error } = await getClient().query(QUERY, { param: "value" });
```
- **Error Handling**: Always check for `error` object and provide user-friendly error UI
- **ISR**: Use `export const revalidate = 60` for Incremental Static Regeneration
- **Scalars**: DateTime, Date (string), JSON (TypedObject from Sanity)

### Schema Generation Workflow
1. **After Sanity schema changes**: Deploy GraphQL API with `npm run sanity:deploy`
2. **Update types**: Run `npm run schema:generate` to regenerate TypeScript types
3. **Generated files**: Types are created in `src/lib/generated/` (auto-ignored by Biome)
4. **Import types**: Use generated types from `@/lib/graphql` for type safety

## GraphQL Fragment Colocation

### Fragment Definition Rules
- **Server Components**: Define fragments directly in component files
- **Client Components**: Define fragments in separate `.ts` files to avoid client/server boundary issues
- **Fragment files**: Use `-fragment.ts` suffix (e.g., `nav-link-fragment.ts`)

### Client Component Pattern
When a component needs `"use client"` directive:

1. **Fragment Definition** (`component-fragment.ts`):
```typescript
import { graphql } from "@/lib/graphql";

export const componentFragment = graphql(`
fragment ComponentName on Type {
field1
field2
}
`);
```

2. **Client Component** (`component.tsx`):
```typescript
"use client";

import { type FragmentOf } from "@/lib/graphql";
import type { componentFragment } from "./component-fragment";

interface Props {
data: FragmentOf<typeof componentFragment>;
}

export function Component({ data }: Props) {
// Client-side logic (hooks, event handlers, etc.)
}
```

3. **Parent Server Component**:
```typescript
import { componentFragment } from "./component-fragment";
import { Component } from "./component";

const parentFragment = graphql(`...`, [componentFragment]);
```

### Why This Pattern?
- **Prevents Runtime Errors**: Avoids "f.definitions is not iterable" errors
- **Maintains Colocation**: Fragments stay close to components that use them
- **Respects Boundaries**: Separates server-side GraphQL logic from client-side interactivity
- **Type Safety**: Components get proper TypeScript types via `FragmentOf<typeof {GraphQL Fragment}>`

## Sanity CMS Integration

### Available Schema Types
The project includes comprehensive Sanity schemas defined in `src/lib/schema.ts`:

- **Post**: Blog posts with title, slug, excerpt, content, publishedAt
- **Page**: Static pages with title, slug, excerpt, content, SEO settings, published status
- **Navigation**: Site navigation with title and navigation items (label, href, isExternal)
- **Footer**: Footer configuration with title, description, links, social links, copyright
- **SEO**: SEO settings object with metaTitle and metaDescription
- **Social Links**: Platform-specific social media links (Twitter, GitHub, LinkedIn, etc.)

### Content Management Workflow
1. **Development**: Use `npm run sanity:dev` to start Sanity Studio
2. **Schema Changes**: After modifying `src/lib/schema.ts`, deploy with `npm run sanity:deploy`
3. **Type Generation**: Run `npm run schema:generate` to update GraphQL types
4. **Content Creation**: Use Sanity Studio to create and manage content
5. **ISR**: Content changes trigger revalidation automatically (only available on deployed project)
Loading