The useCwa() API
useCwa() returns the singleton Cwa instance injected by the module plugin. In templates you can use $cwa directly. In <script setup> and composables, call useCwa().
// In <script setup>
const cwa = useCwa()
// In templates
$cwa.auth.signedIn.value
The Cwa class has six public sub-services:
| Property | Class | Purpose |
|---|---|---|
cwa.resources | Resources | Read-only view of fetched resource state |
cwa.resourcesManager | ResourcesManager | CRUD operations on resources |
cwa.auth | Auth | Authentication state and actions |
cwa.forms | Forms | Form view state and error access |
cwa.admin | Admin | Edit mode, component stack, admin panel |
cwa.siteConfig | SiteConfig | Site-wide settings from the API |
cwa.resources — Resources
The read-only store view. All values are ComputedRef — they react to resource fetches automatically.
cwa.resources exposes two complementary families of page/pageData getters. Understanding the difference is important for using them correctly:
| Family | Getters | What they return | Requires manifest? | Use for |
|---|---|---|---|---|
| Flat leaf | pageIri, pageDataIri, page, pageData | The page/pageData at the leaf of the current URL — i.e. the innermost, deepest target of the route | No | SEO meta, admin identity, reading article data |
| Depth-aware | pageIriAtDepth(n), pageDataIriAtDepth(n), pageAtDepth(n), pageDataAtDepth(n) | The page/pageData at a specific rendering depth from the manifest | Depths > 0 require a manifest | <CwaPage /> rendering, layout-level access |
The flat leaf getters follow the fetch path to the deepest resource — for a URL like /events/2024/conference, pageIri resolves to the innermost page. The depth-aware methods read the manifest's irisByDepth array — pageIriAtDepth(0) is the outermost page, pageIriAtDepth(2) is two levels deep. These families are complementary, not interchangeable.
Layout
cwa.resources.layout // ComputedRef<CwaCurrentResourceInterface | undefined>
cwa.resources.layoutIri // ComputedRef<string | undefined>
Layout always comes from the depth-0 page regardless of nesting depth.
Flat Leaf Getters
Use these when you need to know what the current URL is about — the page or article the visitor navigated to. They work without a manifest (no pagesDepth requirement) and are what the SEO plugin uses to populate <title> and <meta> tags.
cwa.resources.page // ComputedRef<CwaCurrentResourceInterface | undefined>
cwa.resources.pageIri // ComputedRef<string | undefined>
cwa.resources.pageData // ComputedRef<CwaCurrentResourceInterface | undefined> — defined on dynamic pages only
cwa.resources.pageDataIri // ComputedRef<string | undefined>
cwa.resources.displayPage // ComputedRef — the "identity" page shown in the admin (pageData for dynamic pages, page otherwise)
cwa.resources.displayPageIri
Typical use — reading article data in a page template:
const cwa = useCwa()
const headline = computed(() => cwa.resources.pageData.value?.data?.headline)
const title = computed(() => cwa.resources.pageData.value?.data?.title ?? cwa.resources.page.value?.data?.title)
Page Type Flags
cwa.resources.usesPageTemplate // ComputedRef<boolean> — true when the page is marked isTemplate
cwa.resources.isDataPage // ComputedRef<boolean> — true when a pageData record is active
cwa.resources.isDynamicPage // ComputedRef<boolean> — isDataPage && usesPageTemplate
Depth-Aware Methods
Use these when you need to know what renders at a specific nesting level. They read manifest.irisByDepth[n]. At depth 0 they fall back gracefully to the flat fetch path, but at depth 1 and beyond a manifest is required.
These are used internally by <CwaPage /> to pass the correct IRI to each nesting level — you rarely call them with an explicit depth outside of <CwaPage /> itself.
cwa.resources.depthCount // ComputedRef<number> — number of depth levels in the manifest (minimum 1)
cwa.resources.pageAtDepth(0) // ComputedRef — outermost page resource
cwa.resources.pageAtDepth(1) // ComputedRef — first nested page resource
cwa.resources.pageIriAtDepth(0) // ComputedRef<string | undefined>
cwa.resources.pageDataAtDepth(0) // ComputedRef — pageData at a given depth
cwa.resources.pageDataIriAtDepth(0) // ComputedRef<string | undefined>
Calling without an argument — inside a component rendered by <CwaPage />, omit the depth. The component injects cwa-page-own-depth and the method resolves to the correct level automatically:
// Inside a page template component rendered by <CwaPage /> — no depth arg needed
const pageIri = cwa.resources.pageIriAtDepth() // resolves to own depth
const pageDataIri = cwa.resources.pageDataIriAtDepth() // resolves to own depth
const page = cwa.resources.pageAtDepth()
const pageData = cwa.resources.pageDataAtDepth()
Inject keys provided by <CwaPage />:
| Key | Type | What it contains |
|---|---|---|
cwa-page-own-depth | number | The depth at which the current template is rendered |
cwa-page-depth | number | The depth for a nested <CwaPage /> child (incremented automatically) |
cwa-page-data-iri | ComputedRef<string | undefined> | IRI of the PageData record at the current depth |
cwa-page-data-iri is the most convenient way to access PageData in a template component — no depth arithmetic needed:
import { inject } from 'vue'
import type { ComputedRef } from 'vue'
const pageDataIri = inject<ComputedRef<string | undefined>>('cwa-page-data-iri')
const eventData = computed(() => {
if (!pageDataIri?.value) return null
return cwa.resources.getResource(pageDataIri.value).value
})
Arbitrary Resource Lookup
// Fetch any resource by IRI (returns a ComputedRef tracking that IRI)
const resource = cwa.resources.getResource('/component/titles/018e-...')
resource.value?.data?.title
// All resources currently loaded for this page
cwa.resources.currentResources // { [iri: string]: CwaCurrentResourceInterface }
cwa.resources.currentIds // string[] — IRI list for current page
// Find a component group by its reference name
cwa.resources.getComponentGroupByReference('navigation')
Loading State
cwa.resources.isLoading // ComputedRef<boolean> — true during any primary fetch
cwa.resources.pageLoadProgress // ComputedRef<{ total, complete, percent, resources[] }>
Publishable Helpers
cwa.resources.findPublishedComponentIri(iri) // → published IRI for this draft
cwa.resources.findDraftComponentIri(iri) // → draft IRI for this published resource
cwa.resources.isIriPublishableEquivalent(a, b) // → true when a and b are draft/publish twins
cwa.resources.findAllPublishableIris(iri) // → both IRIs for a publishable resource
cwa.resourcesManager — ResourcesManager
CRUD operations that talk to the API. These are used internally by the admin panel and are available for advanced custom UIs.
Creating Resources
await cwa.resourcesManager.createResource({
endpoint: '/component/titles',
data: { title: 'Hello', uiComponent: 'Title' }
})
Updating Resources
await cwa.resourcesManager.updateResource({
endpoint: '/component/titles/018e-...',
data: { title: 'Updated Title' }
})
Deleting Resources
await cwa.resourcesManager.deleteResource({
iri: '/component/titles/018e-...'
})
Saving (Upsert-style)
saveResource handles both create and update depending on whether the IRI is the NEW_RESOURCE_IRI sentinel:
cwa.resourcesManager.saveResource({ endpoint, data })
Error Management
cwa.resourcesManager.errors // CwaErrorEvent[]
cwa.resourcesManager.hasErrors // boolean
cwa.resourcesManager.addError(event)
cwa.resourcesManager.removeError(id)
cwa.auth — Auth
Authentication state and all user account actions.
State
cwa.auth.signedIn // ComputedRef<boolean>
cwa.auth.user // ComputedRef<CwaUser | undefined>
cwa.auth.roles // ComputedRef<string[]>
cwa.auth.isAdmin // ComputedRef<boolean> — true for ROLE_ADMIN or higher
cwa.auth.status // ComputedRef<CwaAuthStatus> (0=SIGNED_OUT, 1=LOADING, 2=SIGNED_IN)
cwa.auth.hasRole('ROLE_ADMIN') // boolean — check a specific role
Actions
// Sign in with username/password
const result = await cwa.auth.signIn({ username: 'alice@example.com', password: 'secret' })
if (result instanceof FetchError) {
console.error('Login failed', result.statusCode)
}
// Sign out
await cwa.auth.signOut()
// Request a password reset email
await cwa.auth.forgotPassword('alice@example.com')
// Complete a password reset (from link parameters)
await cwa.auth.resetPassword({
username: 'alice',
token: 'abc123',
passwords: { first: 'new_password', second: 'new_password' }
})
// Verify email address (from link parameters)
await cwa.auth.verifyEmail({ username: 'alice', token: 'abc123' })
// Confirm email address change (from link parameters)
await cwa.auth.confirmEmail({ username: 'alice', token: 'abc123', newEmail: 'new@example.com' })
// Re-send verification email
await cwa.auth.resendVerifyEmail('alice')
await cwa.auth.resendVerifyNewEmail('alice')
// Re-hydrate user from the /me endpoint (e.g. after updating profile)
await cwa.auth.refreshUser()
cwa.forms — Forms
Access the structured form view data for Form component resources.
getForm(iri)
Returns a ComputedRef of the structured form view, keyed by field name:
const formView = cwa.forms.getForm('/component/forms/018e-...')
// Access a field's vars
const nameField = formView.value?.['contact[name]']
nameField?.vars.value // current value
nameField?.vars.errors // string[]
nameField?.vars.required // boolean
nameField?.vars.block_prefixes // ['form', 'text', '_contact_name'] — for type-specific rendering
getFormViewErrors(formIri, field)
Convenience computed that returns the error array for a specific field, or undefined if there are none:
const nameErrors = cwa.forms.getFormViewErrors('/component/forms/018e-...', 'contact[name]')
// nameErrors.value → ['This field is required'] or undefined
cwa.admin — Admin
Controls admin edit mode and the component selection stack. Mostly used internally, but exposed for custom admin UIs.
cwa.admin.isEditing.value // boolean — whether the admin panel is open in edit mode
cwa.admin.toggleEdit(true) // open edit mode
cwa.admin.toggleEdit(false) // close edit mode
cwa.admin.toggleEdit() // toggle
cwa.admin.emptyStack() // clear the selected component stack
cwa.admin.emitRedraw() // force re-render of the component overlay
Navigation Guard
The admin tracks unsaved changes and shows a confirmation dialog on navigate:
cwa.navigationDisabled.value // boolean
cwa.adminNavigationGuardFn // pass to router.beforeEach
cwa.siteConfig — SiteConfig
Site-wide settings persisted in the API and cached in the Pinia store.
cwa.siteConfig.config // the resolved config object (ComputedRef via store)
cwa.siteConfig.savedSiteConfig // the server-persisted config (before any unsaved changes)
cwa.siteConfig.isLoading // boolean
// Load or refresh from the API
await cwa.siteConfig.loadConfig()
// Save changed keys (only changed values are PATCHed)
cwa.siteConfig.saveConfig({
siteName: 'My New Site Name',
robotsEnabled: false
})
Top-Level Methods on cwa
These are lower-level fetch primitives. Most application code uses the composables instead.
// Fetch a specific resource by IRI
cwa.fetchResource({ path: '/component/titles/018e-...', isPrimary: false })
// Fetch the route manifest for a given Vue Router route
cwa.fetchRoute(route)
// Generic fetch (used internally)
cwa.fetch(event)
// Cancel the current primary page fetch
cwa.clearPrimaryFetch()
// Get the API Platform documentation (for component metadata)
await cwa.getApiDocumentation()
await cwa.getComponentMetadata(refresh, includePosition)
// Access the resolved API URL
cwa.apiUrlBase // string
// Access the module's nuxt.config registrations
cwa.resourcesConfig // the cwa.resources: {} config object
cwa.layoutsConfig // the cwa.layouts: {} config object
cwa.pagesConfig // the cwa.pages: {} config object
cwa.pageDataConfig // the cwa.pageData: {} config object
Common Patterns
Auth-conditional rendering
Always wrap in <ClientOnly> — auth state is only available after client-side hydration:
<ClientOnly>
<UserMenu v-if="$cwa.auth.signedIn.value" />
<NuxtLink v-else to="/login">Sign in</NuxtLink>
</ClientOnly>
Accessing the current page title
const pageTitle = computed(() =>
cwa.resources.pageData.value?.data?.title
?? cwa.resources.page.value?.data?.title
?? ''
)
Checking load state before rendering
const isReady = computed(() =>
!cwa.resources.isLoading.value && !!cwa.resources.page.value?.data
)