# v-runtime-template compiles a Vue template string at runtime

> v-runtime-template is a small Vue component that takes a template string, compiles it in the browser and mounts it against the parent component's scope, so interfaces stored in a database can use component tags and bindings. It requires the with-compiler build of Vue and gives the runtime template access only to the properties of the component that hosts it.

**alexjoverm/v-runtime-template** — Vue component for compiling templates on the fly using a v-html like API

- Repository: https://github.com/alexjoverm/v-runtime-template
- Stars: 601 · Forks: 71
- Language: JavaScript
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/alexjoverm-v-runtime-template

## The case where the template arrives after the build

Vue components are compiled at build time. That model breaks in one specific situation: when the template itself is data rather than source code. A feature that lets a user design their own page, or a backend that stores a template in a database and hands it to the frontend later, has a template string that no bundler ever saw.

v-runtime-template exists for that case. You give the component a template string, it compiles the string in the browser, and it attaches the result to the scope of the component that uses it. The compiled template can then read that component's data, props, methods and computed properties, which is the part that makes it more than a fancy v-html.

The framing in the project description is worth keeping in mind. Think of it as the v-html equivalent that also understands Vue template syntax, where v-html only handles plain HTML. The scope of use is narrow and specific: rendering markup supplied by a user or a server with the same expressiveness as a compiled template, inside an application that already owns the surrounding data.

It is not a general purpose dynamic UI framework. It is one component that compiles a string and mounts it.

## Without the Vue compiler build, the component cannot work

There is a hard prerequisite, and it is the first thing that breaks a new user's setup. Vue ships in two forms, and the default build has no template compiler in it. Compiling a template string at runtime requires the version with the compiler included, and the documentation says so directly.

For a Vue CLI project, the switch is a configuration flag.

```js
// vue.config.js
module.exports = {
  runtimeCompiler: true
};
```

For Nuxt, which does not expose that flag, the documentation shows the webpack alias route instead, pointing vue at the common distribution file.

```js
// nuxt.config.js
{
  build: {
    extend(config, { isDev, isClient }) {
      config.resolve.alias["vue"] = "vue/dist/vue.common";
      // ...
```

The cost of this requirement is real and worth stating plainly. The compiler build is larger than the runtime-only build, and it ships a compiler to every browser that loads your app, whether or not any runtime template is rendered. For a product that uses this component on one route, you are paying that cost everywhere. The documentation offers no guidance on limiting the compiler to a lazily loaded chunk.

## One prop, and the parent scope comes along

The usage is deliberately close to v-html. The component takes a template prop and nothing else.

```html
<template>
	<div>
		<v-runtime-template :template="template"></v-runtime-template>
	</div>
</template>

<script>
import VRuntimeTemplate from "v-runtime-template";
import AppMessage from "./AppMessage";

export default {
  data: () => ({
    name: "Mellow",
    template: `
      <app-message>Hello {{ name }}!</app-message>
    `
  }),
  components: {
    AppMessage,
    VRuntimeTemplate
  }
};
</script>
```

The template string uses a custom component tag, app-message, and that component has to be registered on the host component, since the runtime template resolves tags against the scope it is mounted into. The interpolation in the template reads name from the host's data, which shows the whole point: the markup is stored elsewhere, but it is bound to the code that renders it.

The component is imported from the package name and registered locally. There is no plugin install, no global registration and no configuration object.

## Computed properties and methods are reachable too

Data is not the only thing in scope. The documentation shows a template that also calls a method on a click handler and renders a computed property.

```js
export default {
  data: () => ({
    name: "Mellow",
    template: `
      <div>
        <app-message>Hello {{ name }}!</app-message>
        <button @click="sayHi">Say Hi!</button>
        <p>{{ someComputed }}</p>
      </div>
		`,
  }),
  computed: {
    someComputed() {
      return "Wow, I'm computed";
    },
  },
  methods: {
    sayHi() {
      console.log("Hi");
    },
  },
};
```

So the runtime template behaves like a compiled one for the common cases: interpolation, event bindings, computed values and method calls all work, and the whole thing is reactive because it is mounted against a live component instance rather than against a static string.

That reactivity is also what makes the feature different from server side rendering of a stored template. The template does not get compiled once and inserted as static markup. It is bound to a component that is already running, so later changes to the host's data show up in the rendered output.

## The scope limit is the whole ballgame

The documentation states the limitation without hedging: the template can only access the instance properties of the component that is using it. A linked issue covers the detail.

Read that as a boundary on the data model, not a small caveat. A runtime template can read the host's data, props, computed values and methods, and it can use components registered on the host. It cannot reach a Vuex store, a router instance, a plugin, a mixin or a parent component's state directly, unless the host passes those in as props or exposes them as its own computed properties.

For a product where a user writes a small template that shows a name and a button, that is fine, and the fix is a small wrapper component. For a product where a user writes a template that needs to navigate, call an API, or read global state, every template author has to work through the host component, and the host component grows a computed property per need.

This is also where the security question sits. A runtime template is code that your end users author, and it executes with the privileges of the component that hosts it. The project documentation does not discuss sandboxing or restricting what a runtime template can express, so if untrusted users author templates, that part is yours to solve.

## v-html and dynamic components solve adjacent problems

The project compares itself with two things, and the comparison is honest enough to be useful.

Against v-html: v-html attaches plain HTML to a scope, and it does not understand Vue template syntax. A stored string containing a router-link tag will render as an unknown element under v-html, whereas the runtime component compiles it and resolves the tag. If you only need HTML, the documentation is blunt and says to use v-html, because it ships no compiler and has no scope rules to reason about.

```html
<router-link to="mike-page">Go to Mike page</router-link>
```

Against dynamic components: the `<component>` element renders a component dynamically by binding the `is` prop to a component options object. Those components are usually pre-compiled, so the runtime template case is not covered. The documentation states that the goal can in fact be reached with the component options object form of dynamic components, and that v-runtime-template uses that under the hood in its render function form, along with other common tasks.

That last point is the most useful thing in the comparison section. It means the component is not doing anything Vue cannot do natively, it is packaging a specific pattern, with the scope convenience and the compile step, behind one tag.

## A single component package built with microbundle

The package itself is small. package.json names it v-runtime-template at version 1.10.1, describes it as creating Vue components by compiling templates on the fly, and points main at dist/v-runtime-template.umd.js, with a module entry at dist/v-runtime-template.es.js, a browser field pointing at the same ES build, an unpkg entry at the UMD bundle and TypeScript types at v-runtime-template.d.ts.

```json
  "main": "dist/v-runtime-template.umd.js",
  "module": "dist/v-runtime-template.es.js",
  "unpkg": "dist/v-runtime-template.umd.js",
  "browser": "dist/v-runtime-template.es.js",
  "types": "v-runtime-template.d.ts"
```

The build script runs microbundle on index.js, and microbundle is the only dev dependency. The test script is a placeholder that prints an error and exits, so there is no test suite behind the published package.

The repository itself is correspondingly spare: index.js holds the component, main.js and App.vue and Test.vue are scratch files for local development, vue.config.js carries the runtimeCompiler flag, and dist/ is checked in alongside the sources.

The licence is MIT, so the code can be used in a proprietary product. There are no GitHub releases, so the npm version is the version, and the last push was on 2026-10-06. The project also links to the author's VueDose tips site, which is where the author's Vue tips and ecosystem notes live.

## Conclusion

v-runtime-template fits a product where end users or a backend define markup that must render with real Vue bindings and components, and where the build already ships the with-compiler version of Vue. It does not fit a project still on the runtime-only Vue build, and it does not fit templates that need anything beyond the hosting component's own data, props, methods and computed properties, because the runtime template cannot reach the wider application scope. Before adopting it, confirm your webpack or build configuration exposes the compiler build of Vue, check the scope limitation described in issue 9 against the templates your users will write, and read the version in package.json, which is 1.10.1, against the Vue major version your app runs.

## FAQ

### Why does v-runtime-template need the with-compiler build of Vue?

Because it compiles template strings in the browser at runtime, and the default Vue build ships without a template compiler. The documentation says to use a webpack alias to vue/dist/vue.common, or set runtimeCompiler: true in vue.config.js for a Vue CLI project.

### What can a v-runtime-template template access?

Only the instance properties of the component that uses it, which means its data, props, computed properties and methods. The documentation points to issue 9 for the details of that boundary.

### Should I use v-runtime-template or v-html?

Use v-html when the content is plain HTML, since it needs no compiler and no scope rules. Use v-runtime-template when the stored markup needs Vue template syntax such as custom components, interpolation or event bindings.

### Does v-runtime-template work with Vuex or the router?

The template can only reach the properties of the hosting component, so global stores and the router instance are not directly available. The documentation does not describe a mechanism for exposing them, so the host component would need to pass them in.

## Sources

- [alexjoverm/v-runtime-template on GitHub](https://github.com/alexjoverm/v-runtime-template)
- [Issues](https://github.com/alexjoverm/v-runtime-template/issues)
- [License: MIT](https://github.com/alexjoverm/v-runtime-template/blob/master/LICENSE)
- [README](https://github.com/alexjoverm/v-runtime-template/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/alexjoverm-v-runtime-template
