Views

The wippy/views module provides a virtual page and component system with template rendering, resource management, and environment variable mapping. Pages can be backed by Jet templates or external components (SPAs, micro-frontends).

Setup

Add the module to your project:

wippy add wippy/views
wippy install

Declare the dependency:

version: "1.0"
namespace: app

entries:
  - name: dep.views
    kind: ns.dependency
    component: wippy/views
    version: "*"
    parameters:
      - name: api_router
        value: app:api.public
      - name: api_url_env
        value: PUBLIC_API_URL
Parameter Required Default Description
api_router yes HTTP router for view API endpoints
api_url_env no PUBLIC_API_URL Env var containing the public API URL

Template Pages

Template pages render server-side using Jet templates:

entries:
  - name: contact_page
    kind: template.jet
    meta:
      type: view.page
      name: contact
      title: Contact Us
      icon: mail
      order: 5
      group: main
      group_icon: layout-grid
      group_order: 1
      announced: true
      secure: false
    data:
      set: app.templates:default
      data_func: app:contact_data
      resources:
        - contact_styles

Page Metadata

Field Type Default Description
meta.type string Must be view.page
meta.name string entry name Page identifier
meta.title string Display title
meta.icon string Icon identifier
meta.order number 9999 Sort order within group
meta.group string Group category
meta.group_icon string Group icon
meta.group_order number 9999 Group sort order
meta.group_placement string "default" Placement: "default", "sidebar"
meta.secure boolean false Requires authentication
meta.public boolean false Publicly accessible
meta.announced boolean = public Show in navigation
meta.inline boolean false Hidden from UI
meta.content_type string text/html Response MIME type
meta.parent string Parent page ID

Template Data

Field Description
data.set Template set registry ID
data.data_func Function ID that returns page data
data.resources Array of resource registry IDs

The data_func receives { params, query } and returns a table that becomes the data context in the template.

Rendering Pipeline

  1. Load page from registry
  2. Check access (security)
  3. Call data_func if defined
  4. Collect resources: globals + template set resources + page-specific resources
  5. Load environment variables
  6. Render Jet template with context: { data, resources, query_params, route_params, env }

Component Pages

Component pages point to external applications (SPAs, micro-frontends):

entries:
  - name: dashboard
    kind: registry.entry
    meta:
      type: view.page
      name: dashboard
      title: Dashboard
      icon: chart-bar
      url: https://cdn.example.com/dashboard/
      secure: true
      announced: true
    data:
      proxy:
        enabled: true
        css:
          prime_vue: true
          theme_config: true
        tailwind_config: true

The API returns a component descriptor with the base URL and proxy configuration. The frontend renders the component in an iframe or inline.

Component Fields

Field Type Default Description
meta.url string Public URL of the component
meta.entry_point string index.html (pages), index.js (components) Entry file

Proxy Configuration

The proxy controls what CSS and behavior is injected into the component:

Option Default Description
proxy.enabled true Enable proxy wrapper
proxy.css.fonts true Inject font styles
proxy.css.theme_config true Inject theme variables
proxy.css.iframe true Iframe-specific styles
proxy.css.prime_vue false PrimeVue component styles
proxy.css.markdown false Markdown rendering styles
proxy.css.custom_css false Custom CSS
proxy.css.custom_variables false Custom CSS variables
proxy.tailwind_config false Inject Tailwind config
proxy.resize_observer true Auto-resize iframe
proxy.prevent_link_clicks true Intercept link navigation
proxy.iconify_icons false Load Iconify icon set

View Components

Standalone components that are not pages (no navigation entry):

entries:
  - name: widget
    kind: registry.entry
    meta:
      type: view.component
      name: chat-widget
      title: Chat Widget
      url: https://cdn.example.com/chat-widget/
    data:
      proxy:
        enabled: true

Components use meta.type: view.component instead of view.page. They default to index.js as entry point.

Resources

Resources are CSS, JS, and font files associated with pages:

entries:
  - name: global_styles
    kind: registry.entry
    meta:
      type: view.resource
      name: Global Styles
      resource_type: style
      global: true
      order: 1
      url: https://cdn.example.com/global.css

  - name: app_script
    kind: registry.entry
    meta:
      type: view.resource
      name: App Script
      resource_type: script
      template_set: app.templates:default
      order: 10
      url: https://cdn.example.com/app.js
      defer: true

Resource Fields

Field Type Description
meta.type string Must be view.resource
meta.resource_type string "style", "script", "font"
meta.order number Sort order within type
meta.global boolean Applied to all pages
meta.template_set string Specific to a template set
meta.url string Resource URL
meta.integrity string SRI hash
meta.crossorigin string "anonymous" or "use-credentials"
meta.media string CSS media query
meta.defer boolean Deferred script loading
meta.async boolean Async script loading

Resource Collection

Resources are collected in three layers, merged in order:

  1. Global resourcesglobal: true, applied to all pages
  2. Template set resources — matched by template_set ID
  3. Page resources — listed in data.resources array

Within each layer, resources are grouped by resource_type and sorted by order.

Environment Variable Mapping

The env loader maps environment variables to template context keys through a priority-based system.

Defining Mappings

entries:
  - name: app_env
    kind: registry.entry
    meta:
      type: view.env_mapping
      priority: 20
    data:
      mappings:
        api_endpoint: API_BASE_URL
        app_title: APP_NAME
        debug_mode: DEBUG_ENABLED

Each mapping entry associates context keys (used in templates as env.api_endpoint) with environment variable names.

Priority System

Range Category Description
0–9 Framework defaults Built-in framework mappings
10–19 System overrides System-level configuration
20–29 Application mappings Application-specific mappings
30–100 Environment overrides Runtime overrides

Higher priority wins when multiple mappings define the same context key.

Using in Templates

Resolved environment values are available in the env context object:

<script>
    window.API_URL = "{{ env.api_endpoint }}";
    document.title = "{{ env.app_title }}";
</script>

HTTP API Endpoints

The views module registers these endpoints on the configured router:

Method Path Description
GET /pages/list List accessible, announced pages
GET /components/list List view components
GET /pages/content/{id} Render page or return component descriptor
GET /pages/public/{id} Get component base URL

Render Response

For template pages, returns rendered HTML with the page's content_type.

For component pages, returns a descriptor:

{
    "name": "dashboard",
    "version": "1.0.0",
    "specification": "wippy-component-1.0",
    "title": "Dashboard",
    "baseUrl": "https://cdn.example.com/dashboard/",
    "wippy": {
        "type": "page",
        "path": "index.html",
        "proxy": {
            "enabled": true,
            "injections": {
                "css": { "fonts": true, "themeConfig": true, "iframe": true },
                "tailwindConfig": false,
                "resizeObserver": true,
                "preventLinkClicks": true
            }
        }
    }
}

Access Control

Pages with secure: true require authentication. The page registry checks security.can("view", "page:<page_id>") against the current actor and scope.

Non-secure pages are always accessible. The announced flag controls visibility in navigation listings without affecting access.

ID Qualification

Relative IDs in page definitions are qualified with the entry's namespace:

# In namespace "app"
data:
  data_func: my_data_func       # resolves to app:my_data_func
  set: templates:default         # stays as templates:default (already qualified)
  resources:
    - page_styles                # resolves to app:page_styles

See Also