---
title: "spa-loading-template.html"
description: "The spa-loading-template.html file defines the loading screen shown while a client-side rendered page initializes."
canonical_url: "https://nuxt.com/docs/4.x/directory-structure/app/spa-loading-template"
---
# spa-loading-template.html

> The spa-loading-template.html file defines the loading screen shown while a client-side rendered page initializes.

When a page is rendered with `ssr: false` (either globally in `nuxt.config` or for specific routes with [`routeRules`](https://nuxt.com/docs/4.x/guide/concepts/rendering#hybrid-rendering)), the server returns an HTML shell without server-rendered application content. Your page content is not visible until the JavaScript bundle has been downloaded, Nuxt plugins have run, and the first page has rendered.

You can fill that gap by adding an `app/spa-loading-template.html` file. Its contents are inserted directly into the HTML returned by the server, so they are visible before the Nuxt client bundle has loaded.

```html [app/spa-loading-template.html]
<!-- https://github.com/barelyhuman/snips/blob/dev/pages/css-loader.md -->
<div class="loader"></div>
<style>
  .loader {
    position: fixed;
    top: 50%;
    left: 50%;
    width: 24px;
    height: 24px;
    margin: -12px 0 0 -12px;
    border: 2px solid #efefef;
    border-top-color: #000;
    border-radius: 50%;
    animation: loader 600ms linear infinite;
  }

  @keyframes loader {
    to { transform: rotate(360deg); }
  }
</style>
```

::warning
This file is plain HTML that is rendered independently of Vue, so you cannot use Vue components or auto-imports in it. Include the styles needed by your loading screen directly in this file rather than relying on your application's stylesheets.
::

::tip
This file only covers the initial load of a client-side rendered page. To show a loading state when navigating between pages, use the [`<NuxtLoadingIndicator>`](https://nuxt.com/docs/4.x/api/components/nuxt-loading-indicator) component.
::

## When It Is Removed

By default, the loading template is rendered next to the Nuxt app root rather than inside it:

```html
<div id="__nuxt"></div>
<div id="__nuxt-loader"><!-- spa-loading-template.html --></div>
```

It stays visible until the first page is ready to render, including asynchronous setup in the page, and is then removed. This avoids a white flash between the loading screen and your page. The wrapper element can be customized with [`app.spaLoaderTag`](https://nuxt.com/docs/4.x/api/nuxt-config#app-spaloadertag) and [`app.spaLoaderAttrs`](https://nuxt.com/docs/4.x/api/nuxt-config#app-spaloaderattrs); keep an `id`, as Nuxt uses it to remove the element.

You can render it inside the app root instead by setting the experimental [`spaLoadingTemplateLocation`](https://nuxt.com/docs/4.x/guide/going-further/experimental-features#spaloadingtemplatelocation) option to `'within'`. In that case, it is removed as soon as Vue mounts the app, so the screen may be blank until the first page is ready to render.

## Configuration

Nuxt looks for `spa-loading-template.html` in the `app/` directory (more precisely, the [`dir.app`](https://nuxt.com/docs/4.x/api/nuxt-config#dir) directory) of your project and of each [layer](https://nuxt.com/docs/4.x/directory-structure/layers).

You can change this with the [`spaLoadingTemplate`](https://nuxt.com/docs/4.x/api/nuxt-config#spaloadingtemplate) option:

- a path (relative to [`srcDir`](https://nuxt.com/docs/4.x/api/nuxt-config#srcdir), which is `app/` by default) to use a different HTML file,
- `true` to use Nuxt's built-in loading screen when no file is found,
- `false` to disable the loading template entirely.

```ts twoslash [nuxt.config.ts]
export default defineNuxtConfig({
  ssr: false,
  spaLoadingTemplate: 'my-loader.html',
})
```

::read-more{to="https://nuxt.com/docs/4.x/guide/concepts/rendering#client-side-rendering"}
::


## Sitemap

See the full [sitemap](https://nuxt.com/sitemap.md) for all pages.
