gql:guide

Interactive guide to soda-gql features and patterns

16 stars

Best use case

gql:guide is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Interactive guide to soda-gql features and patterns

Teams using gql:guide should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/gql-guide/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/tools/gql-guide/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/gql-guide/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How gql:guide Compares

Feature / Agentgql:guideStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Interactive guide to soda-gql features and patterns

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# GraphQL Guide Skill

This skill provides interactive guidance on soda-gql features, syntax patterns, and best practices. Use `$ARGUMENTS` to route to specific topics, or ask the user to choose a topic.

## Topic Routing

Parse `$ARGUMENTS` to determine the user's intent, or use AskUserQuestion to offer topic selection.

### Available Topics

1. **tagged-template** — Tagged template syntax for fragments and operations
2. **fragment** — Fragment definitions and spreading patterns
3. **operation** — Query, mutation, and subscription operations
4. **union** — Union type handling and member selection
5. **directive** — GraphQL directives (@include, @skip, custom directives)
6. **metadata** — Fragment metadata and field-level callbacks
7. **setup** — Project setup, config, and initial codegen
8. **lsp** — LSP integration, editor setup, and diagnostics
9. **codegen** — Schema codegen, typegen, and build integration
10. **colocation** — Fragment colocation patterns ($colocate directive)

### Topic Selection

If `$ARGUMENTS` is empty or unclear, use AskUserQuestion:

**Question:** "What would you like guidance on?"
**Options:**
- "Tagged template syntax" → tagged-template
- "Fragment patterns" → fragment
- "Operations (queries/mutations)" → operation
- "Union types" → union
- "Directives" → directive
- "Metadata and callbacks" → metadata
- "Project setup" → setup
- "LSP and editor integration" → lsp
- "Codegen and build tools" → codegen
- "Fragment colocation" → colocation

## Topic Content

For each topic, provide:
1. Concept explanation
2. References to documentation files
3. Code examples from playground
4. Common patterns and anti-patterns
5. Related topics

---

## Topic 1: tagged-template

### Concept

soda-gql supports tagged template syntax for writing GraphQL fragments and operations. Only `gql` is exported from the generated runtime:

```typescript
import { gql } from "<outdir-path>"; // e.g. "@/graphql-system"

// Fragment with tagged template
const userFragment = gql.default(({ fragment }) =>
  fragment("UserFields", "User")`{
    id
    name
    email
  }`(),
);

// Operation with tagged template
const getUserQuery = gql.default(({ query }) =>
  query("GetUser")`($id: ID!) {
    user(id: $id) {
      id
      name
    }
  }`(),
);
```

### When to Use Tagged Template vs Callback Builder

**Decision Tree:**

1. **Fragment definition:**
   - ✅ Use tagged template: Simple field selection, no aliases
   - ❌ Use callback builder: Field aliases needed

2. **Fragment spreading (Fragment → Fragment):**
   - ✅ Use tagged template interpolation: `...${otherFragment}`

3. **Operation definition:**
   - ✅ Use tagged template: No fragment spreads via `.spread()`, no aliases, no $colocate
   - ❌ Use callback builder: Has fragment spreads via `.spread()`, aliases, or $colocate

4. **Special features:**
   - Metadata callbacks with variable access → callback builder only
   - Operations with `.spread()` → callback builder only

### Key Constraint

**Both tagged templates reject interpolation with values:**
- `fragment("Name", "Type")\`${value}\`` → ❌ Throws error
- `query("Name")\`{ field(id: ${id}) }\`` → ❌ Throws error

The only valid interpolation is fragment-to-fragment spreading: `fragment("Name", "Type")\`...${otherFragment} ...\``.

Operations with fragment spreads MUST use callback builder syntax with `.spread()` instead of tagged template interpolation.

### Documentation References

- **Callback-only features:** `playgrounds/vite-react/src/graphql/callback-builder-features.ts`
- **Fragment patterns:** `playgrounds/vite-react/src/graphql/fragment-spread-patterns.md`

### Code Examples

**Tagged template fragment:**
```typescript
// playgrounds/vite-react/src/graphql/fragments.ts
const userFields = gql.default(({ fragment }) =>
  fragment("UserFields", "User")`{
    id
    name
    email
    createdAt
  }`(),
);
```

**Tagged template operation (no spreads):**
```typescript
// playgrounds/vite-react/src/graphql/operations.ts
const simpleQuery = gql.default(({ query }) =>
  query("GetUsers")`{
    users {
      id
      name
    }
  }`(),
);
```

**Callback builder operation (with spreads):**
```typescript
// playgrounds/vite-react/src/graphql/callback-builder-features.ts
const userQuery = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUser",
    variables: {
      ...$var("id").ID("!"),
    },
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        ...userFields.spread(),
      })),
    }),
  }),
);
```

### Common Patterns

✅ **Simple fragment with tagged template:**
```typescript
const fields = gql.default(({ fragment }) =>
  fragment("UserBasic", "User")`{
    id
    name
    email
  }`(),
);
```

✅ **Fragment spreading another fragment (tagged template):**
```typescript
const extendedFields = gql.default(({ fragment }) =>
  fragment("ExtendedUser", "User")`{
    ...${userFields}
    createdAt
    updatedAt
  }`(),
);
```

❌ **Operation with fragment spread (WRONG - tagged template):**
```typescript
// This will FAIL - cannot use tagged template interpolation for fragment spreads in operations
const badQuery = gql.default(({ query }) =>
  query("BadQuery")`{
    user {
      ${userFields}
    }
  }`(),
);
```

✅ **Operation with fragment spread (CORRECT - callback builder):**
```typescript
const userQuery = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUser",
    variables: { ...$var("id").ID("!") },
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        ...userFields.spread(),
      })),
    }),
  }),
);
```

### Related Topics

- **fragment** — Fragment definition and spreading patterns
- **operation** — Operation structure and variable handling
- **metadata** — Callback-builder-only metadata feature

---

## Topic 2: fragment

### Concept

Fragments define reusable field selections with type safety. They can be spread into operations or composed into other fragments.

### Fragment Types

1. **Tagged template fragment** — Simple field selection
2. **Callback builder fragment** — Aliases, nested spreads, metadata
3. **Fragment spreading** — Composing fragments together

### Variable Declaration Pattern

**"Fragments declare requirements; operations declare contract"**

- Fragments can declare variables they need in the GraphQL definition
- Operations must explicitly declare ALL variables, including fragment requirements
- No auto-merge: operation variables are the source of truth

### Documentation References

- **Spread patterns:** `playgrounds/vite-react/src/graphql/fragment-spread-patterns.md`
- **Nested spreads:** `playgrounds/vite-react/src/graphql/nested-fragment-verification.ts`

### Code Examples

**Simple fragment:**
```typescript
const userBasic = gql.default(({ fragment }) =>
  fragment("UserBasic", "User")`{
    id
    name
    email
  }`(),
);
```

**Fragment with variables:**
```typescript
const userConditional = gql.default(({ fragment }) =>
  fragment("ConditionalUser", "User")`($includeEmail: Boolean!) {
    id
    name
    email @include(if: $includeEmail)
  }`(),
);
```

**Fragment spreading (Fragment → Fragment):**
```typescript
const userExtended = gql.default(({ fragment }) =>
  fragment("ExtendedUser", "User")`{
    ...${userBasic}
    createdAt
    updatedAt
  }`(),
);
```

**Operation spreading fragment (callback builder):**
```typescript
const getUserQuery = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUser",
    variables: {
      ...$var("id").ID("!"),
      ...$var("includeEmail").Boolean("!"),
    },
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        ...userConditional.spread({ includeEmail: $.includeEmail }),
      })),
    }),
  }),
);
```

### Common Patterns

✅ **Fragment composition via tagged template:**
```typescript
const baseFields = gql.default(({ fragment }) =>
  fragment("UserBase", "User")`{ id name }`(),
);
const extendedFields = gql.default(({ fragment }) =>
  fragment("UserExtended", "User")`{
    ...${baseFields}
    email
  }`(),
);
```

✅ **Operation declares all variables:**
```typescript
const getUserQuery = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUser",
    variables: {
      ...$var("id").ID("!"),
      ...$var("includeEmail").Boolean("!"), // ALL variables, including fragment requirements
    },
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        ...userConditional.spread({ includeEmail: $.includeEmail }),
      })),
    }),
  }),
);
```

❌ **Auto-merge expectation (WRONG):**
```typescript
// Fragment declares $includeEmail
const frag = gql.default(({ fragment }) =>
  fragment("F", "User")`($includeEmail: Boolean!) {
    id name email @include(if: $includeEmail)
  }`(),
);

// Operation does NOT auto-inherit variables — must declare includeEmail explicitly
const badQuery = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUser",
    variables: { ...$var("id").ID("!") }, // Missing includeEmail!
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        ...frag.spread(), // Will fail — $includeEmail not in scope
      })),
    }),
  }),
);
```

### Related Topics

- **tagged-template** — Syntax for fragment definitions
- **operation** — How operations use fragments
- **metadata** — Fragment-level metadata callbacks

---

## Topic 3: operation

### Concept

Operations define the GraphQL query/mutation/subscription structure with variables, arguments, and field selections.

### Operation Types

1. **Tagged template operation** — Simple operations without fragment spreads
2. **Callback builder operation** — Complex operations with spreads, aliases, $colocate

### Variable Handling

**Operations declare the contract:**
- All variables must be declared at operation level
- Fragment variables are NOT auto-merged
- In callback builder, use `$var("name").Type("!")` to declare variables

### Documentation References

- **Examples:** `playgrounds/vite-react/src/graphql/operations.ts`
- **Callback-only features:** `playgrounds/vite-react/src/graphql/callback-builder-features.ts`

### Code Examples

**Simple query (tagged template):**
```typescript
const getUsers = gql.default(({ query }) =>
  query("GetUsers")`{
    users {
      id
      name
    }
  }`(),
);
```

**Query with variables (tagged template):**
```typescript
const getUser = gql.default(({ query }) =>
  query("GetUser")`($id: ID!) {
    user(id: $id) {
      id
      name
      email
    }
  }`(),
);
```

**Query with fragment spread (callback builder):**
```typescript
const getUserWithFragment = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUserWithFragment",
    variables: {
      ...$var("id").ID("!"),
    },
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        ...userFields.spread(),
      })),
    }),
  }),
);
```

**Mutation (tagged template):**
```typescript
const createUser = gql.default(({ mutation }) =>
  mutation("CreateUser")`($input: CreateUserInput!) {
    createUser(input: $input) {
      id
      name
    }
  }`(),
);
```

### Common Patterns

✅ **Simple query (tagged template):**
```typescript
const getUserQuery = gql.default(({ query }) =>
  query("GetUser")`($id: ID!) {
    user(id: $id) {
      id
      name
      posts {
        id
        title
      }
    }
  }`(),
);
```

✅ **Operation with multiple variables (callback builder):**
```typescript
const getUserPosts = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUserPosts",
    variables: {
      ...$var("id").ID("!"),
      ...$var("limit").Int(),
      ...$var("offset").Int(),
    },
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        ...f.posts({ limit: $.limit, offset: $.offset })(({ f }) => ({
          id: f.id,
          title: f.title,
        })),
      })),
    }),
  }),
);
```

### Related Topics

- **tagged-template** — Operation syntax options
- **fragment** — Using fragments in operations
- **directive** — Adding directives to operations

---

## Topic 4: union

### Concept

Union types in GraphQL represent a value that could be one of several types. soda-gql handles union types using standard GraphQL inline fragment syntax in tagged templates.

### Union Member Selection

Union handling uses standard GraphQL inline fragment syntax (`... on TypeName { fields }`). Always include `__typename` for type discrimination:

```typescript
const searchQuery = gql.default(({ query }) =>
  query("Search")`($term: String!) {
    search(term: $term) {
      __typename
      ... on User {
        id
        name
      }
      ... on Organization {
        id
        name
        members
      }
    }
  }`(),
);
```

### Documentation References

- **Union verification:** `playgrounds/vite-react/src/graphql/union-type-verification.ts`
- **Callback-only features:** `playgrounds/vite-react/src/graphql/callback-builder-features.ts`

### Code Examples

**Union field selection (tagged template):**
```typescript
const searchQuery = gql.default(({ query }) =>
  query("Search")`($term: String!) {
    search(term: $term) {
      __typename
      ... on User {
        id
        name
        email
      }
      ... on Post {
        id
        title
        content
      }
    }
  }`(),
);
```

**Union with fragment spread (callback builder):**
```typescript
const userFields = gql.default(({ fragment }) =>
  fragment("UserFields", "User")`{ id name email }`(),
);
const postFields = gql.default(({ fragment }) =>
  fragment("PostFields", "Post")`{ id title content }`(),
);

const searchQuery = gql.default(({ query, $var }) =>
  query.operation({
    name: "Search",
    variables: { ...$var("term").String("!") },
    fields: ({ f, $ }) => ({
      ...f.search({ term: $.term })(({ f }) => ({
        __typename: f.__typename,
        ...userFields.spread(),
        ...postFields.spread(),
      })),
    }),
  }),
);
```

### Common Patterns

✅ **Always include __typename:**
```typescript
const q = gql.default(({ query }) =>
  query("Search")`($term: String!) {
    search(term: $term) {
      __typename
      ... on TypeA { id fieldA }
      ... on TypeB { id fieldB }
    }
  }`(),
);
```

✅ **Exhaustive member handling:**
```typescript
const q = gql.default(({ query }) =>
  query("SearchAll")`($term: String!) {
    search(term: $term) {
      __typename
      ... on User { id name }
      ... on Organization { id name }
      ... on Bot { id label }
    }
  }`(),
);
```

### Related Topics

- **fragment** — Using fragments with union members
- **metadata** — Type-specific metadata callbacks

---

## Topic 5: directive

### Concept

GraphQL directives modify field behavior (@include, @skip) or provide metadata for tools. soda-gql supports standard and custom directives.

### Directive Types

1. **Standard directives:** `@include(if: Boolean)`, `@skip(if: Boolean)`
2. **Custom directives:** Defined in schema, used for metadata or tooling

### Directive Syntax

**Tagged template with static values:**
```typescript
gql.default(({ fragment }) =>
  fragment("UserFields", "User")`{
    id
    name
    email @include(if: true)
  }`(),
);
```

**Tagged template with variables:**
```typescript
gql.default(({ fragment }) =>
  fragment("ConditionalUser", "User")`($includeEmail: Boolean!) {
    id
    name
    email @include(if: $includeEmail)
  }`(),
);
```

### Documentation References

- **Directive verification:** `playgrounds/vite-react/src/graphql/directive-verification.ts`

### Code Examples

**@include directive:**
```typescript
const conditionalFields = gql.default(({ fragment }) =>
  fragment("ConditionalUser", "User")`($showEmail: Boolean!) {
    id
    name
    email @include(if: $showEmail)
  }`(),
);
```

**@skip directive:**
```typescript
const fields = gql.default(({ fragment }) =>
  fragment("SkipEmail", "User")`($hideEmail: Boolean!) {
    id
    name
    email @skip(if: $hideEmail)
  }`(),
);
```

**Custom directive:**
```typescript
// Assuming schema has: directive @sensitive on FIELD_DEFINITION
const userFields = gql.default(({ fragment }) =>
  fragment("SensitiveUser", "User")`{
    id
    name
    socialSecurityNumber @sensitive
  }`(),
);
```

### Common Patterns

✅ **Conditional field inclusion (callback builder with fragment spread):**
```typescript
const detailsFragment = gql.default(({ fragment }) =>
  fragment("UserDetails", "User")`($includeDetails: Boolean!) {
    bio @include(if: $includeDetails)
    website @include(if: $includeDetails)
  }`(),
);

const getUserQuery = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUser",
    variables: {
      ...$var("id").ID("!"),
      ...$var("includeDetails").Boolean("!"),
    },
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        id: f.id,
        name: f.name,
        ...detailsFragment.spread({ includeDetails: $.includeDetails }),
      })),
    }),
  }),
);
```

### Related Topics

- **fragment** — Directives in fragment definitions
- **metadata** — Directive metadata for tooling

---

## Topic 6: metadata

### Concept

soda-gql allows attaching metadata to fragments and operations for build-time processing (e.g., component mapping, documentation generation). Metadata is passed as an argument to the template call.

### Metadata APIs

**Static metadata** — passed as argument to the template call:

```typescript
const frag = gql.default(({ fragment }) =>
  fragment("UserFields", "User")`{
    id
    name
  }`({
    metadata: { component: "UserCard" },
  }),
);
```

**Callback metadata** — receives variables for dynamic values:

```typescript
const frag = gql.default(({ fragment }) =>
  fragment("UserFields", "User")`($userId: ID!) {
    id
    name
  }`({
    metadata: ({ $ }: { $: { userId: string } }) => ({
      cacheKey: `user:${$.userId}`,
    }),
  }),
);
```

### Documentation References

- **Callback-only features:** `playgrounds/vite-react/src/graphql/callback-builder-features.ts`
- **Metadata verification:** `playgrounds/vite-react/src/graphql/metadata-verification.ts`

### Code Examples

**Static fragment metadata:**
```typescript
const userFragment = gql.default(({ fragment }) =>
  fragment("UserCard", "User")`{
    id
    name
    email
  }`({
    metadata: { component: "UserCard", description: "User profile data" },
  }),
);
```

**Callback metadata with variables:**
```typescript
const userFragment = gql.default(({ fragment }) =>
  fragment("CachedUser", "User")`($userId: ID!) {
    id
    name
    email
  }`({
    metadata: ({ $ }: { $: { userId: string } }) => ({
      cacheKey: `user:${$.userId}`,
    }),
  }),
);
```

**Callback builder operation with metadata:**
```typescript
const q = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUser",
    variables: { ...$var("id").ID("!") },
    metadata: ({ $, fragmentMetadata }) => ({
      entityId: $.id,
      fragmentCount: fragmentMetadata?.length ?? 0,
    }),
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        ...userFragment.spread(),
      })),
    }),
  }),
);
```

### Common Patterns

✅ **Component mapping:**
```typescript
gql.default(({ fragment }) =>
  fragment("UserProfile", "User")`{ id name }`({
    metadata: { component: "UserProfile" },
  }),
);
```

✅ **Dynamic cache key:**
```typescript
gql.default(({ fragment }) =>
  fragment("CachedUser", "User")`($id: ID!) { id name }`({
    metadata: ({ $ }: { $: { id: string } }) => ({
      cacheKey: `user:${$.id}`,
    }),
  }),
);
```

### Related Topics

- **fragment** — Metadata on fragments
- **colocation** — $colocate with metadata

---

## Topic 7: setup

### Concept

Setting up a new soda-gql project involves config file creation, schema setup, and initial codegen.

### Setup Steps

1. **Install dependencies:**
   ```bash
   bun add @soda-gql/core @soda-gql/builder
   bun add -d @soda-gql/cli
   ```

2. **Add framework plugin (optional but recommended):**
   ```bash
   # For Vite
   bun add -d @soda-gql/vite-plugin
   # For Next.js
   bun add -d @soda-gql/next-plugin
   ```

3. **Create config file (`soda-gql.config.ts`):**
   ```typescript
   import { defineConfig } from '@soda-gql/config';

   export default defineConfig({
     outdir: './src/graphql/generated',
     schemas: {
       default: {
         schemaFiles: ['./schema.graphql'],
       },
     },
   });
   ```

4. **Run initial codegen:**
   ```bash
   bun run soda-gql codegen schema
   ```

5. **Configure build plugin (Vite example):**
   ```typescript
   // vite.config.ts
   import { sodaGql } from '@soda-gql/vite-plugin';

   export default {
     plugins: [sodaGql()],
   };
   ```

### Documentation References

- **Main README:** `README.md` — Installation and quick start
- **Playground examples:** `playgrounds/vite-react/src/graphql/` — Working examples of all features

### Common Issues

**Issue: codegen fails with "config not found"**
- Check config file is named correctly: `soda-gql.config.{ts,js,mjs}`
- Check config exports with `export default`

**Issue: "Cannot find module '@soda-gql/core'"**
- Run `bun install` to install dependencies
- Check package.json includes @soda-gql packages

**Issue: Types not updating in editor**
- Restart TypeScript server
- Check outdir matches tsconfig include paths

### Related Topics

- **codegen** — Running codegen and typegen
- **lsp** — Editor integration

---

## Topic 8: lsp

### Concept

soda-gql provides LSP (Language Server Protocol) integration for real-time diagnostics, autocomplete, and hover information in editors.

### LSP Features

1. **Real-time diagnostics:** Type errors, invalid fields, syntax errors
2. **Autocomplete:** Field names, types, directives
3. **Hover information:** Type info, documentation
4. **Go to definition:** Jump to schema type definitions

### Editor Setup

**VS Code:**
1. Install LSP extension (if available)
2. Configure workspace settings:
   ```json
   {
     "soda-gql.configPath": "./soda-gql.config.ts"
   }
   ```

**Other editors:**
- Use language server client compatible with your editor
- Point to soda-gql LSP server

### LSP Diagnostics

The LSP validates:
- Field existence on types
- Argument types and required args
- Fragment type compatibility
- Variable types
- Directive usage

### Common Issues

**Issue: LSP not providing diagnostics**
- Check config file is found (`found: true` in project detection)
- Restart editor/LSP server
- Check LSP logs for errors

**Issue: False positive errors**
- Run `bun run soda-gql codegen schema` to sync generated types
- Check schema files are up to date

### Related Topics

- **setup** — Initial LSP configuration
- **codegen** — Keeping LSP in sync with schema

---

## Topic 9: codegen

### Concept

soda-gql codegen generates TypeScript types from GraphQL schemas (schema codegen) and validates/generates types from tagged templates (typegen).

### Codegen Commands

1. **Schema codegen:**
   ```bash
   bun run soda-gql codegen schema
   ```
   - Reads schema files from config
   - Generates runtime type system in outdir
   - Creates fragment and query builder types

2. **Type generation (typegen):**
   ```bash
   bun run soda-gql typegen
   ```
   - Scans codebase for tagged templates
   - Validates field selections against schema
   - Generates TypeScript types for fragments/operations

### Build Integration

**Development workflow:**
1. Edit schema files
2. Run `bun run soda-gql codegen schema`
3. Edit fragments/operations
4. Build plugin auto-runs typegen during build

**Watch mode (if supported):**
```bash
bun run soda-gql codegen schema --watch
```

### Documentation References

- **Monorepo infrastructure:** `docs/guides/monorepo-infrastructure.md` — Build system

### Common Issues

**Issue: "Schema file not found"**
- Check schemaFiles paths in config are relative to config file
- Use Read tool to verify file exists at expected path

**Issue: Typegen shows "unknown field"**
- Run schema codegen first: `bun run soda-gql codegen schema`
- Check field name spelling matches schema

**Issue: Generated types not updating**
- Delete generated directory and re-run codegen
- Check outdir in config matches import paths

### Related Topics

- **setup** — Initial codegen configuration
- **lsp** — Real-time validation vs build-time codegen

---

## Topic 10: colocation

### Concept

Fragment colocation places fragment definitions near the components that use them, improving code organization and enabling build-time optimizations.

### Colocation Patterns

**$colocate in callback builder spread:**
```typescript
const userQuery = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUser",
    variables: { ...$var("id").ID("!") },
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        id: f.id,
        ...userFragment.spread({ $colocate: true }),
      })),
    }),
  }),
);
```

**Component colocation:**
```typescript
// UserCard.tsx
export const userCardFragment = gql.default(({ fragment }) =>
  fragment("UserCardFields", "User")`{
    id
    name
    email
    avatarUrl
  }`(),
);

export function UserCard({ user }) {
  // Component uses fragment data
}
```

### Build-Time Processing

Colocation enables:
- Dead code elimination (unused fragments removed)
- Component-fragment association tracking
- Automatic fragment composition

### Documentation References

- **Callback-only features:** `playgrounds/vite-react/src/graphql/callback-builder-features.ts` — $colocate examples

### Common Patterns

✅ **Component-fragment pair:**
```typescript
// UserProfile.tsx
const userProfileFragment = gql.default(({ fragment }) =>
  fragment("UserProfile", "User")`{
    id
    name
    email
    bio
  }`(),
);

function UserProfile({ data }) {
  // Use fragment data
}
```

✅ **Fragment composition with colocation:**
```typescript
const parentQuery = gql.default(({ query, $var }) =>
  query.operation({
    name: "GetUserPage",
    variables: { ...$var("id").ID("!") },
    fields: ({ f, $ }) => ({
      ...f.user({ id: $.id })(({ f }) => ({
        ...profileFragment.spread({ $colocate: true }),
        ...settingsFragment.spread({ $colocate: true }),
      })),
    }),
  }),
);
```

### Related Topics

- **fragment** — Fragment spreading and composition
- **metadata** — Component metadata with colocation

---

## Interactive Mode

If the user's question doesn't match a specific topic, use Grep to search documentation:

1. Extract keywords from user's question
2. Use Grep to search docs/guides/ and playgrounds/
3. Read matching files and synthesize answer
4. Reference specific documentation sections

### Example: User asks "How do I add pagination?"

1. Grep for "pagination" in docs and playground
2. If not found, explain general approach:
   - Add limit/offset arguments to field
   - Use variables in operation
   - Show example with args
3. Suggest related topics: operation, fragment

## Validation Checklist

Before completing this skill, ensure:
- ✅ Topic was identified from $ARGUMENTS or user selection
- ✅ Relevant documentation was referenced
- ✅ Code examples were provided from playground or synthesized
- ✅ Common patterns and anti-patterns were shown
- ✅ Related topics were suggested for further exploration

Related Skills

workflow-guide

16
from diegosouzapw/awesome-omni-skill

Provides guidance on Cursor ↔ Claude Code 2-agent workflow. Use when user mentions ワークフローについて, Cursorとの連携, 作業の流れ, 2-agent workflow, collaboration. Do NOT load for: 実装作業, ワークフロー設定, ハンドオフ実行.

validate-guidelines

16
from diegosouzapw/awesome-omni-skill

Empirically verify guideline changes by running before/after eval runs across multiple models and ensuring no regressions. Use when proposing or reviewing changes to runner/models/guidelines.ts, or when the user asks to validate guidelines.

service-guide

16
from diegosouzapw/awesome-omni-skill

Guide for implementing Backend.AI service layer (create, get, search, update, delete, purge, batch operations, Actions, ActionResults, Processors, ActionProcessor, Service methods)

Plexus Classifier Guidelines Management

16
from diegosouzapw/awesome-omni-skill

The format for guidelines documents for Plexus scorecard scores and the validation tool.

migration-guides

16
from diegosouzapw/awesome-omni-skill

Migration guides - from other AI tools, version upgrades, config migration. Use when switching from Cursor, Copilot, or Cody, upgrading Claude Code versions, or migrating configurations and customizations.

implementation-guide

16
from diegosouzapw/awesome-omni-skill

Generate comprehensive implementation guides for coding tasks instead of writing code directly. Use when the user requests detailed implementation documentation, step-by-step development guides, or when they want to implement features themselves using tools like Cursor. Creates exhaustive guides with background context, architecture decisions, milestones with verification points, and rationale for a "build-it-yourself" workflow.

guided-debugging

16
from diegosouzapw/awesome-omni-skill

Scaffolded debugging guidance for learning. Use when a learner encounters unexpected behavior, errors, or bugs and wants to develop debugging skills, not just fix the problem. This skill guides through hypothesis formation, investigation design, and root cause analysis while enforcing human-only decision points. Triggers on phrases like "help me debug", "something's wrong with my code", "unexpected behavior", "learning to debug", or when a learner describes symptoms without immediately asking for the fix.

github.com/n-r-w/ctxlog guidelines

16
from diegosouzapw/awesome-omni-skill

Guidelines and examples for using the ctxlog logging package.

environment-setup-guide

16
from diegosouzapw/awesome-omni-skill

Guide developers through setting up development environments with proper tools, dependencies, and configurations

ecosystem-guide

16
from diegosouzapw/awesome-omni-skill

Guide to spences10's Claude Code ecosystem. Use when user asks which tool to use, how tools relate, or needs help choosing between MCP servers, skills, or CLIs.

cowork-guide

16
from diegosouzapw/awesome-omni-skill

CRITICAL: Comprehensive guide for CoWork Skills CLI tool. Triggers on: cowork, Skills.toml, skill management, plugin configuration, cowork init, cowork install, cowork config, cowork generate

components-guide

16
from diegosouzapw/awesome-omni-skill

Guide to using Convex components for feature encapsulation. Learn about sibling components, creating your own, and when to use components vs monolithic code.