# WPNuxt 2.0: Type-Safe Headless WordPress for Nuxt 4 Source: [vernaillen.dev/blog/wpnuxt-v2](https://vernaillen.dev/blog/wpnuxt-v2) WPNuxt 2.0 brings type-safe composables, multi-layer caching, Gutenberg block rendering, and full authentication to headless WordPress with Nuxt. After 16 alpha releases, 7 betas, and over 700 commits, it's ready for production. WPNuxt connects WordPress with Nuxt via GraphQL, generating typed composables from your queries so you can fetch and render WordPress content without writing boilerplate. Version 2 adds the features that were missing to make this a complete solution for production headless WordPress sites. - **Type-safe composables** generated from GraphQL queries with full autocomplete - **Three-layer caching** — server (Nitro SWR), client deduplication, and SSR payload - **Gutenberg block rendering** with 10 built-in Vue components - **Authentication** with password, OAuth, and external provider support - **AI-powered development** via MCP server integration - **Serverless-ready** — no jsdom, works on Vercel out of the box - **SSG support** — full static site generation with prerender route fetching - **GraphQL mutations** — generated `useMutation*()` composables alongside queries WPNuxt v1 worked as a single module wrapping `nuxt-graphql-middleware`, but it had gaps: no built-in caching strategy, no authentication, and serverless deployments on Vercel broke due to jsdom in the server bundle. Version 2 fills those gaps. Three packages (`@wpnuxt/core`, `@wpnuxt/blocks`, `@wpnuxt/auth`) ship from a unified monorepo with synchronized versions, shared testing infrastructure, and a CI compatibility matrix covering multiple WordPress and Nuxt versions. Upgrading from v1? The MCP server includes a `wpnuxt_migrate` tool that scans your project and guides you through the changes. See [breaking changes](https://vernaillen.dev/#breaking-changes) below. --- ## Composable API The composable API is cleaner in v2. The configurable prefix is gone — all composables use a consistent `use` naming convention. The separate `useAsync*` composables are replaced by a `lazy` option. ```diff - const { data } = await useWPPosts() + const { data } = await usePosts() - const { data } = await useWPPageByUri({ uri }) + const { data } = await usePageByUri({ uri }) - const { data } = useAsyncWPPosts() + const { data } = usePosts(undefined, { lazy: true }) ``` Every composable is auto-imported and fully typed. The module generates TypeScript declarations from your GraphQL queries and fragments at build time, so you get autocomplete and type checking all the way from WordPress through to your Vue templates. Each composable now accepts options for retry, timeout, and caching: ```ts [app/pages/blog/[...slug\\].vue] const { data: post } = await usePostByUri({ uri: route.params.slug }, { retry: 3, retryDelay: 1000, timeout: 5000, clientCache: false }) ``` Retry uses exponential backoff by default. Timeouts create an `AbortController` under the hood and clean up properly when the request completes or the component unmounts. WPNuxt 2 also generates composables for GraphQL mutations. Define a mutation in your `extend/queries/` folder and the module generates a `useMutation{Name}()` composable — fully typed, auto-imported, and ready to use for creating comments, submitting forms, or any custom WordPress mutation. The `usePrevNextPost()` composable provides previous/next post navigation out of the box. ### Extending Queries WPNuxt provides default GraphQL queries for posts, pages, menus, and settings. You can override any of these or add your own by creating `.gql` files in the `extend/queries/` folder: ```graphql [extend/queries/CustomPosts.gql] query CustomPosts($limit: Int = 10) { posts(first: $limit) { nodes { ...Post customField } } } ``` This generates `useCustomPosts()` and a lazy variant automatically — fully typed, auto-imported, and cached. --- ## Multi-Layer Caching One of the biggest improvements in v2 is a structured three-layer caching system that works out of the box: | Layer | Scope | What It Does | | -------------------- | ----------- | ------------------------------------------------------------------------ | | **Server (Nitro)** | All users | SWR-based caching of GraphQL responses (\~1-5ms vs \~200-500ms uncached) | | **Client (GraphQL)** | Per browser | Deduplicates identical queries during navigation | | **Payload** | Per request | Prevents refetch during SSR-to-client hydration | Configure it in `nuxt.config.ts`: ```ts [nuxt.config.ts] export default defineNuxtConfig({ wpNuxt: { cache: { enabled: true, maxAge: 300, swr: true } } }) ``` You can also disable caching per-query for content that needs to be fresh, like authenticated or preview content: ```ts const { data } = await useViewer(undefined, { clientCache: false }) ``` Every deployment automatically generates a unique build hash that invalidates the cache, so stale content never survives a redeploy. The SSG support deserves a special mention. WPNuxt normalizes WordPress URIs with trailing slashes to ensure consistent cache keys between prerendered payloads and client-side navigation. The `getCachedData` functions are defined at module level (not inside the composable) to maintain stable function references across SSR and hydration, preventing Nuxt's "incompatible options" warnings. --- ## Content Rendering ### The WPContent Component The `` component handles WordPress content rendering: ```vue [app/pages/[...slug\\].vue] ``` WPContent automatically detects whether `@wpnuxt/blocks` is installed. If it is, content renders through the `BlockRenderer` for structured Gutenberg blocks. Otherwise, it falls back to sanitized HTML via the built-in `v-sanitize-html` directive. The component also intercepts clicks on internal links and uses `navigateTo()` for client-side navigation. It respects modifier keys (Ctrl/Cmd+click for new tab), `target="_blank"`, `download` attributes, and `rel="external"` — so link behavior stays predictable. ### Gutenberg Blocks The `@wpnuxt/blocks` package renders WordPress Gutenberg blocks as Vue components. Each block type maps to a dedicated component: | Component | Block Type | | --------------- | ------------------------------- | | `CoreParagraph` | `core/paragraph` | | `CoreHeading` | `core/heading` | | `CoreImage` | `core/image` | | `CoreButton` | `core/button` | | `CoreButtons` | `core/buttons` | | `CoreQuote` | `core/quote` | | `CoreGallery` | `core/gallery` | | `CoreSpacer` | `core/spacer` | | `CoreDetails` | `core/details` | | `EditorBlock` | Fallback for unsupported blocks | Install the blocks package alongside core: ```bash pnpm add @wpnuxt/blocks ``` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['@wpnuxt/blocks'] }) ``` The blocks module automatically extends the `Post` and `Page` GraphQL fragments to include `editorBlocks` data. It also detects `@nuxt/ui` and uses its components where appropriate — for example, `CoreButton` renders as a `UButton` when Nuxt UI is available. Override any block by creating your own component in `components/blocks/`. A `CoreParagraph.vue` in your project takes precedence over the built-in version, giving you full control over rendering without ejecting from the system. ### Serverless-Ready Sanitization Version 1 used `@radya/nuxt-dompurify`, which pulled jsdom (\~5.7 MB) into the server bundle. This broke SSR on serverless platforms like Vercel where the bundle size matters. Version 2 replaces this with a built-in `v-sanitize-html` directive. On the server, HTML passes through as-is (WordPress is a trusted source). On the client, DOMPurify loads lazily using the native browser DOM — no jsdom required. --- ## Authentication The `@wpnuxt/auth` package adds WordPress authentication with three supported flows: | Method | Flow | WordPress Plugin | | ------------------- | -------------------------------------- | ---------------------------- | | **Password** | Username/password via GraphQL mutation | Headless Login for WPGraphQL | | **External OAuth** | Google, GitHub, etc. | Headless Login for WPGraphQL | | **WordPress OAuth** | Redirect to WordPress login | miniOrange WP OAuth Server | All three methods store JWT tokens in secure httpOnly cookies with automatic refresh handling. ```ts [app/pages/login.vue] const { user, isAuthenticated, login, logout } = useWPAuth() await login({ username: 'demo', password: 'secret' }) ``` The `useWPUser()` composable provides role checking: ```ts const { hasRole, isAdmin, isEditor } = useWPUser() ``` Authentication is SSR-compatible — cookies are included in server-side requests, so authenticated content renders correctly on first load. --- ## Developer Tools ### MCP Server WPNuxt 2 ships with a [Model Context Protocol](https://modelcontextprotocol.io/){rel=""nofollow""} server that integrates with AI assistants like Claude Code. Add it to your project's `.mcp.json`: ```json [.mcp.json] { "mcpServers": { "wpnuxt": { "type": "sse", "url": "https://wpnuxt.com/mcp" } } } ``` The MCP server provides tools across several categories: **WordPress Discovery** — Connect to your WordPress site and explore content types, menus, taxonomies, installed plugins, and available Gutenberg blocks. **Content Fetching** — Fetch posts, pages, and sample content directly, or run custom GraphQL queries. **Code Generation** — Scaffold pages, components, GraphQL queries, and block renderers for your WPNuxt project. The `wpnuxt_init` tool generates a complete project structure. **Migration** — The `wpnuxt_migrate` tool scans v1 projects, identifies breaking changes, detects anti-patterns, and generates compatibility helpers for upgrading. **Documentation Proxy** — The `nuxt_docs` and `nuxt_ui_docs` tools proxy official Nuxt and Nuxt UI documentation, so you only need one MCP server for your WPNuxt project. ### The wpnuxi CLI A standalone CLI tool handles project scaffolding and diagnostics: ```bash # Create a new WPNuxt project npx wpnuxi init my-site # Display environment info npx wpnuxi info # Run health checks npx wpnuxi doctor ``` The `doctor` command checks your environment variables, WordPress URL validity, GraphQL endpoint reachability, introspection support, and project dependencies. It gives you a clear diagnostic when something isn't connecting. ### Vercel Auto-Configuration WPNuxt v2 auto-detects Vercel deployments and applies the right settings: - Native SWR for proper ISR (Incremental Static Regeneration) handling - SSR forced for all routes (fixes catch-all route classification issues) - WordPress uploads proxy (`/wp-content/uploads/**` forwarded to your WordPress site) — images and media referenced in WordPress content just work without exposing your WordPress domain - `@nuxt/image` IPX configuration with proper WordPress domain aliases No manual Vercel configuration needed — it just works. ### Additional Configuration For WordPress sites with public introspection disabled, WPNuxt supports a `schemaAuthToken` that sends a Bearer token during schema download without ever exposing it in the client bundle: ```ts [nuxt.config.ts] wpNuxt: { schemaAuthToken: process.env.WPNUXT_SCHEMA_AUTH_TOKEN } ``` WPNuxt automatically creates `server/graphqlMiddleware.serverOptions.ts` and `app/graphqlMiddleware.clientOptions.ts` with sensible defaults for cookie forwarding, Authorization header passthrough, and preview mode support. Existing files are never overwritten, so custom configurations are preserved. Running `nuxt prepare` for the first time triggers an interactive setup that prompts for your WordPress URL, creates `.env` and `.env.example` files, sets up `.mcp.json` for AI assistant integration, and creates the `extend/queries/` folder for custom GraphQL queries. --- ## Breaking Changes If you're upgrading from v1, the key changes are: - **Composable names** — `useWP*` prefix dropped: `useWPPosts()` → `usePosts()`, `useWPPageByUri()` → `usePageByUri()` - **Lazy loading** — `useAsync*` replaced by a `lazy` option: `usePosts(undefined, { lazy: true })` - **Cache config** — `enableCache` / `cacheMaxAge` replaced by `cache: { enabled, maxAge, swr }` - **Removed composables** — `useFeaturedImage()` (use `post.featuredImage.node` directly), `useWPUri()` (use `useRoute().params`) - **Minimum versions** — Nuxt 4.0+, Node.js 20+, nuxt-graphql-middleware 5.x The WPNuxt MCP server includes a `wpnuxt_migrate` tool that can scan your v1 project and generate a detailed migration plan. --- ## Getting Started The fastest way to start a new WPNuxt project: ```bash npx wpnuxi init my-wordpress-site ``` Or manually: ```bash pnpm add @wpnuxt/core ``` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: ['@wpnuxt/core'], wpNuxt: { wordpressUrl: 'https://your-wordpress-site.com' } }) ``` To add blocks and authentication: ```bash pnpm add @wpnuxt/blocks @wpnuxt/auth ``` ```ts [nuxt.config.ts] export default defineNuxtConfig({ modules: [ '@wpnuxt/core', '@wpnuxt/blocks', '@wpnuxt/auth' ] }) ``` Run `nuxt prepare` and WPNuxt handles the rest — downloading the GraphQL schema, generating composables, and setting up type declarations. --- ## What's Next WPNuxt 2.0 is stable and ready for production. Here's what's on the roadmap: - **Cursor-based pagination** for large content sets - **Deeper inner block nesting** for complex Gutenberg layouts - **Additional default queries** for taxonomies and search - **End-to-end tutorials** for common use cases (blog, SEO, menus) - **Media handling deep dive** with `@nuxt/image` optimization patterns Feedback, feature requests, and bug reports are welcome on the [GitHub repository](https://github.com/wpnuxt/wpnuxt){rel=""nofollow""}. --- ## Resources **Getting Started:** - [WPNuxt Documentation](https://wpnuxt.com){rel=""nofollow""} - [GitHub Repository](https://github.com/wpnuxt/wpnuxt){rel=""nofollow""} - [npm: @wpnuxt/core](https://www.npmjs.com/package/@wpnuxt/core){rel=""nofollow""} **WordPress Requirements:** - [WPGraphQL Plugin](https://www.wpgraphql.com/){rel=""nofollow""} - [WPGraphQL Content Blocks](https://github.com/wpengine/wp-graphql-content-blocks){rel=""nofollow""} (for `@wpnuxt/blocks`) - [Headless Login for WPGraphQL](https://github.com/AxeWP/wp-graphql-headless-login){rel=""nofollow""} (for `@wpnuxt/auth`) **Related Posts:** - [Discovering Nuxt](https://vernaillen.dev/blog/discoveringnuxt) # Kaspa: digital silver Source: [vernaillen.dev/blog/kaspa](https://vernaillen.dev/blog/kaspa) ## Kaspa At a Glance Kaspa is a proof-of-work cryptocurrency that stays true to Satoshi Nakamoto's vision—decentralized, secure digital money—while fixing Bitcoin's speed limitations. It uses blockDAG (Directed Acyclic Graph) instead of a traditional blockchain, allowing multiple blocks to be created in parallel (\~10 blocks per second) while maintaining decentralization. The ecosystem is expanding with L2 solutions (Kasplex, Igra) today and a longer-term vision called vProgs for native smart contracts using zero-knowledge proofs. --- ## What is Kaspa? Kaspa aims to realize Satoshi Nakamoto's vision of fast, decentralized, secure digital money—but with modern upgrades. It improves on Bitcoin's original design by replacing the single-chain blockchain with a "blockDAG." Instead of adding blocks one at a time, blockDAG allows many blocks to be created simultaneously and connects them in a network (Directed Acyclic Graph). The GHOSTDAG protocol orders any conflicting blocks to maintain consensus. | Traditional Blockchain | Kaspa's BlockDAG | | ------------------------------------ | --------------------------------------- | | One block every 10 minutes (Bitcoin) | \~10 blocks per second (post-Crescendo) | | Sequential block creation | Parallel block creation | | Limited throughput | Higher throughput potential | *Note: The Crescendo hardfork (May 5, 2025) upgraded the network from 1 BPS to 10 BPS. Higher rates (\~32 BPS) are longer-term targets.* Kaspa maintains proof-of-work mining with no pre-mine and no central authority—though ASICs now dominate the network hashrate, making GPU mining mainly a hobbyist pursuit. ## Why I'm Interested As a developer who values open-source principles, Kaspa caught my attention because: - **Technical approach**: The blockDAG architecture is an elegant solution to the throughput vs. decentralization tradeoff - **Active development**: The core team has been steadily improving the protocol, with smart contract capabilities on the horizon - **vProgs vision**: Native smart contracts with off-chain execution and on-chain verification using zero-knowledge proofs (more on this below) I've started learning smart contract development and EVM programming to be ready when these capabilities become available. ## Smart Contracts: Current and Future Kaspa started as a pure currency. The ecosystem is now expanding with [multiple approaches to programmability](https://kaspa.org/kaspas-programmability-mosaic/){rel=""nofollow""}: **Available Today:** - **[KRC-20](https://docs.kasplex.org/){rel=""nofollow""}**: Token standard using L1 data insertion and off-chain indexing **In Development:** - **[Kasplex L2](https://medium.com/@KaspaKEF/kasplex-l2-a-light-weight-based-rollup-solution-on-kaspa-33a5939bdf61){rel=""nofollow""}**: Planned Ethereum-compatible L2 with LUA VM targeted for December 2025 - **[Igra Labs](https://igralabs.com/){rel=""nofollow""}**: EVM-compatible ZK rollup (testnet live, mainnet targeted early 2026) **Long-term Vision:** - **vProgs**: Native smart contracts built into L1 (see below) ## vProgs: Off-Chain Execution, On-Chain Verification vProgs (Verifiable Programs) represent Kaspa's long-term approach to smart contracts. The key idea: instead of executing contracts on-chain (slow and expensive) or on separate L2s (fragments liquidity), vProgs execute off-chain and prove correctness using zero-knowledge proofs. The blockchain only verifies the proof. **How it works**: Think of vProgs like apps that run independently but can interact when needed. A token swap might involve three vProgs—a price oracle, trading app, and stablecoin manager—each generating proofs that combine into one atomic transaction. **Claimed benefits** (per [BSC News analysis](https://bsc.news/post/kaspa-kas-vprogs){rel=""nofollow""}): - Efficient verification instead of full re-execution - Multiple vProgs can interact in single transactions - "ScopeGas" fee system for spam protection **Current status**: The [vProgs Yellow Paper](https://github.com/kaspanet/research/blob/main/vProgs/vProgs_yellow_paper.pdf){rel=""nofollow""} (Draft v0.0.1) was released September 2025. This is early-stage research—timelines are speculative and depend on development progress, testing, and audits. ![Kaspa](https://vernaillen.dev/images/blog/994.kaspa/Gxn--EmXEAAjHhA.jpeg){.rounded-lg height="671" width="1192"} ## Getting Started If you want to explore Kaspa: 1. **Learn more**: [kaspa.org](https://kaspa.org/){rel=""nofollow""} for documentation 2. **Set up a wallet**: [Kasware](https://www.kasware.xyz/){rel=""nofollow""} (browser) or [Kaspium](https://kaspium.io/){rel=""nofollow""} (mobile) 3. **Join the community**: [GitHub](https://github.com/kaspanet){rel=""nofollow""}, [Discord](https://discord.gg/kaspa){rel=""nofollow""}, [Research Forum](https://research.kas.pa/){rel=""nofollow""} 4. **Developer resources**: [Kaspa Developer Hub](https://kaspahub.github.io/developers/){rel=""nofollow""}, [KIPs](https://github.com/kaspanet/kips){rel=""nofollow""} ## Resources **Official:** [Kaspa.org](https://kaspa.org/){rel=""nofollow""} · [Documentation](https://kaspa.org/docs/){rel=""nofollow""} · [Discord](https://discord.gg/kaspa){rel=""nofollow""} **Ecosystem:** [Kasplex](https://kasplex.org/){rel=""nofollow""} · [Igra Labs](https://igralabs.com/){rel=""nofollow""} · [Kasia](https://kasia.fyi/){rel=""nofollow""} **Technical:** [vProgs Yellow Paper](https://github.com/kaspanet/research/blob/main/vProgs/vProgs_yellow_paper.pdf){rel=""nofollow""} · [rusty-kaspa](https://github.com/kaspanet/rusty-kaspa){rel=""nofollow""} · [KIPs](https://github.com/kaspanet/kips){rel=""nofollow""} **Disclaimer:** This post represents my personal interest and research. It is not financial advice. Always do your own research before investing in any cryptocurrency. # Discovering Nuxt Source: [vernaillen.dev/blog/discoveringnuxt](https://vernaillen.dev/blog/discoveringnuxt) ## Discovering Nuxt After rebuilding this site [vernaillen.dev](https://vernaillen.dev){rel=""nofollow""} from scratch up with Vue [last year](https://vernaillen.dev/blog/hello-world-vernaillen-dev), for which I spend a lot of time selecting and integrating different vue and vite plugins, I decided to build my other website, [Harmonics.be](https://harmonics.be){rel=""nofollow""} and [links.vernaillen.dev](https://links.vernaillen.dev){rel=""nofollow""} with [Nuxt 3](https://nuxt.com/){rel=""nofollow""}. Nuxt makes it a lot easier and faster to bootstrap a new website. Less fiddling with plugins to make it all work nicely together. And it's bundled with Vite and running on Nitro's server engine, so it's pretty fast. I also love writing and publishing content with Markdown, therefor [Nuxt Content](https://content.nuxtjs.org/){rel=""nofollow""} is just perfect for me for content management. *Edit: A month has past since I've first published this blog post, but since then I've also created a new website using Nuxt for my sister [Anneleen Vernaillen](https://www.anneleenvernaillen.com/){rel=""nofollow""}, and today (March 2) I've put the Nuxt version of [this website](https://vernaillen.dev){rel=""nofollow""}.* ## Deployed on Vercel At this moment I have deployed 6 websites using Nuxt on [Vercel](https://www.vercel.com/){rel=""nofollow""}: - [anneleenvernaillen.com](https://anneleenvernaillen.com){rel=""nofollow""} my sister, Anneleen Vernaillen's new website. All design and art work by her, web development by me - [harmonics.be](https://harmonics.be){rel=""nofollow""} my website for my activities as a sound healing practicioner, ecstatic dance dj and trance dance facilitator - [vernaillen.dev](https://harmonics.be){rel=""nofollow""} this website, my freelance developer website - [links.vernaillen.dev](https://links.vernaillen.dev){rel=""nofollow""} my "link in bio" app - [nuxt-audiomotion-analyzer-docs](https://nuxt-audiomotion-analyzer-docs.vercel.app/){rel=""nofollow""} Nuxt AudioMotion Analyzer, a Vite plugin I made wrapping [Henrique Vianna's audioMotion-analyzer](https://audiomotion.dev/#/){rel=""nofollow""} - [nuxt-audiomotion-analyzer.vercel.app](https://nuxt-audiomotion-analyzer.vercel.app/){rel=""nofollow""} a small demo site for the Vue AudioMotion Analyzer ## The stack I'm using - [Nuxt 3](https://nuxt.com/){rel=""nofollow""} as web framework - it's abviously based on [Vue.js](https://vuejs.org/){rel=""nofollow""} as JavaScript framework - [Nuxt Content 2](https://content.nuxtjs.org/){rel=""nofollow""} for managing content with markdown - [Tailwindcss](https://tailwindcss.com/){rel=""nofollow""} as CSS framework - [Vitest](https://vitest.dev/){rel=""nofollow""} for unit testing - [Cypress](https://www.cypress.io/){rel=""nofollow""} for e2e testing - [pnpm](https://pnpm.io/){rel=""nofollow""} as fast package manager - [Renovate](https://www.mend.io/free-developer-tools/renovate/){rel=""nofollow""} for automating dependency updates - [GitHub](https://github.com/vernaillen){rel=""nofollow""} as code repository - [Netlify](https://netlify.com/){rel=""nofollow""} for 'bringing it all together' and hosting the apps - [Visual Studio Code](https://code.visualstudio.com/){rel=""nofollow""} for code editing ## The learning never stops For learning everything about Nuxt I decided to purchase the [Mastering Nuxt 3](https://masteringnuxt.com/){rel=""nofollow""} video course, which is created by the team who created Nuxt 3. I didn't regret that purchase and I can highly recommed it. Currently I'm learning how to build and secure serverside api's with Nuxt. # Hello World Vernaillen.dev Source: [vernaillen.dev/blog/hello-world-vernaillen-dev](https://vernaillen.dev/blog/hello-world-vernaillen-dev) ## Sunset of Vernaillen.com To be honest the most important reason I wanted to make a new website is because [Vernaillen.com](https://www.vernaillen.com){rel=""nofollow""} was made in Liferay and I didn't want to keep a Liferay server running only for my personal website. Anyway, my main focus as a freelance consultant is not on Liferay any more lately, but more on full stack development with Spring micro-services, Angular or Vue.js, as well as on DevOps with Kubernetes, Jenkins, Sonar, etc. I wanted to become more skilled in Vue.js anyway, so I decided to rewrite my website using Vue 3, Vite, Tailwind and Markdown: ## Hello World for Vernaillen.dev For the design I decided to use this [Startup Tailwind CSS Template](https://tailwindtemplates.co/templates/startup){rel=""nofollow""}, cause I'm a developer, not a designer :) It was fun to port into the Vue app. And after changing the main colors to match my company branding and logo (design by my sister, [Anneleen Vernaillen](https://www.anneleenvernaillen.com){rel=""nofollow""}), I thought the result was quite nice. Most of the fun for me was in learning the new features of Vue 3, learning how to use Vite and Tailwind, and create blog functionality based on markdown files. The result is a website that is very easy to edit and publish content updates, cause as a developer I'm obviously familiar with git and markdown anyway. ## Website Features - Built with [Vue 3](https://vuejs.org/){rel=""nofollow""}, [TypeScript](https://vuejs.org/guide/typescript/overview.html){rel=""nofollow""}, [Vite](https://vitejs.dev/){rel=""nofollow""} and [Tailwind CSS](https://tailwindcss.com/){rel=""nofollow""} - Static Site Generation with [vite-ssg](https://github.com/antfu/vite-ssg){rel=""nofollow""}, so search indexes can crawl the content - All content is created using [Markdown](https://daringfireball.net/projects/markdown/){rel=""nofollow""} and rendered with [vite-plugin-md](https://github.com/antfu/vite-plugin-md){rel=""nofollow""} and [markdown-it](https://markdown-it.github.io/){rel=""nofollow""} - SVG support in Vue with [vite-svg-loader](https://github.com/jpkleemans/vite-svg-loader){rel=""nofollow""}, used for the background graphics - RSS & Atom for newsreaders - Dark and Light style - [Tone.js](https://tonejs.github.io/){rel=""nofollow""} and audio visualisation with [vue-audiomotion-analyzer](https://vue-audiomotion-analyzer.dev/){rel=""nofollow""} - [Pinia](https://pinia.vuejs.org/){rel=""nofollow""} is used to keep track of the audio player state - Automated deployments / auto publishing on [Netlify](https://www.netlify.com/){rel=""nofollow""} - Continous integration with [CircleCI](https://app.circleci.com/pipelines/github/vernaillen/vernaillen.dev?filter=all){rel=""nofollow""} - Code quality check with [SonarCloud](https://sonarcloud.io/summary/new_code?id=vernaillen.dev){rel=""nofollow""} - Unit tests with [vitest](https://vitest.dev/){rel=""nofollow""} # Building a stronger personal brand Source: [vernaillen.dev/blog/building-a-stronger-personal-brand](https://vernaillen.dev/blog/building-a-stronger-personal-brand) ## The Crew January 2017 was a month that I will always remember. I left Belgium on January 6th for what would be a 2,5 months journey in Asia. For the first leg of my trip, I decided to spend 6 weeks in Bali because I wanted to focus on some side projects and get stuff done. To hold me accountable to reach my goals for these side projects, I decided to join a productivity program in Ubud called The Crew, organized and coached by [Colleen Schell](https://leadershiprev.com/){rel=""nofollow""}. During this one month of productivity I was hoping to finish a [WordPress website](https://pastoriebalegem.be/){rel=""nofollow""} for a client, profile myself better as a [Liferay](https://www.liferay.com/){rel=""nofollow""} expert, define a roadmap for {dev}Nomads, a community for nomadic developers that I have started, and start executing that roadmap. ## Program But it turned out completely different! In this month we had half day sessions 4 times a week, from Monday to Thursday. To give you an idea of the program, these are some of the **topics we worked on**: - Define our "North Star", our personal mission - Analysis of our own personal value tree - Exercises around emotional intelligence and empathic listening - NLP with Helene Weiss - Practicing the Pomodoro technique - Write in a gratitude journal every day - Deep Dive: Focus on a Crew member's challenges - ... ![Leila presents her project idea to the group](https://vernaillen.dev/images/blog/997.personalbrand/thecrew2.jpeg){.rounded-lg height="671" width="1192"} ## Takeaways This was quite intensive and I didn't get to focus as much on my projects as I wanted. I felt bad about that at first, but later I realized that what I got out of it instead was amazing. These are the **most important things I got out of the program**: - I learned how to express myself and show who I am, creating my own value tree and translate this into text for my website and a strong personal brand - I was able to redefine my goals and get more clarity, realizing that what works best for me is to focus on only one thing at a time - Discussing emotions and being open about vulnerabilities was so far out of my comfort zone, but it has helped me to open up and realize that it can be powerful to show your vulnerability. It made me confident that I can be more open about being an HSP, Highly Sensitive Person. There is also a TED talk by [Brene Brown about the Power of Vulnerability](https://www.ted.com/talks/brene_brown_the_power_of_vulnerability){rel=""nofollow""}, that inspired me a lot, so I highly recommend it if you're interested in the topic. ## New ideas Now, what does this all has to do with my new website, you're asking? It is the Crew program that has set the mindset in which the ideas for the new website were born. ## Personal branding And during the program, another opportunity presented itself: a **personal branding workshop** organized by **Patricia Parkinson** at the [Outpost coworking space](https://destinationoutpost.co/){rel=""nofollow""}. First I didn't want to do yet another workshop that would eat more of my time, cause I was feeling bad about not having much work done yet for the WordPress website for my client, but on the other hand it was a perfect opportunity to focus on my personal branding, which I actually need to do as well. The workshop turned out to be amazing as well. We learned why personal branding is important, we did a peer survey, defined our audience persona, build a mood board and practiced our elevator pitch. This was exactly what I needed to translate what I had learned at the Crew program into an actual personal brand. After the workshop, Patricia helped me to translate the values I had listed in my value tree into the different sections on my website. ![Values](https://vernaillen.dev/images/blog/997.personalbrand/values.png){.rounded-lg height="326" width="1192"} Patricia also came up with the brilliant idea of listing the projects I have worked on in "portfolio style" using a category filter based on the technologies I used on these projects. So, the end result is a website that is not only showing what I do, but also who I am, how I love to work and what my values and passions are. Last, but not least, I want to thank Carole Favre, one of my fellow Crew members, for coming up with the term "Techie with a heart" (I love it!), as well as the other Crew members for supporting me in this journey. # Using Liferay 7 to build a community website Source: [vernaillen.dev/blog/using-liferay-7-to-build-a-community-website](https://vernaillen.dev/blog/using-liferay-7-to-build-a-community-website) ## Liferay 7 Since I wrote the previous article on this blog, about my plans after Liferay DevCon last year, I've been testing every alpha, beta, rc and ga release of the new Liferay 7. The reason why I was following it up so closely is not just because I make a living as a freelance Liferay consultant, but also because I decided to use Liferay 7 to build the community website for {dev}Nomads, a community for nomadic developers. For those who don't know Liferay yet, here's why to use it as described on the Liferay website: The reasons to use Liferay Portal for your website are simple: it provides a robust platform to build your site on quickly and serve it to all clients, be they desktop, mobile, or anything in between; it provides all the standard applications you need to run on your site; and it provides an easy to use development framework for new applications or customization. In addition to this, Liferay Portal is developed using an open source methodology, by people from around the world. The code base is solid and has been proved to be reliable and stable in mission critical deployments in diverse industries. ## Building a community website In fact Liferay provides almost everything "out of the box" that is needed to build a great community website: - Message Boards This will be one of the core features for the {dev}Nomads website. - Polls - Wiki's - Microblogs: status updates like twitter - Blogs - Form builder - Web Content & Document Management Besides the specific community features Liferay also supports: - Multiple sites and subsites This is excellent for {dev}Nomads for creating a private forum for each mastermind group. Virtual instances In fact this website ([www.vernaillen.com](http://www.vernaillen.com){rel=""nofollow""}) is set up as a virtual instance on the same Liferay server. - Staging Allows to do all the content authoring and testing in a staging environment and publish them to a production environment when ready. - Geolocation Out of the box ability to geolocate all web content, data lists, documents & media as well as the ability to create lists of geolocalized content and publish them in a Map. All the Liferay functionality is also accessible through a RESTFul Webservice API This is excellent for integration with other applications or mobile apps. - Full modularity with OSGi All functionality is provided as separate modules, which allows to easily switch features on and off, but also easily extend and customize functionality. These are a few of the new features of the Liferay 7 that I'm most excited about: AlloyEditor is a new web content editor build on CKEditor. Liferay decided to remove the default UI of CKEditor and build a completely new UI using React. The inline content authoring works very easy, but it's also possible to edit the html directly, including side by side editing and html validation: In other words: this is an excellent editor for the target audience of {dev}Nomads, cause they are all developers. :) The new Form builder allows defining and publishing advanced dynamic forms. The forms can have complex multi-column layouts and span several pages. They can be published in any Liferay site just by dropping the form into a page or also Google Forms style, by providing a URL that links directly to a full page form. Many field types are included out of the box and custom types can be added by deploying custom modules. Forms can also be integrated with Liferay's workflow system to submit forms through a predefined process. # My action plan after Liferay DevCon Source: [vernaillen.dev/blog/my-action-plan-after-liferay-devcon](https://vernaillen.dev/blog/my-action-plan-after-liferay-devcon) ## Liferay DevCon 2015 A few weeks ago I went to the Liferay Developer Conference in Darmstadt. Needless to say there were many new features of Liferay 7 presented and lot's of exciting stuff happened at the conference. You can read about the highlights in the blogposts of Olaf Kock and James Falkner. ## My action plan It was already the 3rd year in a row that I attended the conference and as always it has given me a motivational boost. So, I made a list for myself about the actions I want to take after the conference and I'd like to share this with you: - Participate more in the forums. I've been trying to do that for a while already, but it's not always easy when working full time as a consultant. But James Falkner announced the use of [networkactivator.com](https://networkactivator.com/){rel=""nofollow""} for the Liferay forums, which is a system that sends a list every week of unanswered forum topics. I'm now subscribed for the Theming and Development sections. - Test new Liferay7 theming features. I've been part of the Liferay 7 Community Expedition from the start, tested some milestone releases and posted a few forum topics about it. I was surprised though when James Falkner mentioned me in his Community Update at DevCon on the leaderboard of the expedition. This motivates me to be involved even more, so I'm actively testing new features in the alpha releases now. - Get Liferay 7 up and running for my website. Maybe it's very early to already base a live website on on alpha version, but after all it is just a website and no real portal functionality is needed yet. The most important part to be able to put this website online, was to learn about the new theming features of Liferay 7. Lots is changing fo the theming as well, but I managed to convert my Liferay 6.2 theme into a Liferay 7 theme. :) - **Start blogging on vernaillen.com**. Which also happened already, because you're reading my first blogpost right now. :) - And lastly, but maybe the most important one, start building Liferay plugins to distribute through the [Liferay Marketplace](https://web.liferay.com/marketplace){rel=""nofollow""}. I won't share yet what exactly I'm working on, but I might do it when i'm a bit further in the process. :) Starting this week I will work as a consultant for only 4 days per week instead of 5, which will give me more space to work on my own projects and contribute back to the community. # About Me Source: [vernaillen.dev/about](https://vernaillen.dev/about) I wrote my first line of code in the late 90s. Back then, it was static HTML and the occasional Java applet. Almost 30 years later, I'm still at it — though the stack has gotten considerably better. I'm a freelance full stack developer based in Belgium. Since going independent in 2013, I've spent most of my time in the space where enterprise backends meet modern frontends — building web portals for government organizations and large companies, where the architecture needs to be solid but the user experience still needs to feel effortless. ## The stack My backend roots run deep in **Java** and **Spring Framework** — APIs, system integrations, the kind of architecture that handles real-world complexity without falling over. On the frontend, I've gone all in on **Nuxt** and **Vue.js**. The developer experience is unmatched, and the results speak for themselves. What I enjoy most is the translation layer between these two worlds. Making a complex enterprise system feel simple on the surface — that's the puzzle I keep coming back to. ## Open source I created **[WPNuxt](https://wpnuxt.com){rel=""nofollow""}**, a Nuxt module for using WordPress as a headless CMS. It connects via GraphQL and gives content teams the WordPress editor they already know, while developers get a Nuxt frontend they actually want to work with. It started as a scratching-my-own-itch project and turned into something other people rely on. I also build smaller things — audio visualization components, creative coding experiments — mostly because I can't help myself. ## The other side There's a whole part of my life that has nothing to do with code. I'm a sound healing practitioner, an ecstatic dance DJ, and a trance dance facilitator. I run **[Harmonics.be](https://harmonics.be){rel=""nofollow""}** — organizing events around sound, music, and movement. It might seem like a strange combination, but there's a thread that connects it all: I like building experiences. Whether it's a web application that just works, or a sound journey that takes people somewhere unexpected — the craft is in making the complex feel natural. I travel whenever I can, always looking for how different cultures approach rhythm, movement, and community. It feeds everything I do. ## Let's talk I'm currently working on a long-term project, but feel free to contact me on [LinkedIn](https://www.linkedin.com/in/woutervernaillen/){rel=""nofollow""}. # Home Source: https://vernaillen.dev/ ## About Me I build robust web solutions from backend to frontend — bridging enterprise Java with modern JavaScript, and now embracing agentic workflows.
Loving every bit of it!

As a full stack developer with 25+ years of experience, I've gone from the first static HTML sites to cutting-edge web portals with seamless backend integrations. I combine deep Java/Spring expertise with a passion for modern frontend development using Nuxt and Vue. Creator of WPNuxt, an open source module for headless WordPress with Nuxt.

I'm also a sound healing practitioner, an ecstatic dance DJ, and a trance dance facilitator. I run [Harmonics.be](https://harmonics.be) — organizing events around sound, music, and movement.

I'm based in Belgium (Europe/Brussels timezone) and work primarily remotely, for Belgian and international clients alike. ## Work Experience - **2023 - Present** — Creator & Maintainer of [WPNuxt](https://wpnuxt.com) - **2019 - Present** — Full Stack Developer at [Opgroeien / Kind & Gezin](https://www.opgroeien.be) - **2018 - 2019** — Full Stack Developer at [IDEWE](https://www.idewe.be) - **2014 - 2017** — Full Stack Developer at [Kind & Gezin](https://www.kindengezin.be) - **2013 - 2014** — Lead Developer at [Colruyt](https://www.colruytgroup.com) - **2010 - 2013** — Portal Architect at [Van Marcke](https://www.vanmarcke.com) - **2006 - 2010** — WebSphere Portal Consultant at [IBM](https://www.ibm.com) - **2003 - 2006** — Java Software Engineer at [UPM-Kymmene](https://www.upm.com) - **2000 - 2003** — Lotus Notes Developer at [Atos Origin](https://atos.net) - **1999 - 2000** — Lotus Notes Developer at [Alcatel e-Com](https://en.wikipedia.org/wiki/Alcatel) ## At a Glance - **25+** Years Experience - **50+** Projects Delivered - **64** GitHub Stars - **2013** Freelancing Since ## Frequently Asked Questions ### Services & Expertise **What services do you offer?** I specialize in full stack web development with Java/Spring backends and Nuxt/Vue frontends. This includes API development & integration, building modern web portals, setting up CI/CD pipelines, and DevOps with Docker and Kubernetes. I also build headless WordPress solutions using my open source WPNuxt module. **What is your tech stack?** My primary stack is Java and Spring Framework on the backend, with Nuxt and Vue.js on the frontend. For DevOps I work with Docker, Kubernetes, and Jenkins. I deploy to Vercel for frontend projects and have extensive experience with Liferay portal platforms. **Do you work with startups or only enterprises?** Both! While much of my career has been in enterprise environments (government, large corporations), I also enjoy working with smaller teams and startups. My open source work on WPNuxt is a good example of building developer tools from the ground up. ### Working Together **Are you available for freelance work?** Yes, I've been freelancing since 2013. I'm available for both long-term engagements and shorter project-based work. Feel free to schedule a call via Calendly to discuss your project. **Where are you based?** I'm based in Belgium (Europe/Brussels timezone). I work primarily remotely, for Belgian and international clients alike — for clients in Belgium I'm available on-site up to one day a week. **How can I get in touch?** The easiest way is to schedule a 15-minute call on [Calendly](https://calendly.com/vernaillen/15min). You can also reach me on [LinkedIn](https://www.linkedin.com/in/woutervernaillen/) or [GitHub](https://github.com/vernaillen/). ### About Me **What do you enjoy most about your work?** I love bridging the gap between robust backend systems and beautiful, fast frontends. There's something satisfying about making a complex enterprise system feel effortless to use. Building open source tools like WPNuxt and seeing others use them is also incredibly rewarding. **What are your interests outside of coding?** Sound, music and dance are a big part of my life. I'm a sound healing practitioner, ecstatic dance DJ, and trance dance facilitator — you can find more about that on [Harmonics.be](https://harmonics.be). I'm also an avid traveler, always curious about other cultures. # Career Source: https://vernaillen.dev/career The projects and companies I've worked with over 25+ years, and the technologies I've used along the way. - **2019** — *Freelance* — Senior Full Stack Java Developer — Governmental citizen portal @ [Opgroeien / Kind & Gezin](https://www.opgroeien.be) - **2018** — *Freelance* — Senior Full Stack Java Developer — Customer Portal @ IDEWE (via Cronos) - **2014** — *Freelance* — Senior Full Stack Java Developer — Governmental citizen portal @ Kind & Gezin (via Cronos) - **2013** — *Freelance* — Lead Developer — Dreambaby community portal @ Colruyt (via TCS) - **2010** — *Employment* — Portal Architect / Project Leader Intranet @ Van Marcke - **2006** — *Employment* — WebSphere Portal & J2EE Developer/Consultant — clients: UZ Gent, VDAB, European Commission, Eandis @ IBM - **2003** — *Employment* — Java Software Engineer & Lead Developer @ UPM-Kymmene - **2000** — *Employment* — Lotus Notes Developer @ Atos Origin - **1999** — *Employment* — Lotus Notes Developer @ Alcatel e-Com / the e-Corporation # Projects Source: https://vernaillen.dev/projects ## [WPNuxt](https://wpnuxt.com) A Nuxt module to use WordPress as a headless CMS with a Nuxt frontend. Connects via GraphQL for the best of both worlds — familiar editing for content creators, cutting-edge frontend for developers. Tags: Nuxt, WordPress, GraphQL, Open Source ## [Vernaillen.dev](https://vernaillen.dev) This very website — my developer portfolio and blog. Built with Nuxt 4, Nuxt UI, and Nuxt Content. Open source on GitHub. Tags: Nuxt, Nuxt UI, Nuxt Content ## [Vue FFT Visualizer](https://github.com/vernaillen/vue-fft-visualizer) Real-time FFT audio visualization component for Vue. Renders frequency data as interactive WebGL visuals — where creative coding meets the web audio API. Tags: Vue, WebGL, Audio, Creative Coding ## [Nuxt Audiomotion Analyzer](https://nuxt-audiomotion-analyzer-docs.vercel.app/) High-resolution real-time audio spectrum analyzer for Nuxt. A plugin wrapping Henrique Vianna's audioMotion-analyzer for visualizing audio data. Tags: Nuxt, Audio, Creative Coding ## [Harmonics.be](https://harmonics.be) Website for my sound healing, ecstatic dance, and trance dance activities. Built with Nuxt and Nuxt Content, deployed on Vercel. Tags: Nuxt, Nuxt Content, Vercel