Integrating Qwik with Builder.io/Visual Editor

Hi friends!

I’m new to both Builder.io and Qwik, and I’m very excited about both projects. But I’m having some difficulty getting them to play nice together and I’m wondering if I’m doing something wrong.

I’m having difficulty getting the Visual Editor to integrate with my Qwik site. My Qwik page itself seems to work fine and the Preview Iframe shows an accurate representation of my site, but it shows a page load error and none of the basic components on the left panel are loading for me to add to the page.

I made a React page for comparison and it seems to work just fine with the Visual Editor.

I’ve followed through much of the suggested troubleshooting, which I will detail below, but something popped up that I want to highlight in case it’s relevant.

One thing to note is that I have been using the dev server and my localhost in these cases. While troubleshooting I discovered that when I add the Builder component to my code and try to npm run preview, the build fails. Building without adding the Builder component works fine.

It seems to have difficulty with old references to mutable() in the codebase?

I didn’t want to get too far over my head with that yet in case it’s a rabbit hole, so I figured I’d check in here first :smile_cat:

I considered trying a different version of Builder.io or Qwik but a cursory search for a way to do that proved fruitless. If anyone can show me how to do so I’d be happy to try that out!

Troubleshooting steps taken:

  • Verified my server at my URL is running as expected
  • Allowed “unsafe” content
  • Made sure I have the right preview URL configured for my page model and it has the correct Builder.io content for this model on it
  • Tried the Chrome extension
  • Set a persistent preview URL
  • Toggled Reload preview on URL path change to the off position
  • Set Proxy previews to the on position.
  • Investigated setting a custom 404, but I wanted to check in before going down a possible rabbit hole (that seems redundant with the previous two points anyway)

Am I missing something obvious? :sweat_smile:

Thanks in advance for any and all help! :blue_heart:

Builder content link

Builder public api key
2d34fe55a5374dbfb33fe72dd150d17f

What are you trying to accomplish
I want to edit my Qwik page with the Visual Editor

Screenshots or video link
React works:

Qwik does not:

Code stack you are integrating Builder with
QwikCity, Qwik

Reproducible code example
React works (App.js):

import logo from './logo.svg';
import './App.css';
import CatchAllRoute from './CatchAllRoute';

function App() {
  return (
    <div className="App">
      <CatchAllRoute />
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.js</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
      </header>
    </div>
  );
}

export default App;

React works (CatchAllRoute.js):

import { useEffect, useState } from "react";
import { BuilderComponent, builder, useIsPreviewing } from "@builder.io/react";
import App from "./App";

// Put your API key here
builder.init("2d34fe55a5374dbfb33fe72dd150d17f");

// set whether you're using the Visual Editor,
// whether there are changes,
// and render the content if found
export default function CatchAllRoute() {
  const isPreviewingInBuilder = useIsPreviewing();
  const [notFound, setNotFound] = useState(false);
  const [content, setContent] = useState(null);

  // get the page content from Builder
  useEffect(() => {
    async function fetchContent() {
      const content = await builder
        .get("page", {
          url: window.location.pathname
        })
        .promise();

      setContent(content);
      setNotFound(!content);
    }
    fetchContent();
  }, [window.location.pathname]);
  
  // if no page is found, return a 404 page
  if (notFound && !isPreviewingInBuilder) {
    return <App/>
  }

  // return the page when found
  return (
    <>
      <head>
        <title>{content?.data.title}</title>
      </head>
      {/* Render the Builder page */}
      <BuilderComponent model="page" content={content} />
    </>
  );
}

Qwik does not (routes/index.tsx):

import { component$, Resource, useResource$ } from "@builder.io/qwik";
import { useLocation } from "@builder.io/qwik-city";
import { getContent, RenderContent, getBuilderSearchParams } from "@builder.io/sdk-qwik";

export const BUILDER_PUBLIC_API_KEY = "2d34fe55a5374dbfb33fe72dd150d17f"; 
export const BUILDER_MODEL = "page";
export default component$(() => {
  const location = useLocation();
  const builderContentRsrc = useResource$<any>(() => {
    return getContent({
      model: BUILDER_MODEL,
      apiKey: BUILDER_PUBLIC_API_KEY,
      options: getBuilderSearchParams(location.query),
      userAttributes: {
        urlPath: location.pathname || "/",
      },
    });
  });

  return (
    <Resource
      value={builderContentRsrc}
      onPending={() => <div>Loading...</div>}
      onResolved={(content) => (
        <RenderContent
          model={BUILDER_MODEL}
          content={content}
          apiKey={BUILDER_PUBLIC_API_KEY}
        />
      )}
    />
  );
});

Building for preview without the Builder component works:

$ npm run preview

> preview
> qwik build preview && vite preview --open


vite build
vite build --ssr src/entry.preview.tsx

vite v3.1.7 building for production...
✓ 47 modules transformed.
dist/q-manifest.json        11.23 KiB
dist/build/q-d8ba39a6.js    0.06 KiB / gzip: 0.07 KiB
dist/build/q-8c2d0758.js    4.26 KiB / gzip: 2.10 KiB
dist/build/q-3555fa77.js    0.26 KiB / gzip: 0.22 KiB
dist/build/q-5590c870.js    1.49 KiB / gzip: 0.84 KiB
dist/build/q-d22a55ed.js    0.83 KiB / gzip: 0.49 KiB
dist/build/q-44a403b1.js    0.85 KiB / gzip: 0.47 KiB
dist/build/q-6c5a35e1.js    0.61 KiB / gzip: 0.27 KiB
dist/build/q-ac7432c2.js    0.20 KiB / gzip: 0.16 KiB
dist/build/q-a848e0ce.js    0.26 KiB / gzip: 0.20 KiB
dist/build/q-5ba55c44.js    0.26 KiB / gzip: 0.20 KiB
dist/build/q-e5e06d00.js    0.11 KiB / gzip: 0.11 KiB
dist/build/q-27801b00.js    0.43 KiB / gzip: 0.29 KiB
dist/build/q-49d59090.js    2.82 KiB / gzip: 0.87 KiB
dist/build/q-392ff273.js    2.41 KiB / gzip: 1.11 KiB
dist/service-worker.js      2.48 KiB / gzip: 1.18 KiB
dist/build/q-1916b01a.js    39.52 KiB / gzip: 15.97 KiB
dist/build/q-0ea8883c.css   1.58 KiB / gzip: 0.79 KiB
dist/build/q-51aa422a.js    3.99 KiB / gzip: 1.99 KiB

✓ Built client modules
✓ Built preview (ssr) modules

  ➜  Local:   http://localhost:4173/
  ➜  Network: use --host to expose

Building for preview with Builder component in code throws errors:

$ npm run preview

> preview
> qwik build preview && vite preview --open


vite build
vite build --ssr src/entry.preview.tsx

vite v3.1.7 building for production...
✓ 98 modules transformed.
'_useMutableProps' is not exported by node_modules/@builder.io/qwik/core.min.mjs, imported by src/s_ca0svhikr5g.js
file: .../qwik-app/src/s_ca0svhikr5g.js:2:9
1: import { _track } from "../node_modules/@builder.io/sdk-qwik/lib/index.qwik";
2: import { _useMutableProps } from "@builder.io/qwik";
            ^
3: import { allRegisteredComponents } from "../node_modules/@builder.io/sdk-qwik/lib/index.qwik";
4: import { canTrackToUse } from "../node_modules/@builder.io/sdk-qwik/lib/index.qwik";
error during build:
Error: '_useMutableProps' is not exported by node_modules/@builder.io/qwik/core.min.mjs, imported by src/s_ca0svhikr5g.js
    at error (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:1858:30)
    at Module.error (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:12429:16)
    at Module.traceVariable (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:12788:29)
    at ModuleScope.findVariable (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:11440:39)
    at ReturnValueScope.findVariable (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:6372:38)
    at ChildScope.findVariable (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:6372:38)
    at TrackingScope.findVariable (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:6372:38)
    at BlockScope.findVariable (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:6372:38)
    at TrackingScope.findVariable (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:6372:38)
    at BlockScope.findVariable (file:///.../qwik-app/node_modules/rollup/dist/es/shared/rollup.js:6372:38)