npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@openreachtech/furo-vue

v1.3.2

Published

furo for Vue

Readme

@openreachtech/furo-vue

furo-vue is a library that supports Vue development.

Installation

Requires Node.js ^20.19.2 and npm ^10.9.0 (the versions the CI builds against).

npm install @openreachtech/furo-vue

Getting Started

This guide takes a brand-new project (one that has never used furo-vue) from zero to a rendered component. It targets Nuxt 3 (the primary consumer stack); plain Vue 3 + Vite differs only in how you register components (use app.component(...) or per-component imports instead of a Nuxt plugin).

For AI agents initializing a project: follow the numbered steps below in order. To pick and call components, read the machine-readable manifest at node_modules/@openreachtech/furo-vue/public/furo-vue/components.json and use the furo-vue-components skill (skills/furo-vue-components/SKILL.md).

(1) Import the design tokens (required)

Every component reads CSS custom properties from a single token entry. Import it once in your app. Without it, components render unstyled.

Nuxt — add it to nuxt.config css:

// nuxt.config.js
export default defineNuxtConfig({
  css: [
    '@openreachtech/furo-vue/lib/assets/css/furo.css',
  ],
})

Plain Vue 3 — import it in your entry file:

// main.js
import '@openreachtech/furo-vue/lib/assets/css/furo.css'

(2) Enable light / dark theme

Tokens are defined for both themes and switch off a data-theme attribute on <html>. Set it to light (default) or dark — component CSS responds automatically, no media query needed.

<html data-theme="light">

To toggle at runtime, set the attribute on document.documentElement:

document.documentElement.setAttribute('data-theme', 'dark')

(3) Render your first component

Components are named exports. Import only what you use.

<script>
import {
  FuroButton,
} from '@openreachtech/furo-vue'

export default {
  components: {
    FuroButton,
  },
}
</script>

<template>
  <FuroButton :parcel="{ variant: 'default' }">
    Create record
  </FuroButton>
</template>

To register components globally instead of per-file (optional), create a Nuxt plugin:

// plugins/furo-vue.js
import * as furoVue from '@openreachtech/furo-vue'

export default defineNuxtPlugin(nuxtApp => {
  Object.entries(furoVue)
    .filter(([name]) => name.startsWith('Furo'))
    .forEach(([name, component]) => {
      nuxtApp.vueApp.component(name, component)
    })
})

(4) The component contract

Every form-control component shares one public surface — learn it once, it applies everywhere:

  • Props: parcel (a reactive behavior object) plus v-model:value.
  • Events: most controls emit change-value (on input), commit-value (on blur / enter), and update:value (v-model sync). Not all do — read each component's events array in the manifest. Action components (e.g. FuroButton) emit their own typed payloads.
  • No primitive imports: the public contract is Furo-defined; never import the underlying headless library.
  • Logic in the Context, not the template.
<template>
  <FuroTextField
    v-model:value="form.name"
    :parcel="{ placeholder: 'Full name' }"
    @commit-value="context.onCommitName({ payload: $event })"
  />
</template>

(5) Labeled form fields

Wrap any field atom in FuroControlBlock to add a label, hint, and error message:

<template>
  <FuroControlBlock :parcel="{ label: 'Email', error: context.emailError }">
    <FuroEmailField
      v-model:value="form.email"
      :parcel="{ placeholder: '[email protected]' }"
    />
  </FuroControlBlock>
</template>

(6) Toasts

Mount <FuroToaster /> once near your app root, then call the imperative toast helper from anywhere (client-side only):

<template>
  <FuroToaster />
  <!-- the rest of your app -->
</template>
import {
  toast,
} from '@openreachtech/furo-vue'

toast.show({ title: 'Saved', type: 'success' })

(7) Icons the library does not ship

Icons resolve offline, so FuroIcon draws only the data it holds: the 49 icons the library ships, plus whatever your application registers. Register yours once at start-up, before the first render:

import {
  furoIconRegistry,
} from '@openreachtech/furo-vue/icons'

furoIconRegistry.registerIconSet({
  iconSet: applicationIconSet,
})

A name nothing resolves throws outside a production build, naming the icon, so a missing icon never hides as an empty box. A production build draws the warning glyph instead.

To reach every name rather than registering them one by one, install your own renderer. The registry still answers first, so the library's own icons keep drawing offline whatever you install:

furoIconRegistry.useIconRenderer({
  component: applicationIconComponent,
})

A Nuxt application gets this from the module instead:

// nuxt.config.js
modules: ['@nuxt/icon', '@openreachtech/furo-vue/nuxt']

A plain Vue application gets it from createIconifyRenderer(), exported at @openreachtech/furo-vue/icon-renderers. Full API, including single-icon registration and a lazy resolver: docs/furo-icon.md.

(8) Discover every component

  • Human catalog (grouped by layer, with use cases): docs/COMPONENTS.md
  • Machine-readable manifest (for AI agents and tooling): public/furo-vue/components.json
  • llms.txt: public/furo-vue/llms.txt

Maintainers regenerate these from the doc registry with:

npm run docs:manifest

(9) GraphQL, fetchers, and page templates (out of scope here)

furo-vue ships presentational atoms, molecules, and organisms only. GraphQL launchers, fetcher/submitter adapters, and page-level templates (ListView, DetailView, …) live in the consumer app. See docs/furo-vue/README.md for the scope boundary and docs/furo-vue/architecture.md for layer rules.

(9) Importing logic in a Node / test environment

The main entry (@openreachtech/furo-vue) re-exports Vue SFCs, which a plain Node / CommonJS test runner (e.g. Jest without a Vue transform) cannot parse. When you only need the pure-JS surfaceBaseFuroContext, BaseFuroContextAccessor, the imperative toast helper, toastQueue, ToastQueue — import the logic-only entry, which pulls no .vue files and loads in a jsdom-free Node environment:

import {
  BaseFuroContext,
} from '@openreachtech/furo-vue/lib/index.core.js'

Component (.vue) tests still go through the full entry under a jsdom + Vue transform.

Using with Claude (AI agents)

furo-vue ships machine-readable docs so an AI agent (Claude Code, Cursor, etc.) can scaffold components correctly without guessing the API. After install they live inside the package:

  • node_modules/@openreachtech/furo-vue/public/furo-vue/llms.txt — a compact, link-based index of every component grouped by layer.
  • node_modules/@openreachtech/furo-vue/public/furo-vue/components.json — the full manifest: for each component its import path, props, parcel keys, events, slots, and features.

Point Claude Code at the manifest

Add a pointer in your project's CLAUDE.md (or AGENTS.md) so the agent reads the contract before writing furo-vue code:

## furo-vue component library

When building UI with `@openreachtech/furo-vue`, follow its machine-readable contract:

- Index: `node_modules/@openreachtech/furo-vue/public/furo-vue/llms.txt`
- Full API manifest: `node_modules/@openreachtech/furo-vue/public/furo-vue/components.json`

Contract for every component: pass a reactive `parcel` object plus `v-model:value`,
listen to Furo emits (`change-value`, `commit-value`, `update:value`), and use the
documented slots. Do not reach into the underlying headless primitive.

Ask Claude to load it on demand

In a Claude Code session you can also just say:

Read node_modules/@openreachtech/furo-vue/public/furo-vue/components.json and build a login form using FuroTextField, FuroPasswordField, and FuroButton.

The manifest is regenerated from the doc registry by maintainers with npm run docs:manifest, so it always matches the shipped components.

Add the furo-vue skill (Claude Code)

The repo ships a Claude Code skill, furo-vue-components, that routes a request ("which component for X") to the right component and its contract via the manifest. The skill is not in the npm package, so copy it from the repo into your project's .claude/skills/:

# from a checkout of furo-vue
cp -R skills/furo-vue-components <your-project>/.claude/skills/

# or fetch just the skill file from GitHub
mkdir -p .claude/skills/furo-vue-components
curl -fsSL https://raw.githubusercontent.com/openreachtech/furo-vue/main/skills/furo-vue-components/SKILL.md \
  -o .claude/skills/furo-vue-components/SKILL.md

Claude Code auto-discovers skills under .claude/skills/. Once copied, ask Claude to build UI and it invokes the skill, loads the manifest, and calls components with the correct parcel + v-model:value + emits contract.

Contribution

Bug reports, feature requests, and code contributions are welcome.

Feel free to contact us through GitHub Issues.

git clone https://github.com/openreachtech/furo-vue.git
cd furo-vue
npm install
npm run lint
npm test

License

This project is released under the Apache License 2.0.

For more details, please see in the LICENSE file.

Developer

Open Reach Tech Inc.

Copyright

© 2026 Open Reach Tech Inc.