@revenexx/editor
v0.1.3
Published
revenexx hard fork of blökkli — interactive page building experience for Nuxt. Independently versioned; the upstream base of each release is documented in FORK.md.
Readme
@revenexx/editor
The visual page editor for revenexx Revenue Cloud themes — a hard fork of blökkli (live demo), adapted to the revenexx UI and platform. How the fork is maintained, synced with upstream and released is documented in FORK.md.
The editor gives buyers of a theme true WYSIWYG page building: drag & drop
blocks, inline text editing, undo/redo history, comments, a reusable-block
library, templates, multi-language content and a publish workflow. The editor
does not store data — every mutation goes through an adapter to a backend.
In the Revenue Cloud that backend is the pages platform app (apps/pages),
and the reference integration is @revenexx/cover-theme.
Using it in a revenexx theme
1. Install
npm install @revenexx/editor2. Register the module
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@revenexx/editor'],
blokkli: {
itemEntityType: 'block',
defaultLanguage: 'de',
// Where your block components live:
pattern: ['app/components/blokkli/**/*.vue'],
// Your edit adapter (see step 4):
editAdapterPath: 'app/blokkli.editAdapter.ts',
},
})The config key stays
blokkliand all in-app imports go through the generated#blokkli/*aliases — only the package name is revenexx-specific.
3. Write blocks
A block is a Vue component using the defineBlokkli() macro. Props are the
editable fields; options control appearance and show up in the editor toolbar.
<!-- app/components/blokkli/hero/index.vue -->
<script setup lang="ts">
const props = defineProps<{
headline: string
subheadline?: string
}>()
const { options } = defineBlokkli({
bundle: 'hero',
options: {
alignment: {
type: 'radios',
label: 'Alignment',
default: 'left',
options: { left: 'Left', center: 'Center' },
},
},
editor: {
// Props a freshly added block starts with:
mockProps: () => ({ headline: 'Headline' }),
},
})
</script>
<template>
<section :class="options.alignment === 'center' && 'text-center'">
<!-- v-blokkli-editable enables inline editing for this field -->
<h1 v-blokkli-editable:headline>{{ headline }}</h1>
<p v-if="subheadline" v-blokkli-editable:subheadline>{{ subheadline }}</p>
</section>
</template>Nested blocks (sections, grids, accordions) render their children with
<BlokkliField name="items" :list="..." />.
4. The edit adapter
The adapter translates editor actions (add, move, delete, options, publish, comments, …) into backend calls. Don't write one from scratch — copy the reference implementation:
- Adapter:
cover/packages/cover-theme/app/blokkli.editAdapter.ts— full feature surface against the pages app - Backend contract:
apps/pages/README.mdhas the complete adapter-method → endpoint mapping (mutation log with undo/redo, ownership, revisions, comments, library, templates, translations, notifications) - BFF proxy: the browser never calls the pages app directly; a Nitro route
(
/api/blokkli/app/[...path]) forwards calls with tenant context
5. The /admin/ pattern
Live storefront routes never ship editor code. The editor mounts on a dedicated route the cockpit embeds in an iframe:
/admin/edit?page={id}&langcode={lang} ← editor surface (BlokkliProvider)
/preview/{token} ← read-only share preview
/{slug} ← live rendering, zero editor weightThe cockpit hands a short-lived, user-scoped token to the iframe via
postMessage ({ type: 'blokkli:edit-token', token }) or the #token=
fragment; the theme attaches it to every adapter call. See
cover-theme/app/pages/admin/edit.vue + useEditToken.ts.
Development (this repo)
npm install
npm run dev:prepare # generate the .nuxt alias environment (required once)
npm run dev -- --port 3001 # playground with the revenexx theme
npm test # vitest
npm run typecheck # see /typecheck for targeted commandsReleasing & upstream syncs: see FORK.md.
Acknowledgments
blökkli was created by dulnan at Liip (MIT). This fork tracks upstream closely — we pull new releases regularly and replay the revenexx customizations on top.
