IntraVox Architecture¶
IntraVox is a modern intranet application for Nextcloud that provides SharePoint-like content management capabilities. This document describes the technical architecture.
System Overview¶
+------------------------------------------------------------------+
| Nextcloud Server |
| +--------------------------------------------------------------+ |
| | IntraVox App | |
| | +----------------+ +----------------+ +----------------+ | |
| | | Vue.js SPA | | PHP Backend | | GroupFolder | | |
| | | (Frontend) |->| (API + Logic) |->| Integration | | |
| | +----------------+ +----------------+ +----------------+ | |
| +--------------------------------------------------------------+ |
| | |
| v |
| +--------------------------------------------------------------+ |
| | IntraVox GroupFolder | |
| | +------------+ +------------+ +------------------------+ | |
| | | Pages | | Navigation | | Images & Attachments | | |
| | | (JSON) | | (JSON) | | (files) | | |
| | +------------+ +------------+ +------------------------+ | |
| +--------------------------------------------------------------+ |
+------------------------------------------------------------------+
Design Principles¶
Organizational communication, not personal productivity¶
IntraVox is an organizational communication platform — it publishes company news, team updates, shared resources, and data from external systems to a broad audience. This is fundamentally different from the Nextcloud Dashboard, which is a personal productivity overview showing each user their own mail, tasks, files, and notifications.
This distinction extends to external system integrations. Many systems that IntraVox connects to — OpenProject, Jira, Canvas LMS, Moodle — also have dedicated Nextcloud integration apps. These serve different purposes:
| Nextcloud integration apps | IntraVox Feed Widget | |
|---|---|---|
| Audience | Individual user (my tasks, my files) | Team or department (shared overview) |
| Purpose | Take action (link files, create items) | Build awareness (see what's happening) |
| Context | Dashboard widget, search, file sidebar | Embedded in intranet page alongside news, calendar, people |
| Visibility | Only the authenticated user | Everyone with page access, including public shares |
| Data scope | Personal (security-trimmed per user) | Organizational (shared view or per-user via OAuth/OIDC) |
These are complementary, not competing. An organization can use integration_openproject for individual developers to link Nextcloud files to work packages, while simultaneously using IntraVox's Feed Widget to show a project status overview on a department intranet page — visible to managers, stakeholders, and team members who don't have OpenProject accounts.
See the Feed Widget documentation for detailed guidance on when to use which approach.
Technology Stack¶
| Layer | Technology |
|---|---|
| Frontend | Vue.js 3, Vue Router, Pinia (state management) |
| Backend | PHP 8.x, Nextcloud App Framework |
| Storage | Nextcloud Files API, GroupFolders |
| Permissions | GroupFolder ACL, Nextcloud Permissions |
| Build | Webpack, npm |
| i18n | Nextcloud L10N, Transifex |
Directory Structure¶
intravox/
├── appinfo/
│ ├── info.xml # App metadata
│ └── routes.php # API route definitions
├── css/
│ └── *.css # Stylesheets
├── img/
│ └── *.svg # App icons
├── js/
│ └── *.js # Compiled JavaScript (build output)
├── l10n/
│ ├── *.js # Compiled translations
│ └── *.json # Translation source files
├── lib/
│ ├── Controller/ # API Controllers
│ │ ├── ApiController.php
│ │ ├── FooterController.php
│ │ ├── NavigationController.php
│ │ └── PageController.php
│ ├── Service/ # Business Logic
│ │ ├── FooterService.php
│ │ ├── NavigationService.php
│ │ ├── PageService.php
│ │ ├── PermissionService.php
│ │ └── SetupService.php
│ └── AppInfo/
│ └── Application.php
├── src/
│ ├── components/ # Vue components
│ ├── views/ # Page views
│ ├── stores/ # Pinia stores
│ ├── App.vue # Root component
│ └── main.js # Entry point
├── templates/
│ └── index.php # Main template
└── demo-data/
├── nl/ # Dutch demo content
├── en/ # English demo content
├── de/ # German demo content
└── fr/ # French demo content
Core Components¶
Backend Services¶
PageService¶
Handles page CRUD operations: - Load pages from JSON files - Save page content - Manage page hierarchy (nested pages) - Image and attachment handling
NavigationService¶
Manages the navigation structure: - Load/save navigation configuration - Support for megamenu and dropdown navigation types - Multi-level navigation items
FooterService¶
Handles footer content per language.
PermissionService¶
Integrates with GroupFolder permissions: - Read permissions from GroupFolder ACL - Check user access to specific paths - Filter content based on permissions
SetupService¶
Handles initial app setup: - Creates IntraVox GroupFolder if not exists - Initializes folder structure
Frontend Components¶
App.vue¶
Main application shell with: - Navigation component - Router view for page content - Footer component
Navigation.vue¶
Renders the navigation menu: - Megamenu support - Dropdown menus - Language switcher - Mobile responsive
PageView.vue¶
Displays page content: - Renders widgets (text, images, links, etc.) - Edit mode with drag-and-drop - Row and column layouts
PageEditor.vue¶
WYSIWYG page editor: - Widget palette - Drag-and-drop widget placement - Real-time preview - Save/cancel functionality
Data Model¶
Page Structure (JSON)¶
{
"uniqueId": "page-uuid-here",
"title": "Page Title",
"language": "en",
"layout": {
"columns": 1,
"rows": [
{
"columns": 2,
"backgroundColor": "",
"widgets": [
{
"type": "heading",
"column": 1,
"order": 1,
"content": "Welcome",
"level": 1
},
{
"type": "text",
"column": 1,
"order": 2,
"content": "Page content here..."
}
]
}
],
"sideColumns": {
"left": { "enabled": false, "widgets": [] },
"right": { "enabled": false, "widgets": [] }
}
}
}
Widget Types¶
| Type | Description |
|---|---|
| heading | H1-H6 headings |
| text | Rich text content (Markdown) |
| image | Image with alt text, optional clickable link (internal page or external URL) |
| video | Embedded video from YouTube, Vimeo, PeerTube, or local upload |
| links | Link collection (cards or list) |
| divider | Horizontal separator |
Navigation Structure (JSON)¶
{
"type": "megamenu",
"items": [
{
"id": "nav_home",
"title": "Home",
"uniqueId": "page-uuid",
"url": null,
"target": null,
"children": []
}
]
}
API Endpoints¶
Pages¶
GET /api/page/{uniqueId}- Get page by IDPUT /api/page/{uniqueId}- Update pagePOST /api/page- Create new pageDELETE /api/page/{uniqueId}- Delete pageGET /api/pages/{language}- List pages for language
Navigation¶
GET /api/navigation/{language}- Get navigationPUT /api/navigation/{language}- Update navigation
Footer¶
GET /api/footer/{language}- Get footerPUT /api/footer/{language}- Update footer
Setup¶
GET /api/setup- Check setup statusPOST /api/setup- Run setup
File Storage¶
All content is stored in the IntraVox GroupFolder:
IntraVox/
├── {language}/
│ ├── navigation.json
│ ├── footer.json
│ ├── home.json
│ ├── _media/
│ │ └── *.jpg, *.png, *.mp4, ...
│ └── {section}/
│ ├── {page}.json
│ ├── _media/
│ └── {subpage}/
│ └── ...
The _media/ folder stores images, videos, and other media files. Local video uploads are stored here alongside images.
Benefits of File-based Storage¶
- Version control through Nextcloud versioning
- Easy backup and migration
- No database tables required
- Content editable via Nextcloud Files app
- Integrates with Nextcloud sharing
Multi-language Support¶
IntraVox supports multiple languages: - Each language has its own folder structure - Navigation and footer are per-language - Pages can link to translations via uniqueId - UI translations via Nextcloud L10N system
Permission Model¶
See AUTHORIZATION.md for detailed permission documentation.
Key points: - Uses GroupFolder permissions - Supports ACL for fine-grained control - Permissions checked at API and UI level - Navigation filtered based on access
Scalability & Performance¶
IntraVox uses a multi-layer caching strategy and resilience patterns to support large deployments (up to 10k users, 5k pages):
- Distributed caching (Redis/APCu) for page trees, feed results, and people filter results
- Singleflight locks to prevent thundering herd on external feed sources
- Circuit breaker to handle failing external sources gracefully
- Background feed refresh via Nextcloud cron to keep caches warm
- Page metadata database index for fast listing, tree, and search operations
- Bundle splitting (217 KB main + lazy-loaded editor and widgets)
- Progressive rendering in tree components (50 items per batch)
Rate limiting, audit logging, GDPR user deletion, and a health check endpoint provide enterprise-grade operational security.
See Scalability & Enterprise Readiness for full details.
Build Process¶
# Install dependencies
npm install
# Development build with watch
npm run dev
# Production build
npm run build
# Create release tarball
./create-release.sh
Deployment¶
See README.md for installation instructions. Key steps: 1. Install via Nextcloud App Store or manually 2. Enable the app 3. GroupFolder "IntraVox" is created automatically 4. Add groups to the GroupFolder 5. Import demo data or start creating pages
Integration Points¶
MetaVox Integration¶
IntraVox can integrate with MetaVox for enhanced navigation: - Respects MetaVox department structure - Uses MetaVox nav color settings - Syncs navigation styles
GroupFolders¶
- Automatic GroupFolder creation
- ACL permission reading
- File storage within GroupFolder
Nextcloud Features¶
- Uses Nextcloud theming (colors, logo)
- Integrates with Nextcloud Files
- Supports Nextcloud versioning
- Uses Nextcloud authentication