feat: Complete fleet — 94 skills across 10+ domains
Pulled ALL skills from 15 source repositories: - anthropics/skills: 16 (docs, design, MCP, testing) - obra/superpowers: 14 (TDD, debugging, agents, planning) - coreyhaines31/marketingskills: 25 (marketing, CRO, SEO, growth) - better-auth/skills: 5 (auth patterns) - vercel-labs/agent-skills: 5 (React, design, Vercel) - antfu/skills: 16 (Vue, Vite, Vitest, pnpm, Turborepo) - Plus 13 individual skills from various repos Mosaic Stack is not limited to coding — the Orchestrator and subagents serve coding, business, design, marketing, writing, logistics, analysis, and more. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
121
skills/pinia/references/advanced-ssr.md
Normal file
121
skills/pinia/references/advanced-ssr.md
Normal file
@@ -0,0 +1,121 @@
|
||||
---
|
||||
name: server-side-rendering
|
||||
description: SSR setup, state hydration, and avoiding cross-request state pollution
|
||||
---
|
||||
|
||||
# Server Side Rendering (SSR)
|
||||
|
||||
Pinia works with SSR when stores are called at the top of `setup`, getters, or actions.
|
||||
|
||||
> **Using Nuxt?** See the [Nuxt integration](advanced-nuxt.md) instead.
|
||||
|
||||
## Basic Usage
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
// ✅ Works - pinia knows the app context in setup
|
||||
const main = useMainStore()
|
||||
</script>
|
||||
```
|
||||
|
||||
## Using Store Outside setup()
|
||||
|
||||
Pass the `pinia` instance explicitly:
|
||||
|
||||
```ts
|
||||
const pinia = createPinia()
|
||||
const app = createApp(App)
|
||||
app.use(router)
|
||||
app.use(pinia)
|
||||
|
||||
router.beforeEach((to) => {
|
||||
// ✅ Pass pinia for correct SSR context
|
||||
const main = useMainStore(pinia)
|
||||
|
||||
if (to.meta.requiresAuth && !main.isLoggedIn) {
|
||||
return '/login'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## serverPrefetch()
|
||||
|
||||
Access pinia via `this.$pinia`:
|
||||
|
||||
```ts
|
||||
export default {
|
||||
serverPrefetch() {
|
||||
const store = useStore(this.$pinia)
|
||||
return store.fetchData()
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
## onServerPrefetch()
|
||||
|
||||
Works normally:
|
||||
|
||||
```vue
|
||||
<script setup>
|
||||
const store = useStore()
|
||||
|
||||
onServerPrefetch(async () => {
|
||||
await store.fetchData()
|
||||
})
|
||||
</script>
|
||||
```
|
||||
|
||||
## State Hydration
|
||||
|
||||
Serialize state on server and hydrate on client.
|
||||
|
||||
### Server Side
|
||||
|
||||
Use [devalue](https://github.com/Rich-Harris/devalue) for XSS-safe serialization:
|
||||
|
||||
```ts
|
||||
import devalue from 'devalue'
|
||||
import { createPinia } from 'pinia'
|
||||
|
||||
const pinia = createPinia()
|
||||
const app = createApp(App)
|
||||
app.use(router)
|
||||
app.use(pinia)
|
||||
|
||||
// After rendering, state is available
|
||||
const serializedState = devalue(pinia.state.value)
|
||||
// Inject into HTML as global variable
|
||||
```
|
||||
|
||||
### Client Side
|
||||
|
||||
Hydrate before any `useStore()` call:
|
||||
|
||||
```ts
|
||||
const pinia = createPinia()
|
||||
const app = createApp(App)
|
||||
app.use(pinia)
|
||||
|
||||
// Hydrate from serialized state (e.g., from window.__pinia)
|
||||
if (typeof window !== 'undefined') {
|
||||
pinia.state.value = JSON.parse(window.__pinia)
|
||||
}
|
||||
```
|
||||
|
||||
## SSR Examples
|
||||
|
||||
- [Vitesse template](https://github.com/antfu/vitesse/blob/main/src/modules/pinia.ts)
|
||||
- [vite-plugin-ssr](https://vite-plugin-ssr.com/pinia)
|
||||
|
||||
## Key Points
|
||||
|
||||
1. Call stores inside functions, not at module scope
|
||||
2. Pass `pinia` instance when using stores outside components in SSR
|
||||
3. Hydrate state before calling any `useStore()`
|
||||
4. Use `devalue` or similar for safe serialization
|
||||
5. Avoid cross-request state pollution by creating fresh pinia per request
|
||||
|
||||
<!--
|
||||
Source references:
|
||||
- https://pinia.vuejs.org/ssr/
|
||||
-->
|
||||
Reference in New Issue
Block a user