---
title: Working With GraphQL
description: An overview of the various ways Houdini applications can leverage GraphQL documents.
---

<script>
    import { Transformation, DeepDive, Highlight, Warning } from '~/components'

    const storeSource = `query ViewerProfile {
    viewer {
        firstName
    }
}`

    const storeTypeDef = `// Generated Store
type ViewerProfileStore = {
    subscribe: Readable<ViewerProfile>
    fetch(...): Promise<void>
}`

    const inlineMutation = `import { mutation, graphql } from '$houdini'

const UpdateUser = graphql(\`
    mutation UpdateUser($input: UpdateUserInput!) {
        updateUser(input: $input) {
            user {
                firstName
            }
        }
    }
\`)`

    const externalMutationGraphQL = `
# src/lib/graphql/UpdateUser.gql

mutation UpdateUser($firstName: String!) {
    updateUser(firstName: $firstName) {
        user {
            firstName
        }
    }
}
`

    const externalMutation = `
// src/routes/myProfile/+page.svelte

import { UpdateUserStore } from '$houdini'

const update = new UpdateUserStore()

async function update() {
    await update.mutate({ firstName: "..." } )
}
`

</script>

# Working with GraphQL

Everyone has different needs from their GraphQL client. That means that in order to provide a high quality
developer experience, Houdini supports a few different APIs that overlap. While this is great for the
community as a whole, it creates a challenge for newcomers since there isn't a clear path for how to
structure their applications.

Hopefully, by the end of this guide you will have a much better understanding of how to do that.

## Our Recommendation

This first part is more of a style guide than detailed summary. Rather than make you sit through a bunch of examples of
alternate ways of implementing the same thing over and over, we wanted to jump right to our recommendation. Don't worry if the comments don't make
sense immediately. Come back and read this list a second time after you are done and hopefully your confusion will be cleared.

### Route Queries

The first one is straight forward: define your route queries in a file named `+page.gql` inside of your route directory. When houdini detects this file, it will handle
all of the details for you and your route will receive the query store as a prop with the same name:

```graphql:title=src/routes/myProfile/+page.gql

query MyProfile {
	viewer {
		firstName
	}
}
```

```svelte:title=src/routes/myProfile/+page.svelte&typescriptToggle=true
<script lang="ts">
    import type { PageData } from './$houdini'

    export let data: PageData

    $: ({ MyProfile } = data)
</script>

<div>
    {$MyProfile.data.viewer.firstName}
</div>
```

The reason we recommend this pattern is that it provides a nice balance between editing experience, co-location, and reliable directory structure.
If a route directory contains a `+page.gql` file, we immediately know that the route loads data from our API. When you need to
start doing more complicated things with your queries like variables or custom logic, head over to [plugin docs](/api/query#automatic-loading) to see
how you can customize the load function that houdini will generate for you.

### Fragments

Fragments should be defined inside of your `.svelte` components using the inline fragment function.

```svelte:title=src/lib/components/UserAvatar.svelte&typescriptToggle=true
<script lang="ts">
    import { fragment, graphql } from '$houdini'
    import type { UserAvatar } from '$houdini'

    export let user: UserAvatar

    // prettier-ignore
    $: data = fragment(user, graphql(`
        fragment UserAvatar on User {
            avatar
        }
    `))
</script>

<img src={$data.avatar} />
```

This keeps everything nicely isolated within a single `.svelte` file and feels like giving your svelte components a whole new
superpower.

### Mutations

At first, we find its fastest to define your documents directly inside of your components. However, as your app grows you'll
probably want to share those mutations in multiple places. When
that happens, it's easy to pull the document into an external file and import it from `$houdini`:

<Transformation>
    <Highlight slot="from" code={inlineMutation} language="typescript" />
    <div slot="to">
        <Highlight code={externalMutationGraphQL} language="graphql" />
        <Highlight code={externalMutation} language="typescript" />
    </div>
</Transformation>

### That's it!

If that's enough for you, then I hope you have a great rest of your day. Please come tell us what about you're building with houdini - we'd love to hear from you!
If you want to read more, in the next section we're going to break down all of the different ways that you can work with your project's GraphQL Documents.

<div style="height: 100px"></div>

# Working with GraphQL, part 2

Now that we have the recommendation out of the way, we can assume that you are reading this section because you are interested in a deeper
summary of houdini's GraphQL APIs.

Let's start by going over the core abstraction powering Houdini's data fetching: Document Stores.

## Document Stores

When Houdini detects a graphql document in your project, it generates a [Svelte store](https://svelte.dev/tutorial/writable-stores) that you
can use to interact with your data. Every document type (query, mutation, fragment, and subscription) generates a different kind of store with different methods.

<Transformation>
    <Highlight language="graphql" code={storeSource} slot="from"/>
    <Highlight language="typescript" code={storeTypeDef} slot="to" />
</Transformation>

These stores are your primary tools in a Houdini application. So how do you define your documents so Houdini can do its magic?

## Defining Documents

There are two different ways you can define graphql documents:

- **External documents**: you write your graphql documents in dedicated graphql files (`.gql` or
  `.graphql`) and interact with stores that you import from `$houdini`
- **Inline documents**: you define your graphql documents inside your `.svelte`, `.ts` or `.js` files and
  interact with stores that are provided by the `graphql` tag

The following examples all show query documents but everything holds true for all document types (queries, mutations, fragments, and subscriptions).

### External Documents

External documents are pretty self explanatory: define your graphql documents a file (one definition per file) and then import your
store from `$houdini` as `new MyAwesomeQueryStore()`:

```graphql:title=src/lib/queries/MyAwesomeQuery.gql
query MyAwesomeQuery {
	viewer {
		isAwesome
	}
}
```

```typescript:title=src/routes/myRoute/+page.ts&typescriptToggle=true
import { MyAwesomeQueryStore } from '$houdini'
```

### Inline Documents

Another option is to define your document directly inside of your source code (ie, in a `.svelte`, `.js`, or `.ts` file). To
do that, import `graphql` from `$houdini` and pass your query:

```svelte:title=src/routes/myRoute/+page.svelte&typescriptToggle=true
<script lang="ts">
    import { graphql } from '$houdini'

    const store = graphql(`
        query ViewerSettings {
            viewer {
                isAwesome
            }
        }
    `)
</script>
```

```typescript:title=src/routes/myRoute/+page.ts&typescriptToggle=true
import { graphql } from '$houdini'

const store = graphql(`
	query MyAwesomeQuery {
		viewer {
			isAwesome
		}
	}
`)
```

### More Information

For more information on each store type, please visit the [api docs](/api).

## Loading Data

For the rest of the guide, we are going to focus on [SvelteKit routes](https://kit.svelte.dev/docs/routing). If you want more information on
fragments, mutations, or subscriptions, you can head over to the <a href="/api" target="_blank" rel="noreferrer">api docs</a> and come
back.

Once you have your store, the next step is to start using it. Usually, your route's `.svelte` files will receive their stores as props. This often looks something like:

```svelte:title=src/routes/myProfile/+page.svelte&typescriptToggle=true
<script lang="ts">
    import type { PageData } from './$houdini'

    export let data: PageData

    $: ({ UserProfile } = data)
</script>

{$UserProfile.data.viewer.firstName}
```

Of course, you could have also defined an inline store, but most of the time, you'll want to render your views on the server which means we have to define
a `load` function in `+page.js`. This leads us to the next question: do you want Houdini to generate the load function for you?

### Manual Loads

If you are the kind of person who doesn't like hidden details, you are totally free to define your own load function as long as you call
the store's `fetch` method. In order to streamline this, Houdini provides a function for each of your stores that you can use to render
your route on the server. These functions take the same parameters as fetch:

```typescript:title=src/routes/myProfile/+page.ts&typescriptToggle=true
import { load_MyQuery } from '$houdini'
import type { PageLoad } from './$houdini'

export const load: PageLoad = async (event) => {
	return {
		...(await load_MyQuery({ event }))
	}
}
```

If even _that_ is too much magic for you, rest assured all it's doing is instantiating a store and calling `.fetch`. You can check out the definition yourself, its defined in `$houdini/plugins/houdini-svelte/stores/MyStore.js`. If you still want to do something custom, you are free to structure things however you want
just make sure that you instantiate stores inside of `load` and pass them to your route's `.svelte` file as props.

<Warning>

Be careful when loading multiple stores in a single load. You want to make sure that you aren't blocking one request while you wait for another. For
help in this situation, check out the loadAll function. It's described inside the Deep Dive, <a href="/api/query#manual-loading" target="_blank" rel="noreferrer">here</a>.

</Warning>

### Automatic Loads

On the other hand, maybe you are the kind of person who gets really tired of typing the same code over and over. For those people, Houdini's vite plugin offers some powerful
features that dramatically reduce the amount of boilerplate that you are responsible for. As you'll see there are a few different ways to get houdini to generate a load for you
but they all behave the exact same and can be [customized the same way](/api/query#automatic-loading).

The first way to tell houdini to generate a load for you is by exporting a `_houdini_load` value from `+page.js` that contains one or more query stores that you want to use in your route:

```typescript:title=src/routes/myProfile/+page.ts&typescriptToggle=true
import { ProjectListStore, graphql } from '$houdini'

const userInfo = graphql(`
	query UserInfo {
		viewer {
			firstName
		}
	}
`)

export const _houdini_load = [new ProjectListStore(), userInfo]
```

With that in place, your route will be passed two props, named after the queries: `ProjectList` and `UserInfo`:

```svelte:title=src/routes/myProfile/+page.svelte&typescriptToggle=true
<script lang="ts">
    import type { PageData } from './$houdini'

    export let data: PageData

    $: ({ ProjectList, UserInfo } = data)

    $: firstName = $UserInfo.data.viewer.firstName
    $: length = $ProjectList.data.projects.length
</script>

{firstName} can see {length} projects
```

Keep in mind that `_houdini_load` can also take a single store, which allows for something interesting:

```typescript:title=src/routes/myProfile/+page.ts&typescriptToggle=true
import { graphql } from '$houdini'

export const _houdini_load = graphql(`
	query UserInfo {
		viewer {
			firstName
		}
	}
`)
```

Your route will be rendered with a single prop: `UserInfo`. This approach works nicely when you have lots of different variables and
hooks for a particular query since it allows all of that logic to be co-located:

```typescript:title=src/routes/myProfile/+page.ts&typescriptToggle=true
import { graphql } from '$houdini'
import type { UserInfoVariables } from './$houdini'

export const _houdini_load = graphql(`
	query UserInfo($id: ID!) {
		user(id: $id) {
			firstName
		}
	}
`)

export const _UserInfoVariables: UserInfoVariables = ({ params }) => {
	return {
		id: params.id
	}
}
```

### Inline Queries

Another way to get a generated load for queries, is to add `@load` to the document inside of a
svelte component:

```svelte:title=src/lib/UserList.svelte&typescriptToggle=true
<script lang="ts">
    import { graphql } from '$houdini'

    const info = graphql(`
        query UserInfo @load {
            viewer {
                firstName
            }
        }
    `)
</script>

{$info.data.viewer.firstName}
```

This is the recommended approach for non-route components that don't care about server-side rendering.

<Warning>

Route components that use an inline query must use a reactive
statement when defining their store:

```svelte:title=src/routes/users/+page.svelte&typescriptToggle=true
<script lang="ts">
    import { graphql } from '$houdini'

    $: info = graphql(`
        query UserInfo @load {
            viewer {
                firstName
            }
        }
    `)
</script>

{$info.data.viewer.firstName}
```

</Warning>

Inline queries also work well for simple routes since we can co-locate our data needs close to the query without
having to move between files. Unfortunately, the moment we want to do anything extra (variables, hooks, etc), that logic has to be
defined inside of `+page.js` so routes using this pattern can feel a little scattered at times.

### Page Queries

The final approach for loading your data that we need to cover is by defining a page query. A page query is a query defined inside of a `+page.gql`
file inside of your route directory. This file behaves like the rest of SvelteKit's `+page` files and automatically configures your route to load the
provided query. For example, with the following query defined:

```graphql:title=src/routes/myProfile/+page.gql
query UserInfo {
	viewer {
		firstName
	}
}
```

You can now define a `+page.svelte` file that looks like the following and your route will be rendered on the server without any extra configuration:

```svelte:title=src/routes/myProfile/+page.svelte&typescriptToggle=true
<script lang="ts">
    import type { PageData } from './$houdini'

    export let data: PageData

    $: ({ UserInfo } = data)
</script>

{$UserInfo.data.viewer.firstName}
```

Remember, if you want to define variable functions or hooks, those will go in `+page.js`.

### Layout Queries

Very similar to page queries, you can create a file `+layout.gql` that will fill the prop `data` in your `layout.svelte` file.

## That's all for now!

Thanks for making it this far. Hopefully you have some idea for how you want to structure your application. If not, head to the
top of this guide and start with our suggestion, we think its a pretty compelling experience for building GraphQL applications.
