ViteHub is still experimental. Expect bugs and breaking changes.

Source

Retrieve read-only files, records, and external resources through typed source loaders.

Source owns typed retrieval from read-only origins. Use it when server code needs addressable content from files, globs, markdown, GitHub, MCP resources, or custom loaders without first modeling a persistent Workspace file tree.

Source does not own Workspace placement, Source Sync, Workspace rules, snapshots, or model-facing Source Instructions. Workspace can consume Sources and decide where retrieved items appear in a Workspace File Tree.

Quick start

Install

Terminal
pnpm add @vite-hub/source

Configure

server/sources.ts
import { defineSources, file, registerSources } from '@vite-hub/source'

export const sources = defineSources({
  readme: file('README.md'),
})

registerSources(sources)

Start using it

server/api/readme.get.ts
import '../sources'
import { useSource } from '@vite-hub/source'

export default defineEventHandler(() => {
  return useSource('readme').read('README.md')
})

Public imports

ImportUse
defineSource, defineSources from @vite-hub/sourceType and return one Source or a named Source map.
registerSource, registerSources, clearSources, getRegisteredSource from @vite-hub/sourceManage the process-local Source registry.
useSource from @vite-hub/sourceRead from a registered Source at runtime.
file, glob, github, markdown, mcpResources, custom from @vite-hub/sourceCreate built-in Source loaders.
SourceNotFoundError, SourcePathError, SourceError from @vite-hub/sourceHandle registry, path, and loader failures.
@vite-hub/source/sources/* subpathsImport one loader directly when you want narrower dependencies.

Source, Source Reader, Source Item, loader option, cache, search, and error types are exported from @vite-hub/source.

Register Sources

Use @vite-hub/source when you want a direct retrieval registry.

server/sources.ts
import { defineSources, file, github, registerSources } from '@vite-hub/source'

export const sources = defineSources({
  readme: file('README.md'),
  docs: github({
    repo: 'acme/docs',
    ref: 'main',
    root: 'docs',
    include: ['**/*.md'],
  }),
})

registerSources(sources)

Named Source Loader imports are the public authoring shape. Import the helpers you need directly.

Source has no discovery or Vite Integration by itself. Import the module that registers Sources before calling useSource() in a process.

Source loader options

LoaderKey optionsNuance
file(input)A path string, { path, workspacePath?, mediaType? }, or inline { workspacePath, content, mediaType? }.Reads one file from the Source Context root. workspacePath controls the Source key.
markdown(input)Same options as file(input).Wraps file retrieval with markdown-oriented media type behavior.
glob(options)include, cwd, ignore, dot, followSymlinks, keyCache, prefix.Expands local files with tinyglobby; keyCache: false refreshes keys on each read path.
github(options)repo, ref, root, auth, include, exclude, cache.Retrieves repository archive content. auth can be a token string or a trusted callback.
mcpResources(options)server, include, exclude, path, request, cache.Reads MCP Resource content. server can be a client, client config, or resolver.
custom(source)A Source object.Use when the built-in loaders do not match the origin contract.

Source object contract

A custom Source implements the retrieval behavior directly.

FieldTypeDescription
namestringLoader name used in errors and metadata.
cachefalse or SourceCacheOptionsOptional cache policy.
fingerprintunknownCache identity for origin state.
prepare(ctx)functionOptional prefetch or validation hook.
getKeys(ctx)functionReturns all addressable Source keys.
getItem(key, ctx)functionReturns a SourceItem for one key.
getItems(ctx)functionOptional bulk item reader.
getMeta(key, ctx)functionOptional metadata reader.
search(query, ctx)functionOptional Source search implementation.

SourceContext carries rootDir, optional sourceRootDir, optional Source name, and optional Workspace name. It is supplied by the caller that owns the runtime boundary.

Use it at runtime

Read a Source by name with useSource().

server/api/readme.get.ts
import '../sources'
import { useSource } from '@vite-hub/source'

export default defineEventHandler(async () => {
  const readme = useSource('readme')

  return {
    text: await readme.read('README.md'),
  }
})

Source Reader API

MethodReturns
source.keys()All Source keys.
source.get(key)A SourceItem with content, data, media type, and metadata.
source.read(key, options?)Text by default, or Uint8Array with { encoding: 'binary' }.
source.meta(key)Metadata for one key, when the loader supports it.
source.exists(key)Whether a key exists.
source.list(prefix?)Direct child files and directories below a prefix.
server/api/docs.get.ts
import '../sources'
import { useSource } from '@vite-hub/source'

export default defineEventHandler(async () => {
  const docs = useSource('docs')

  return {
    files: await docs.keys(),
    root: await docs.list(''),
  }
})

Use Sources with Workspace

Use Workspace Source Bindings when retrieved content should appear inside a persistent Workspace file tree.

server/workspaces/docs.ts
import { defineWorkspace, file, github } from '@vite-hub/workspace'

export default defineWorkspace({
  sources: {
    readme: file('README.md'),
    docs: github({
      repo: 'acme/docs',
      root: 'docs',
      mount: 'docs',
      materialize: 'lazy',
    }),
  },
})

The Source Package owns retrieval. The Workspace Package owns Mount placement, Source-Backed Paths, Source Sync Policy, Source Instructions, and Workspace Store reconciliation.

Provider output

@vite-hub/source is a retrieval primitive, not a Vite Integration. It does not generate host output, provider config, or discovered Definitions by itself.

Workspace and other consuming packages can wrap Sources in discovered Definitions, runtime registries, generated metadata, or Provider Output when they need placement, persistence, or deployment wiring.

Production boundaries

Treat Sources as read-only retrieval boundaries. Secrets for private origins should come from Server Env or trusted callbacks, not from model-authored input.

Use Workspace when content needs durable sync, path-scoped rules, diffs, snapshots, or scoped agent visibility. Use Source directly when server code only needs to retrieve and inspect items.

Next steps

Copyright © 2026