We recently published a write-up on a project we built for PaperCut’s Partner Portal using a static-first architecture — but with the dynamic capabilities you’d expect from a full-stack application.
The site is built as a static Next.js application, running behind a Node.js Express server that delivers dynamic content through APIs. This let us combine the performance and reliability of a static site with the flexibility and power of a traditional web application.
Some of the key features we implemented include:
User authorisation
Internationalisation (i18n)
Role-based dynamic content
Database integration
Live editing directly within CloudCannon
Static performance with dynamic behaviour
CloudCannon played a big role in making this setup practical and maintainable, especially when it came to enabling content updates without developer involvement.
I’d be interested to hear from others in the community:
— Has anyone built a similar setup using an SSG?
— Have you used CloudCannon in a more dynamic or application-style project?
Looking forward to hearing how other devs are approaching this!
I am very interested in your solutions for dynamic content as well @Tiaan_Fairchild . The challenge when using Next.js with Cloudcannon is that you need to use output: export. And that means that comes with limitations: Guides: Static Exports | Next.js
Some things, like Next.js Image optimization are easy to tackle by setting the images to unoptimized when in Cloudcannon with an environment variable in the Next config, if you are not using a custom loader. Other things can be more difficult, but my go-to solution is setting up my app so that I can remove my API folder (which uses server side functions) in the Cloudcannon prebuild script without a hassle. If this is not possible I use .env to detect Cloudcannon and render a fallback component that does not use server functions or other output: export limitations like ISR or Nuqs server side filtering. Content editors don’t need those anyway. But it all works fine on production on platforms like Vercel or Netlify which can execute Next start.
Knowing what can and can’t be used with output: export is definitely one of the biggest pain points of using Next.js as an SSG.
When working with Nextjs and CloudCannon, I fully lean into the static-first approach so there is minimal workarounds needed to get CloudCannon working. Anything that would normally rely on server-side functions (API routes, server actions etc.) is handled instead by a separate backend (in this case an Express backend). The Next.js frontend just talks to that backend via standard GET/POST requests. These requests all happen client-side rather than relying on the built-in Next.js API routes, since those require a running server and won’t work with output: export. By shifting everything to our external Express API, the Next.js site stays fully exportable and CloudCannon-friendly while still giving us the dynamic behaviour we need.
For the editing experience, we’ve added skeleton loaders for any truly dynamic content. On CloudCannon’s cloudvent/staging environment, those sections simply display the loaders instead of breaking. And for key areas where editors need to see actual content, we inject dummy data behind an environment variable flag so the static export still works without the backend.
This means the CloudCannon cloudvent sites run perfectly, because the static export doesn’t need to execute any server code. All the dynamic functionality lives in the backend, while the editor experience stays clean and static. Then on production, the same static build step occurs however the Express server is running and serving the static build so everything behaves as expected.