A minimal MotherDuck Wasm setup with vanilla JS and (almost) no build step
I’ve been using MotherDuck’s Wasm client a lot lately, but I always forget how to set up a new project to get started with it.
On top of this, Claude tends to get very confused when I ask for boilerplate here — errors range from a misspelled package name for npm install
to thinking we need to deal with bundle selection and workers like in the lower-level DuckDB-Wasm documentation.
Meanwhile MotherDuck’s examples (and AI-powered app builder!) are great but they’re all built with React, so there’s a lot of extra stuff in there.
For new projects these days when I don’t think I’ll need Vue for complex state management I tend to use vanilla JS — and prefer as few build steps as possible.
Here’s a minimal setup that works. First we install the wasm-client package into a new vite project:
npm create vite@latest
cd vite-project
npm install --save @motherduck/wasm-client
Next, make a really simple main Javascript entry point that just exposes a MotherDuck factory as a global function:
cat > src/main.js <<EOF
import { MDConnection } from '@motherduck/wasm-client';
window.MotherDuck = mdToken => MDConnection.create({ mdToken });
EOF
We also need to make sure we’re serving our page in cross-origin isolation mode, so we’ll write some headers in the vite.config.js file:
cat > vite.config.js <<EOF
import { defineConfig } from "vite";
export default defineConfig({
server: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
},
});
EOF
That’s it! Start the dev server:
npm run dev
And now we can just write our code in the Javascript file — or even directly in index.html
if we prefer:
<script type="module" src="/src/main.js"></script>
<script type="module">
const connection = MotherDuck(MY_TOKEN);
const result = await connection.evaluateQuery('SHOW DATABASES');
console.log(result.data.toRows());
</script>
However you write it and wherever you deploy it, you’ll just need to make sure that your eventual production server retains those HTTP headers.