Nuxt and CiviCRM - a proof of concept

Közzétéve
2025-11-28 06:11
Written by
michaelmcandrew - member of the CiviCRM community - view blog guidelines

Note: this is a fairly technical post that outlines an integration between CiviCRM and Nuxt. If that sounds like your cup of tea, then please read on. Otherwise, feel free to skip this one.

What is Nuxt?

Nuxt is a popular and modern web application framework based on Vue. For those that are familiar with the React ecosystem, Nuxt a bit like Next.js. And if you are into Svelte, you can think of Nuxt as roughly equivalent to SvelteKit. All three of these projects aim to be 'batteries included' frameworks that make developers more productive and encourage best practice.

How did this come about?

We've started working more and more with Vue and Nuxt at Third Sector Design and wanted to explore ways in which we could better integrate them with CiviCRM. Nuxt has a module system (similar to CiviCRM's extension system) and creating a Nuxt CiviCRM integration module seemed like a good way of doing so.

It also felt like a good project to try and tackle at the CiviCRM sprint in Lunteren, Netherlands. That is to say, it felt simple enough to attempt in four days provided there were lots of other CiviCRM people around to ask for help! In the four days of that sprint - and with lots of help from Patrick Figel, Tim Otten and others - we were able to get a basic proof of concept up and running...

You're looking at a very simple Nuxt application connected to a CiviCRM Standalone site. A user logs in with the standard demo data username and password and can then access CiviCRM data. Here is the code behind this demo.

Why integrate Nuxt and CiviCRM?

It’s fair to say that the CiviCRM user interface as it stands today has some room for improvement. Indeed there are many people working on improving it right now (think of initiatives like RiverLea, SearchKit and FormBuilder). You can think of Nuxt CiviCRM as another initiative in that space. When it comes to UI, both Nuxt and Vue both bring a lot to the table in terms of tooling and best practice. Adopting them more widely has the potential to significantly increase the quality of our user interface and the speed at which we can improve CiviCRM (though exactly how this could fit in with current efforts is a topic for another day).

Most organisations today run CiviCRM alongside a compatible PHP CMS (WordPress, Drupal, Joomla or Backdop) and often rely heavily on their CMS for front-facing functionality (donation pages, event registration, portals, etc.). While our PHP CMSes are great no-code tools - and they aren't going anywhere soon - since the beginning of this year, we have also had the opportunity to run CiviCRM Standalone, which has encouraged people to begin to explore life outside of the PHP CMS box.

In Lunteren last month, Jaap introduced Kurund and Eileen and I as 'CiviCRM old timers'. I suppose that is fair enough - we have been hanging around for a while - but as well as being a timely reminder of our own mortality, it was also a good nudge to think more about how to attract new people to the project. My hunch is that there is a potential next generation of CiviCRM developers out there that are (rightly or wrongly) put off getting involved with CiviCRM because of our aging technology stack. Introducing newer tools is a great way to open the doors to these new people.

The nuts and bolts

Nuxt CiviCRM is a nuxt module that you can install as part of a Nuxt project. The general idea is that you give Nuxt the URL of your CiviCRM site and then configure CiviCRM to allow authentication from the Nuxt app. You can then log in using your normal username and password and perform any API actions available to that user. More details on how to do that are in README and on the npm page.

I've tried to make the integration feel native on both sides so that everyone will feel at home. The main interface is a composable useCivi() that gives access to the api, to login() and logout() functions, and to a reactive user object. The api looks exactly the same as it does in CiviCRM, so you can do things like retrieve 25 contacts:

const { data } = await api('Contact', 'get', {limit: 25})

All requests are proxied via some fairly simple Nuxt server functions that forward requests to CiviCRM (along with any cookies) and return the results. When a user logs in, CiviCRM issues a cookie which the Nuxt server forwards to the user. The user then sends the cookie back again with each subsequent request. And when the user logs out, the Cookie is cleared. The server doesn't store the cookie or any data. Proxying requests via a backend means that we can avoid having to configure CORS and or third party cookies.

What's next?

We are only at the proof of concept phase right now, but what we have so far feels quite promising and worth exploring some more. Here are some thoughts and ideas on what we might like to do next.

Given that we are granting access to the CiviCRM API, we should get some more eyes on the code so that we can sense check the approach, and consider and address any security concerns.

While we have chosen to do the authentication via a proxy, there are other approaches to authentication that it would be good to support, most notably, OAuth.

It would be good to create a more inspiring demo - a page that does something useful like accept donations or allow people to manage their communication preferences. In a similar vein, we could leverage Nuxt's UI library to create something that meets WAI accessibility criteria and is more designed.

We'd like to build out a more complete set of components and composables that take the grunt work out of making UI that interacts with the CiviCRM API.

The API function is written in typescript but is only superficially typed at the moment. CiviCRM's API comes with a lot of metadata that we could leverage to better type both the parameters and results of the API function. This would provide a much better developer experience and help catch logical errors in any UI we build.

We could explore how to package up widgets written with these tools as web components or similar so that they can be embedded in non Nuxt contexts (other websites, etc.).

We chose Nuxt and Vue for this proof of concept but you might have your own favourite framework - hopefully this work has given you some pointers and inspiration on how you might integrate it with CiviCRM.

We'd love to hear your thoughts and questions on what we have done so far. Feel free to take the demo for a spin and let us know if it works for you, and post in the comments below.

And If you'd like to get involved or collaborate in any way, please reach out. You could create an issue in the Github repo or message me - I'm michaelmcandrew on Mattermost.

Comments

Thanks for this interesting work, @michaelmcandrew .

We should consider the size and health of any open source community whose software we want to make a core dependency of CiviCRM. Our bet on AngularJS while understandable at the time hasn't worked out well for us.

Nuxt doesn't get broken out in most top level market share analyses in js frameworks though svelte, solid and one or two others have broken through. Here are a variety of metrics over time that are interesting: https://gist.github.com/tkrotoff/b1caa4c3a185629299ec234d2314e190 .

As nuxt is built on vue.js and has almost as much market share as vue (0.8% vs 0.7% according to https://w3techs.com/technologies/overview/javascript_library ) the figures for vue above can be taken as a reasonable proxy for nuxt .

Great thank you @michaelmcandrew

> (MichaelMcandrew) We chose Nuxt and Vue for this proof of concept but you might have your own favourite framework - hopefully this work has given you some pointers and inspiration on how you might integrate it with CiviCRM.

> (JoeMurray) We should consider the size and health of any open source community whose software we want to make a core dependency of CiviCRM.

Clarification - I think this project positions Nuxt less like "core dependency" (a la jQuery, AngularJS) and more like "CMS/UserFramework" (a la Drupal, Joomla, WordPress). The framing would be like:

* If you enjoy Drupal site-building and want to integrate with Civi, then here are some tools/techniques...
* If you enjoy WordPress site-building and want to integrate with Civi, then here are some tools/techniques...
* If you enjoy NuxtJS development and want to integrate with Civi, then here are some tools/techniques...