@frontic/nuxt

Nuxt module for Frontic - data fetching composables with smart caching, page routing, and context management
8,386
Install
npm install @frontic/nuxt
Latest Version:1.3.2
Vue:3
License:MIT
Last Updated:Oct 3, 2026
Links: npm
Maintainer: seilex

@frontic/nuxt

Nuxt module for building with the Frontic API and Frontic UI components. Provides auto-imported composables for data fetching with smart caching, page routing, and context management.

Features

  • Smart caching via Pinia Colada - stale-while-revalidate, request deduplication, SSR hydration
  • Type-safe composables - Full TypeScript support with generated types from your Frontic schema
  • Search & filtering - Ready-to-use search state management with filters, sorting, pagination, and infinite scroll
  • Page routing - Dynamic page resolution with automatic redirects and 404 handling
  • Context management - Locale and region switching with cookie persistence
  • Infinite scroll - Bidirectional infinite loading with deep-link support via Pinia Colada's useInfiniteQuery
  • Analytics hooks - Typed frontic:listing:resolved, frontic:search:committed and frontic:page:resolved events for any analytics vendor
  • Built-in proxy - CORS-free API requests through your Nuxt server

Installation

npx nuxi@latest module add @frontic/nuxt

Quick Start

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@frontic/nuxt'],
  frontic: {
    contextDomain: 'demo-shop.com',
  },
})

Generate the Frontic client:

npx @frontic/cli generate

Composables

useFronticPage

Dynamic page routing with automatic redirects and 404 handling:

const { page, data, type, block, alternates } = useFronticPage()

useFronticSearch

Full-featured search with filtering, sorting, and pagination:

const { result, state, searchTerm, filterResult, sortResult, loadNext } = useFronticSearch(
  'ProductSearch',
  {},
  {
    filter: {
      select: ['properties.color', 'properties.size'],
      label: { 'properties.color': 'Color' },
    },
    sorting: {
      label: { 'name:asc': 'Name A-Z', 'price.amount:asc': 'Price: Low to High' },
    },
  }
)

useFronticListing

Simple listing access:

// Second argument is the listing's parameters; query options go in the third
const { listing, status, error } = useFronticListing('CategoryProducts', { categoryKey: 'shoes' }, { query: { limit: 10 } })

useFronticBlock

Fetch single blocks (products, categories):

const { block, status, error } = useFronticBlock('ProductCard', 'product-handle')

Every data composable returns status and error alongside its data, plus refresh and refetch.

useFronticTree

Hierarchical menu trees:

const { items, status } = useFronticTree('CategoryNavigation', { depth: 2 })

useFronticContext

Manage locale and region:

const { contexts, current, update } = useFronticContext()
await update({ region: 'de', locale: 'de-DE' })

The selection is stored against a context token, persisted in the fs-context cookie. Every composable resolves that token and sends it — you do not pass it per call — and it is part of every cache key, so a switch re-keys each active query and the new context's content is fetched. contextKey overrides it for one call, contextKey: false opts a call out so it resolves through the domain alone (useful behind a shared cache), and disableContext: true hands token management to you entirely.

Server routes

useFronticClient is a Nuxt app composable and does not run in Nitro. A server/ route uses createFronticServerClient(event), which resolves the context domain from config, the visitor's token from the request's context cookie, and the request URL from the event — and reports failures on the Nitro frontic:fetch:error hook:

// server/api/stock.get.ts
import { createFronticServerClient } from '@frontic/nuxt/server'

export default defineEventHandler(async (event) => {
  const client = createFronticServerClient(event)
  return await client.listing('ProductSearch', {}, { query: { limit: 5 } })
})

The API secret needs no wiring — the module's Nitro plugin attaches it to every Frontic request the server makes. contextDomain: true (read the active i18n locale) cannot resolve here, since there is no i18n instance in Nitro; pass the domain per call in that setup. The module's disableContext is what decides whether the cookie is read here — a per-instance useFronticContext({ disableContext }) override lives inside the Nuxt app, and a server route cannot see it. Pass contextKey explicitly if your app overrides the module setting and also fetches server-side.

Configuration

export default defineNuxtConfig({
  frontic: {
    // Page routing
    contextDomain: 'demo-shop.com',
    redirectOn301: true,
    throwOn404: true,

    // API proxy
    proxy: true, // or '/api/custom-path'
    fetchApiSecret: process.env.FRONTIC_FETCH_SECRET, // only if the project's Fetch API is protected

    // Sitemap
    sitemap: true,

    // Context cookies
    contextCookieName: 'fs-context',
    contextCookieMaxAge: 31536000,

    // Composables
    composables: true, // or ['page', 'search', 'listing', 'block', 'tree', 'context', 'client']

    // UI components (optional)
    componentsPrefix: '',
    componentDir: '@/components/ui',
  },
})

Sitemap

With sitemap: true, requests to /sitemap.xml (and /sitemapN.xml for split sitemaps) on any locale prefix serve the Frontic sitemap for the matching domain — generated from the Pages marked "Visible in Sitemap". Responses carry the upstream ETag and are cached with stale-while-revalidate. When your config declares domains (sitemap: { domains: [...] }, a contextDomain string, or contextDomain: true with i18n locales carrying contextDomain properties), only those domains are served — other hosts get a 404. With no declared domains the route serves any well-formed forwarded host and the module warns at build time. When @nuxtjs/robots is installed, the sitemap is added to robots.txt automatically. Not compatible with @nuxtjs/sitemap yet — with both installed the option is ignored with a warning.

Multi-locale domains

Frontic resolves scope, region and locale from the domain each request carries. Set contextDomain: true to take it from the locale @nuxtjs/i18n currently has active, instead of hardcoding one:

export default defineNuxtConfig({
  modules: ['@frontic/nuxt', '@nuxtjs/i18n'],

  frontic: {
    contextDomain: true,
  },

  i18n: {
    defaultLocale: 'en',
    locales: [
      { code: 'en', contextDomain: 'demo-shop.com' },
      { code: 'de', contextDomain: 'demo-shop.com/de' },
    ],
  },
})

contextDomain on the locale object is a property you add — the module reads it through i18n's localeProperties, and each value must match a domain configured in your Frontic project. The resolved domain is part of every cache key, so locales never share a cached response.

Per call, any composable accepts contextDomain to override it, and useFronticClient({ contextDomain: false }) sends none at all.

Analytics

Listing, search and page events are announced as typed Nuxt hooks, so any vendor can be wired up in one plugin:

export default defineNuxtPlugin((nuxtApp) => {
  nuxtApp.hook('frontic:listing:resolved', (payload) => {
    if (payload.trigger === 'initial') {
      track('view_item_list', { list: payload.listing, count: payload.resultCount })
    }
  })
})

Hooks are client-only and deduplicated per route entry. Payload types are importable from @frontic/nuxt/types when you factor handlers out of the plugin.

TypeScript

Composable typing comes from your generated client (npx @frontic/cli generate): block, listing and tree names, listing parameters, filter and sort fields, and response types all resolve to your project's schema, and invalid names fail the typecheck. Helper types are available from @frontic/nuxt/types:

import type { ResponseOf, ListingQuery, SortString, FronticClient } from '@frontic/nuxt/types'

Documentation

Full documentation at docs.frontic.com

License

MIT

Related Packages

nuxt-request-context

Provide typed request-specific data to Nuxt before the initial render.

979 1
nuxt-hydration-gate

Mark Nuxt app hydration with a DOM attribute for CSS, scripts, and end-to-end te...

211 0
@verbaly/nuxt

Nuxt integration for Verbaly: zero-config module with per-request locale negotia...

8,706 4
@vitral/nuxt

The Nuxt module for Vitral: the plugin from nuxt.config, auto-imported component...

2,999 3
@nhealth/nutils

Shared Nuxt.js v4 module with components, composables, and utilities

1,159 0

Version History

Version Released Vue License
1.3.2 ^3.0 MIT
1.3.1 ^3.0 MIT
1.3.0 ^3.0 MIT
1.2.0 ^3.0 MIT
1.1.1 ^3.0 MIT