# Vue and Nuxt

> A client-only component that draws the answer after it mounts, in Nuxt 4 or any Vue 3 app.

```sh
npm install @morphscreen/web
```

The core runs in the browser. In Nuxt, a component named `*.client.vue` renders only there, and `onMounted` runs after its element exists.

## Serve the core

Copy `morphscreen.wasm` into `public/` before each build:

```js
// Copies the core out of the package into public/, where the app serves it
// and loadCore("/morphscreen.wasm") fetches it. Run before each build.
import { copyFileSync, mkdirSync } from "node:fs";
import { createRequire } from "node:module";

const require = createRequire(import.meta.url);
mkdirSync("public", { recursive: true });
copyFileSync(require.resolve("@morphscreen/web/morphscreen.wasm"), "public/morphscreen.wasm");
```

## The stylesheet

```ts
export default defineNuxtConfig({
  css: ["@morphscreen/web/morphscreen.css"],
  telemetry: false,
});
```

## The answer

```vue
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { createAnswer, loadCore } from "@morphscreen/web";
import { SAMPLE } from "../sample";

const el = ref<HTMLElement | null>(null);

onMounted(async () => {
  const core = await loadCore("/morphscreen.wasm");
  const answer = createAnswer(el.value!, { core });
  // Your server's stream goes here; this feeds a saved answer in pieces.
  for (let i = 0; i < SAMPLE.length; i += 24) {
    answer.push(SAMPLE.slice(i, i + 24));
    await new Promise((r) => setTimeout(r, 10));
  }
  answer.end();
  document.body.dataset.done = "yes";
});
</script>

<template>
  <div ref="el" />
</template>
```

```vue
<template>
  <main>
    <!-- The answer draws in the browser; the page around it renders on the server. -->
    <MorphAnswer />
  </main>
</template>
```

In a Vue app with Vite but no Nuxt, import the core's address the way the [Plain JavaScript](/docs/integrations/vanilla) page does (`@morphscreen/web/morphscreen.wasm?url`) instead of copying the file.
