eddev

_app.tsx Layout

Common site layout

views/_app.tsx is the site shell. It wraps every active view, so it is the right place for global providers, headers, footers, scroll restoration, tracking systems, and route-level UI.

import { Footer } from "@components/site/Footer"
import { Header } from "@components/site/Header"
import { ScrollRestoration } from "eddev/routing"
import { defineView } from "eddev/views"

export default defineView("_app", (props) => {
  return (
    <>
      <ScrollRestoration />
      <Header />
      {props.children}
      <Footer />
    </>
  )
})

The children prop is the current route view. Do not query the current page in _app.tsx; that belongs in the view's own .graphql file.

App Data

Add views/_app.graphql for data needed across the whole frontend, such as menus, settings, trackers, or template parts.

query CommonData {
  menus {
    nodes {
      locations
      menuItems {
        nodes {
          label
          url
          parentId
        }
      }
    }
  }
  templateParts {
    siteFooter {
      contentBlocks
    }
  }
}

The result is available in _app.tsx as props, and also through useAppData() anywhere inside the app.

import { ContentBlocks } from "eddev/blocks"
import { useAppData } from "eddev/hooks"

export function Footer() {
  const footer = useAppData((data) => data.templateParts?.siteFooter)

  return <ContentBlocks blocks={footer?.contentBlocks} />
}

On the initial page request, app data is included with the route payload. During normal client-side navigation it is reused, so avoid putting per-page data in _app.graphql.

Manual Route Display

Most projects only need {props.children}. More complex sites can render routes manually with RouteDisplay when they need page transitions, modal routes, drawers, or background routes.

import { Footer } from "@components/site/Footer"
import { Header } from "@components/site/Header"
import { RouteDisplay, useRoute } from "eddev/routing"
import { defineView } from "eddev/views"

export default defineView("_app", () => {
  const route = useRoute()

  return (
    <>
      <Header />
      <RouteDisplay route={route} />
      <Footer />
    </>
  )
})

Only reach for this when the shell needs control over how the active route is displayed. For normal site layouts, keep _app.tsx boring.

App Data Versus View Data

  • Use _app.graphql for global data shared by many routes.
  • Use views/name.graphql for data needed by one view.
  • Use queries/*.graphql and generated hooks for interactive data that changes after the route has rendered.

On this page