Vue SSR Architecture
Owns the full application architecture knowledge: stack, file structure, routing, SSR lifecycle, shared utilities, patterns, and conventions.
Stack
| Layer |
Technology |
| Frontend |
Vue 3.5+ (Composition API) + Pinia 3 + Vue Router 5 |
| SSR |
Vite 7 + renderToString + Express middleware |
| UI |
Vuetify 4 (Material Design 3) + MDI icons (@mdi/js) |
| i18n |
Vue i18n v11 (EN/FR, Composition API legacy: false) |
| Backend |
Express 5 + express-session + session-file-store |
| Database |
MongoDB 7 (native driver, connection pooling) |
| Email |
Nodemailer 8 |
| Sanitization |
DOMPurify 3 |
| Security |
Helmet 8 + CSP (production only) + express-rate-limit + CORS |
| Build |
Vite 7 (client + server bundles) |
| Tests |
Vitest 4 + @vue/test-utils + happy-dom |
| Lint |
ESLint 10 + eslint-plugin-vue + Prettier |
| SCSS |
sass-embedded (modern-compiler API) |
File structure
See references/file-structure.md for the full annotated tree.
Routing — locale-prefixed
All routes prefixed with /:locale(en|fr)/. See references/routing-locale.md.
Layout system
| Layout |
Usage |
Header |
Footer |
| public |
Landing, contact |
Yes |
Yes |
| minimal |
Auth pages |
No |
No |
| app |
Dashboard, account, admin |
Yes |
Yes |
SSR lifecycle
See references/ssr-lifecycle.md.
Shared utilities inventory
| Module |
Exports |
const.js |
BCRYPT_ROUNDS, SECURITY_CODE_EXPIRY_MS, LOCALES, USER_SAFE_PROJECTION, EMAIL_REGEX, isAdmin() |
dbHelpers.js |
parseObjectId(), parsePagination(), findUserSafe(), getUserWithCounts() |
email.js |
generateSecurityCode(), hashCode(), verifyCode(), sendSecurityCodeEmail(), sendContactEmail() |
security.js |
getClientIp(), isIpBlocked(), recordLoginIp(), destroyUserSessions() |
api.js |
apiFetch() — client fetch wrapper (AbortController 15s, rate-limit detection) |
mongo.js |
connectDB(), getDB(), closeDB() — connection pooling + ensureIndexes |
analytics.js |
Google Analytics gtag injection (SSR head, GA_MEASUREMENT_ID) |
captcha.js |
Server-side reCAPTCHA v3 verification |
utils.js |
escapeHtml() |
log.js |
logInfo(), logWarn(), logError(), logDebug() |
logger.js |
logEvent(db, event, meta) — MongoDB events collection |
Key patterns
Adding an API endpoint
export function setupMyFeatureRoute(app, db) {
app.post('/api/my-feature', async (req, res) => {
try {
res.json({ status: 'success', data });
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Server error' });
}
});
}
Register in src/api/router.js.
Adding a view
- Create
src/views/MyPage/MyPageView.vue + MyPageView.scss
- Add route to
localeRoutes in src/router.js
- Add i18n keys in
en.json + fr.json
- Use
useLocalePath() for navigation links
Naming conventions
- Components: PascalCase (TheHeader, AdminUsersView)
- Stores: useXStore (useAuthStore)
- API: setupXRoute(app, db)
- Views: XView.vue in views/X/
- SCSS: XView.scss alongside XView.vue
- Composables: useX.js
Vuetify gotchas
- Typography: MD3 classes (text-headline-small, text-title-medium)
- Icon prop: Use
:icon="mdiXxx" (bound), import from @mdi/js
- CSS reset removed: Vuetify 4 no longer resets CSS
- v-list-item to: Works like router-link, use
:to="localePath('/path')"
Environment variables
See references/env-vars.md.
Where to look
Source: e-xode/vue-ssr — distributed by TomeVault.
1---2name: e-xode-vue-ssr-vue-ssr-architecture3description: Vue SSR Architecture4---56# Vue SSR Architecture78> Owns the full application architecture knowledge: stack, file structure, routing, SSR lifecycle, shared utilities, patterns, and conventions.910## Stack1112| Layer | Technology |13| ------------ | ------------------------------------------------------------ |14| Frontend | Vue 3.5+ (Composition API) + Pinia 3 + Vue Router 5 |15| SSR | Vite 7 + renderToString + Express middleware |16| UI | Vuetify 4 (Material Design 3) + MDI icons (@mdi/js) |17| i18n | Vue i18n v11 (EN/FR, Composition API legacy: false) |18| Backend | Express 5 + express-session + session-file-store |19| Database | MongoDB 7 (native driver, connection pooling) |20| Email | Nodemailer 8 |21| Sanitization | DOMPurify 3 |22| Security | Helmet 8 + CSP (production only) + express-rate-limit + CORS |23| Build | Vite 7 (client + server bundles) |24| Tests | Vitest 4 + @vue/test-utils + happy-dom |25| Lint | ESLint 10 + eslint-plugin-vue + Prettier |26| SCSS | sass-embedded (modern-compiler API) |2728## File structure2930See [references/file-structure.md](./references/file-structure.md) for the full annotated tree.3132## Routing — locale-prefixed3334All routes prefixed with `/:locale(en|fr)/`. See [references/routing-locale.md](./references/routing-locale.md).3536## Layout system3738| Layout | Usage | Header | Footer |39| ------- | ------------------------- | ------ | ------ |40| public | Landing, contact | Yes | Yes |41| minimal | Auth pages | No | No |42| app | Dashboard, account, admin | Yes | Yes |4344## SSR lifecycle4546See [references/ssr-lifecycle.md](./references/ssr-lifecycle.md).4748## Shared utilities inventory4950| Module | Exports |51| -------------- | --------------------------------------------------------------------------------------------- |52| `const.js` | BCRYPT_ROUNDS, SECURITY_CODE_EXPIRY_MS, LOCALES, USER_SAFE_PROJECTION, EMAIL_REGEX, isAdmin() |53| `dbHelpers.js` | parseObjectId(), parsePagination(), findUserSafe(), getUserWithCounts() |54| `email.js` | generateSecurityCode(), hashCode(), verifyCode(), sendSecurityCodeEmail(), sendContactEmail() |55| `security.js` | getClientIp(), isIpBlocked(), recordLoginIp(), destroyUserSessions() |56| `api.js` | apiFetch() — client fetch wrapper (AbortController 15s, rate-limit detection) |57| `mongo.js` | connectDB(), getDB(), closeDB() — connection pooling + ensureIndexes |58| `analytics.js` | Google Analytics gtag injection (SSR head, GA_MEASUREMENT_ID) |59| `captcha.js` | Server-side reCAPTCHA v3 verification |60| `utils.js` | escapeHtml() |61| `log.js` | logInfo(), logWarn(), logError(), logDebug() |62| `logger.js` | logEvent(db, event, meta) — MongoDB events collection |6364## Key patterns6566### Adding an API endpoint6768```js69export function setupMyFeatureRoute(app, db) {70 app.post('/api/my-feature', async (req, res) => {71 try {72 res.json({ status: 'success', data });73 } catch (err) {74 console.error(err);75 res.status(500).json({ error: 'Server error' });76 }77 });78}79```8081Register in `src/api/router.js`.8283### Adding a view84851. Create `src/views/MyPage/MyPageView.vue` + `MyPageView.scss`862. Add route to `localeRoutes` in `src/router.js`873. Add i18n keys in `en.json` + `fr.json`884. Use `useLocalePath()` for navigation links8990### Naming conventions9192- Components: PascalCase (TheHeader, AdminUsersView)93- Stores: useXStore (useAuthStore)94- API: setupXRoute(app, db)95- Views: XView.vue in views/X/96- SCSS: XView.scss alongside XView.vue97- Composables: useX.js9899## Vuetify gotchas1001011. Typography: MD3 classes (text-headline-small, text-title-medium)1022. Icon prop: Use `:icon="mdiXxx"` (bound), import from `@mdi/js`1033. CSS reset removed: Vuetify 4 no longer resets CSS1044. v-list-item to: Works like router-link, use `:to="localePath('/path')"`105106## Environment variables107108See [references/env-vars.md](./references/env-vars.md).109110## Where to look111112| If you need… | Read |113| ----------------------------- | -------------------------------------------------------------- |114| Full file tree | [references/file-structure.md](./references/file-structure.md) |115| Route table and locale system | [references/routing-locale.md](./references/routing-locale.md) |116| SSR build and render cycle | [references/ssr-lifecycle.md](./references/ssr-lifecycle.md) |117| API endpoint patterns | [references/api-patterns.md](./references/api-patterns.md) |118| Environment variables list | [references/env-vars.md](./references/env-vars.md) |119120---121> Source: [e-xode/vue-ssr](https://github.com/e-xode/vue-ssr) — distributed by [TomeVault](https://tomevault.io).122<!-- tomevault:4.0:skill_md:2026-05-24 -->