Portal Architecture
What is a Portal?
A portal is the attendee-facing web experience for a project. Each project can have multiple portals, each with its own custom domain, authentication configuration, pages, widgets, and theme. Portals are how attendees interact with the event — they never see the admin dashboard.
Portals are assembled from plugins: pages provide the content, widgets add global functionality, and themes control the look and feel. Project admins configure all of this through the dashboard.
Portal Hierarchy
Project
└── Portal (attendee.example.com)
├── Pages
│ ├── /register → Registration Form
│ ├── /schedule → Schedule Plugin (v3)
│ ├── /speakers → Speaker Directory Plugin (v2)
│ └── /social → Social Feed Plugin (v1)
├── Widgets
│ ├── Analytics Tracker (head script)
│ ├── Chat Widget (floating overlay)
│ └── Cookie Consent (banner)
├── Theme
│ ├── Public template (login, registration)
│ ├── Private template (authenticated pages)
│ └── Styles (CSS, branding)
└── Domains
├── conference.example.com (primary)
└── register.example.com (redirect → /register)
A single project can have multiple portals — for example, a main attendee portal and a separate VIP portal with different pages and authentication requirements.
Custom Domains
Every portal is served on one or more custom domains. The platform supports two domain types:
| Type | Format | Scope | Example |
|---|---|---|---|
| Wildcard | *.customer.com | Team-level, shared across projects | event1.customer.com, event2.customer.com |
| Single | app.customer.com | Project-level, one portal at a time | register.myevent.com |
How Domain Resolution Works
- Attendee's browser resolves the custom domain to the platform's load balancer
- The platform extracts the hostname from the request
- Looks up the
ProjectPortalDomainrecord by hostname (cached for 60 seconds) - Loads the parent portal with all its configuration, pages, and widgets
- If the domain has a redirect configured, issues a 302 redirect immediately
All custom domains CNAME to a single target, and SSL certificates are automatically provisioned and renewed via GCP Certificate Manager.
Authentication
Portals support 10 authentication methods, each configurable per-portal:
| Method | Description |
|---|---|
| Email/Password | Standard email + password login |
| Phone/Password | Phone number + password login |
| Magic Link | Auto-send magic link on email entry |
| One-Time Password | OTP delivered via email or SMS |
| Link Login | Magic link sent via email or phone |
| SSO (SAML2) | Enterprise single sign-on |
| Badge Scan | QR code or barcode badge scan |
| Kiosk Login | Login code for kiosk devices |
| Reader Access Code | Access code for reader devices (kiosks, print servers) |
| Reader OTP | OTP for reader devices |
Each method can be independently enabled, ordered, and configured per-portal. Methods also support:
- Group-based access control — restrict methods to specific attendee groups (e.g., SSO only for VIPs)
- Inline registration — display a registration form alongside the login method
- Post-auth redirects — send attendees to a specific page after login
Access Codes
Portals have a two-level access code system:
- Portal-level codes — gate the entire portal; attendees must enter a code before seeing any page
- Page-level codes — gate individual pages independently of the portal-level code
Access codes are stored as bcrypt hashes and verified via the session.
How a Portal Loads
When an attendee visits a portal, the request flows through several layers:
1. Domain resolves to portal
│
2. Portal configuration loaded (cached)
│
3. Access code check (portal-level)
│
4. Team context set (multi-tenant isolation)
│
5. Session timeout check
│
6. Page controller resolves content
│
7. Theme applies layout templates + styles
│
8. Navigation renders from portal pages
│
9. Page loads its plugin content (or form)
│
10. Widgets inject globally (scripts, overlays)
│
11. Inertia response sent to Vue 3 SPA
The result is a fully rendered page with the portal's theme, the plugin page's content, and all widgets active.
Pages
Portal pages are polymorphic — they can render two types of content:
Plugin Pages (Apps)
The primary content type. A ProjectPortalPage points to a ProjectPage, which references a PluginPage pinned to a specific version. The version contains the HTML template, CSS, JavaScript, and a dependency manifest.
Plugin content is rendered in a sandboxed context with the portal's theme, settings, and authenticated user data injected as props.
Forms
Registration forms, quizzes, and standard forms can also be served as portal pages. The system detects the form type and renders the appropriate component.
Page Properties
Each portal page carries:
| Property | Purpose |
|---|---|
url_slug | URL path (e.g., /schedule, /register) |
title | Display title in portal navigation |
sort_order | Navigation ordering |
requires_authentication | Whether the page requires login |
access_code_enabled | Whether the page requires an access code |
permission_flags | Permission checks for attendee access |
plain_text_key | Sanctum token for API authorization (auto-generated) |
API Authorization
Each page gets its own Sanctum token, auto-generated when the page is created. This token is passed to the plugin frontend as apiPageAuthId and included in all API calls via the X-Portal-Page-Token header. The token ties API access to the page's declared permissions — plugins can only access data their version explicitly declares in its dependencies.
Widgets
Widgets are persistent UI elements that appear on every portal page. They're designed for global functionality that isn't tied to a specific page.
Common widget types:
- Head scripts — analytics trackers, tag managers
- Floating overlays — chat bubbles, help buttons, notification bells
- Banners — cookie consent, announcements
- Footer components — persistent navigation, branding
Each widget:
- References a
PluginWidgetpinned to a specific version - Has its own Sanctum token (independent of page tokens)
- Carries custom settings, security overrides (CORS/iframe whitelist), and trigger state (show/hide conditions)
Widget data is resolved and shared to the frontend on every portal request.
Themes
Themes control the overall layout and styling of a portal. A PluginTheme provides:
- Public template — layout for unauthenticated pages (login, registration)
- Private template — layout for authenticated pages
- System template — layout for system pages (error pages, access code entry)
- Styles — CSS and JavaScript libraries that apply globally
- Branding — colors, fonts, and visual identity settings
Themes are versioned like other plugins. Projects pin to a specific theme version.
Dashboard Tiles
Tiles are admin-side analytics displays — custom data visualizations that appear on the project dashboard. Unlike pages and widgets (which are attendee-facing), tiles are for project administrators.
A PluginTile provides versioned templates for rendering project data as charts, tables, counters, or other visualizations.
Settings Hierarchy
Configuration flows through a merge hierarchy where more specific settings override broader defaults:
Plugin Version Defaults (set by developer)
└── overridden by → Project Instance Settings (set by admin)
└── overridden by → Portal/Page-Level Settings (set by admin)
This applies to:
- Settings — behavioral configuration
- Styles — CSS overrides
- Language strings — i18n translations
Plugin developers set sensible defaults; project admins customize for their event.
Next Steps
- Plugin System — Deep dive into plugin types, versioning, and the security model
- Platform Overview — GXP philosophy and high-level architecture
- GxP DevKit — Build your first plugin