Skip to content

Getting Started

Pinia's well-designed architecture allows it to be modular while also functioning as a central store. This means that we don't have to register each service's store in a central location. Here's are the recommended steps for setting up Feathers-Pinia:

Install Pinia

Install these packages using your preferred package manager:

pinia feathers-pinia

Install Feathers

If your app will use, install these packages:

@feathersjs/feathers @feathersjs/authentication-client feathers-hooks-common @feathersjs/socketio-client

If your app will use feathers-rest (no realtime connection), install these packages:

@feathersjs/feathers @feathersjs/authentication-client feathers-hooks-common @feathersjs/rest-client

Project Configuration

Vite will work without any configuration. Instructions for Quasar, Nuxt, and Vue CLI are yet to be determined.


By default, TypeScript will expect you to strictly identify properties on Model classes. See the ! in the following example:

class UserModel extends BaseModel {
  foo!: string
  bar!: number

You can optionally configure TypeScript to not require the ! on every property in your tsconfig.json. The strictPropertyInitialization property goes at the top level of the config, and not in the compilerOptions:

  "strictPropertyInitialization": false,
  "compilerOptions": {
    // not in here

With strictPropertyInitialization turned off, you can declare class properties as normal:

// No `!` needed after every property
class UserModel extends BaseModel {
  foo: string
  bar: number


Feathers Client(s)

Feathers-Pinia supports multiple, simultaneous Feathers API servers. The process is the same with one exception: the name of the client must be unique and becomes the alias for that particular API server. Here's an example:

Here's an example client:

// src/feathers.ts
import feathers from '@feathersjs/feathers'
import socketio from '@feathersjs/socketio-client'
import auth from '@feathersjs/authentication-client'
import io from ''
import { iff, discard } from 'feathers-hooks-common'

const socket = io('http://localhost:3030', { transports: ['websocket'] })

// This variable name becomes the alias for this server.
export const api = feathers()
  .configure(auth({ storage: window.localStorage }))

For additional Feathers APIs, export another Feathers client instance with a unique variable name (other than api).

Here's an example that exports a couple of feathers-rest clients:

// src/feathers.ts
import feathers from '@feathersjs/feathers'
import rest from '@feathersjs/rest-client'
import auth from '@feathersjs/authentication-client'

// The variable name of each client becomes the alias for its server.
export const api = feathers()

export const analytics = feathers()


These few lines of code to setup pinia go in /store/store.pinia.ts. The setupFeathersPinia utility wraps defineStore and provides a global configuration (as long as you use the returned defineStore). It's not recommended to use a global configuration, like the below example, in SSR scenarios.


Adding .pinia. to each store's filename will help disambiguate utilities from store setup. If you're upgrading a Vuex app, it helps distinguish which Vuex services haven't been upgraded, yet.

// store/store.pinia.ts
import { createPinia } from 'pinia'
import { setupFeathersPinia } from 'feathers-pinia'
import { api } from '../feathers'

export const pinia = createPinia()

export const { defineStore, BaseModel } = setupFeathersPinia({
  clients: { api },
  idField: 'id',

The above snippet just provided the main pinia instance and a feathers client called api in the clients option. It also set the default idField to id. Now we won't have to set the idField at the service level.

The final step to setup pinia is to add pinia as an app plugin, like this:

// src/main.ts
import { createApp, App as AppType } from 'vue-demi'
import { router } from './routes'
import { pinia } from './store/store.pinia' // import from the file you just created.
import App from './App.vue'

const app = createApp(App)
  .use(pinia) // register pinia as a plugin. This also enables devtools support

Service Stores

Now that we've created the main pinia store, we are ready to setup our first service. Here's an example that creates a User class and connects it to the users service. This next example uses the global configuration, so it won't work well for SSR:

// src/store/users.ts
import { defineStore, BaseModel } from './store.pinia'
import { api } from '../feathers'

export class User extends BaseModel {}

const servicePath = 'users'
export const useUsers = defineStore({ servicePath, Model: User })


Small tweaks are needed for SSR apps:

  1. Import defineStore directly from feathers-pinia.
  2. Pass all options to defineStore
import { defineStore, BaseModel } from 'feathers-pinia' // (1)
import { api } from '../feathers'

export class User extends BaseModel {}

const servicePath = 'users'
export const useUsers = defineStore({
  idField: 'id', // (2)
  clients: { api }, // (2)
  Model: User,


Many thanks go to the Vue, Vuex, Pinia, and FeathersJS communities for keeping software development FUN!