---
title: Architecture
description: An overview of Houdini's internal architecture
---

<script>
    import { DeepDive } from '~/components'
</script>

# Architecture

Houdini is a highly customizable framework for building GraphQL applications.
It does come with a basic set of assumptions that we believe are important,
however it relies on plugins to make this core integrate as closely as possible with
your application.

This document is meant to illustrate the high level organization of Houdini and is
meant for people who are looking to extend the framework or contribute to
the project. Once you are some-what comfortable with this document,
head over to the [Codegen Plugins reference](/api/codegen-plugins) for a deeper
dive in how to build your own extensions. As always, if you have any questions,
please [join us on discord](https://discord.gg/Gd8vfvxpsD) and ask.

## Overview

Our solution is broken up into 3 parts:

- **HoudiniClient**: The heart of your application. It's built out of a composable
  structure that defines your documents' behavior (query the API, cache the
  result, mutations, etc). Out of the box, it contains a normalized cache,
  garbage collector, optimistic updates, pagination, and much more.
- **Codegen**: A code generation tool that's responsible for taking
  your GraphQL documents and generating all of the necessary files that the runtime
  needs to perform its job. Plugins can also hook into this pipeline and generate their
  own documents or runtime utilities. This is incredibly
  helpful when combined with custom file transformations.
- **Source Transformations**: Plugins can define transformations that change
  your project's files from an ergonomic API to whatever it takes to support the
  desired behavior.

As a guiding principal, Houdini tries to shift as much processing and logic into
a build/compile step. This significantly trims down your application's
bundle size since we can avoid including things like your schema or
extraneous logic to parse your queries. As a loose rule, the more we
can do at compile time, the less our browsers are responsible for.

For more info on `HoudiniClient`, check out the [Client Plugin docs](/api/client-plugins). For the code generation pipeline and source transformations,
check out the [Codegen Plugin docs](/api/codegen-plugins).

## An Example

Let's see this in practice with a concrete example: a Svelte component. Don't
worry if you don't know Svelte - the actual contents and syntax should translate
to any framework. But, just in case it's not clear, this component fires a
query and renders the name of every user separated by a comma:

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

    const UserList = graphql(`
        query UserList @load {
            users {
                name
            }
        }
    `)
</script>

{$UserList.data?.users?.map(user => user.name).join(', ')}
```

This small example contains a lot of things:

- The user defines a query by passing a string to the `graphql` function. This function
  has an overloaded definition that returns a specific store for the given
  string.
- The code generator parses, validates and creates an internal representation
  of the document that the cache needs to process the result. The svelte plugin
  generates the store in the previous step from this representation.
- The component content is transformed to automatically load the query when the
  component mounts.

It might help to see the transformed version. This does contain a little more Svelte
but hopefully its clear that the function passed to `onMount` happens when the component
mounts:

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

    const UserList = new UserListStore()

    onMount(() => {
        UserList.fetch()
    })
</script>

{$UserList.data?.users?.map(user => user.name).join(', ')}
```

With this in mind, we can now be a little more explicit about what we have to do:

- Generate an overloaded definition for `graphql` for typescript that points to a
  Svelte Store
- Generate a `UserListStore` class that will perform the actual loading. Internally,
  it holds a reference to the query's internal representation and creates a
  [Document Store](/api/client-plugins) which handles the caching and
  network interactions.
- Replace the `graphql` function with an instantiation of `UserListStore`
- Add the `onMount` block to load the store

While this example _is_ slightly complex, it does illustrates how Houdini
leverages a combination of code generation and file transformations to deliver its core
user experience. It's also a good overview of the kinds of things a plugin might be
concerned about.

<DeepDive title="Plugin vs Core">

If you want to build your own plugins, it's worth trying identify which parts of that
list are provided by the Svelte plugin and what is part of Houdini's core.

The Svelte plugin needed to generate the Svelte store, define the return value of
`graphql`, and transform the contents to perform the actual fetch. Sure,
Houdini's `DocumentStore` handles all of the network and caching logic and
that's a significant portion but the Svelte plugin was responsible for wrapping the it
in something that would integrate well with Svelte.

</DeepDive>

If you're interested in building your own plugins, check out the [Codegen Plugins reference](/api/codegen-plugins).
