In this episode you complete the Pinia installation and create the first store: a counter store with a count state and an increment action. You also use that store inside a component, including how to access state and call an action from the template and the script.

The theory in episode 2 is enough. Now it's time to write real code: define the first store and use it in a component. The counter store is Pinia's hello world — small, clear, and it demonstrates the entire flow you'll use in every store that follows.
Episode 3 will guide you from installing Pinia, registering it with the app, creating the counter store, to consuming the store in an SFC component. By the end of the episode, you'll see the number increase on the browser screen — proof that the entire reactivity pipeline works.
Make sure your Vue 3 project with Vite is ready (episode 0). Install Pinia and mount it into the app:
npm i piniaThen open src/main.ts and register Pinia before mount:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')app.use(createPinia()) must be called before app.mount('#app'). This order guarantees Pinia is available when the first components are rendered.
Create the file src/stores/counter.ts. The recommended naming convention: the file name matches the store id, and the store function starts with use:
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
double: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})defineStore('counter', ...) creates a store with the id counter. The count state is initialized to zero, the double getter computes twice the value, and the increment action increases it. Notice that this store hasn't touched any component yet — it's purely a unit of logic.
Inside an SFC component, call the store through the exported function. Vue creates the store instance on first use and caches it:
<script setup lang="ts">
import { useCounterStore } from '@/stores/counter'
const store = useCounterStore()
</script>
<template>
<p>Value: {{ store.count }}</p>
<p>Double: {{ store.double }}</p>
<button @click="store.increment()">Add</button>
</template>const store = useCounterStore() gives you a reactive store instance. The template uses store.count to read state and store.increment() to change it. Every button click increases the value, and store.double updates automatically.
There are three common ways to interact with a store from a component:
store.count — the simplest and still reactive.store.increment() — used when there's mutation logic.const { count } = storeToRefs(store) — to pick specific fields, covered in episode 5.import { useCounterStore } from '@/stores/counter'
import { storeToRefs } from 'pinia'
const store = useCounterStore()
const { count, double } = storeToRefs(store)
function tambahLima() {
store.$patch({ count: store.count + 5 })
}storeToRefs(store) turns state and getters into refs so they can be destructured without losing reactivity. For a simple single update, store.count = 10 directly is easier.
Tip
After creating the store file, save it and check Vue DevTools. The Pinia tab will show the counter store with its state, getters, and action — proof that the store is registered correctly.
In episode 3 you completed the installation setup and created a fully working first store: you installed pinia, registered the instance with the app, defined the counter store, and used it in an SFC component.
Key takeaways:
npm i pinia, then register it with app.use(createPinia()) before mounting.src/stores/<name>.ts and the function use<Name>Store.defineStore block.store.count, call an action with store.increment().storeToRefs when you want destructuring that stays reactive.In the next episode, episode 4, we'll discuss Options Store vs Setup Store — two equally capable styles of writing stores, how to write both with pure Composition API, using composables inside a store, and guidance on when to choose each style. Get your project ready, because we're going to write two versions of the same store.