Building an Application with GraphQL and SvelteKit
Tags: graphql, svelte
Published: 2021-07-29 17:03:34

So, you've decided to build an application with two of the most hyped projects in our community. After browsing the internet for a bit, you've probably ran into various posts showing how to send a query in [Kit's load](https://kit.svelte.dev/docs#loading) and use it to populate the cache driving one of the more common GraphQL libraries. If you're like me, it probably left you with a bit of an unsatisfying feeling. GraphQL was supposed to reduce the amount of boilerplate necessary to build a user interface, right? Surely there's a way to pull this off without all that ceremony. Well, in this blog post I'll introduce you to [houdini](https://github.com/AlecAivazis/houdini), a new GraphQL client I've been working on that's built for SvelteKit. Hopefully by the end of this you'll agree that it dramatically reduces the overhead of building a GraphQL application with SvelteKit.

## Getting Started

We're going to be using the [Rick and Morty API](https://rickandmortyapi.com/graphql) to build a gallery of characters from the popular television show. Let's begin by starting a normal SvelteKit project: 

```sh
npm init svelte@next rick-and-morty && \
cd rick-and-morty && \
npm install
```

You should select the `Skeleton project` option and the rest is  up to you. Houdini fully supports typescript but you don't have to worry about that now if you don't want to. Next, install houdini and its preprocessor (more on that later):

```sh
npm install --save houdini houdini-preprocess
```

Once that's run, you can bootstrap a houdini project using the command line tool:

```sh
npx houdini init
```

When prompted for the API's address, enter `https://rickandmortyapi.com/graphql` and choose the `SvelteKit` option when it asks you to choose a framework. You can use the default answers for the rest of the questions (just press enter).

The only thing that's left is to link our application to houdini's runtime. Similar to how Svelte compiles our components, houdini shifts what is traditionally handled by a bloated runtime to a compile step and generates a lean GraphQL layer for your application. In order to use the generated runtime, we need to do two things. First, add the following to `svelte.config.js`:

```javascript
import path from 'path'
import houdini from 'houdini-preprocess'

export default {
    // ...
    
    preprocess: [houdini()],

    kit: {
        vite: {
            resolve: {
                alias: {
                    $houdini: path.resolve('.', '$houdini')
                }
            }
        }
    }
}
```

And finally, create a file at `src/routes/__layout.svelte` with the following contents. Note, there are two `_` in the file name.

```html
<script context="module">
    import { setEnvironment } from '$houdini'
    import environment from '../environment'
    
    setEnvironment(environment)
</script>

<slot />
```


## Fetching Data

Okay, now that we've set the project up, we can start querying the API. Update `src/routes/index.svelte` with the following content. Keep in mind that vite's hot reloading will complain about missing files until you compile the runtime:

```html
<!-- src/routes/index.svelte -->

<script>
    import { query, graphql } from '$houdini'

    const { data } = query(graphql`
        query AllCharacters { 
            characters { 
                results { 
                    name
                    id
                    image
                }
            } 
        }
    `) 

</script>

<h1>The World of Rick and Morty</h1>
<main>
    {#each $data.characters.results as character (character.id) }
        <section style={`background-image: url(${character.image})`}>
            <h2>{character.name}</h2>
        </section>
    {/each}
</main>

<style>
    h1, h2 { 
        font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
    
    main { 
        display: grid;
        grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
        grid-template-rows: repeat(4, 200px);
        row-gap: 10px;
        column-gap: 10px;
    }

    section { 
        position: relative;
        background-size: cover;
    }

    h2 { 
        display: none;
        position: absolute;
        bottom: 0px;
        margin: 0px;
        padding: 10px;
        background: rgba(255, 255, 255, .5);
        width: 100%;
        font-weight: bold;
    }

    section:hover > h2 { 
        display: block;
    }
</style>
```

Next, execute the `generate` command to create the files needed for your query:

```
npx houdini generate
```

And that's it! If you haven't already, start the SvelteKit dev server with `npm run dev` and navigate to `http://localhost:3000`. 

Notice there was no need to write your own `load` function. The only thing you had to do was write the query and then generate the runtime. One important thing to keep in mind is that every time you change your query, you will have to run the same generate command for things to take effect.

### So happened to load?

That's where the preprocessor comes in. One of its jobs is to move the actual request logic into a load function. You can think of the above code as roughly equivalent to:

```html
<script context="module">
    export async load({fetch}) {
        return { 
            props: {
                _data: await fetch({
                    text: `
                        query AllCharacters {
                            characters { 
                                results { 
                                    name
                                    id
                                    image
                                }
                            } 
                        }
                    `
                })
            }
        }
    }
</script>

<script>
    export let _data

    const data = readable(_data, /* ... */)
</script>

...
```

## That's it for now!

In this post, we setup a project with SvelteKit and houdini, created a single page driven by a GraphQL query, and generated the runtime necessary for the application to run.

I wanted to keep this short and sweet to show how easy it is to get something going but Houdini can do a lot more than just fire single queries. If you want to find out more, head over to the [project page on Github](https://github.com/AlecAivazis/houdini). That's currently the best place to go for more information. If you would like to read an in-depth series of posts that covers more of houdini's features (fragments, mutations, subscriptions, pagination, etc), let me know in the comments!