Two lines. Any stack.
The fastest way in: copy the snippet for your framework, replace YOUR_PROJECT_ID with your project id, and drop it into your root layout or base template. Done.
Watch the full walkthrough on YouTube — setup, middleware and layout explained step by step.
One <my-widget> element plus one <script> tag — that's the whole integration. No SDK, no config file, no build step.
The web component renders a floating feedback button. Visitors click it, rate and leave a message.
Every rating and message appears instantly in your MilkyWay dashboard, ready to act on.
Two pieces make the widget work on this site, and the same pattern applies on yours:
middleware.ts intercepts /widget.umd.js and rewrites it to the widget host before the browser ever sees it. The embed stays same-origin — no external domain in your code, and the script is served from your own domain.
// middleware.ts — proxy
if (pathname === "/widget.umd.js") {
return NextResponse.rewrite(
new URL("https://embeddales.vercel.app/widget.umd.js")
);
}The root layout renders the my-widget element and loads the proxied script. Because it lives in the layout, the widget appears on every page — one edit, whole site.
// app/layout.tsx
<my-widget project-id="38" />
<Script strategy="afterInteractive"
src="/widget.umd.js" />The flow: browser requests /widget.umd.js → middleware rewrites it to the widget host → the script arrives from your own origin → the web component upgrades <my-widget> into the floating feedback button. No SDK, no build step, no third-party script tag in your HTML.
app/layout.tsx
import Script from "next/script";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
{/* MilkyWay feedback widget — script proxied via middleware */}
<my-widget project-id="YOUR_PROJECT_ID"></my-widget>
<Script strategy="afterInteractive" src="/widget.umd.js" />
</body>
</html>
);
}src/App.jsx
import { useEffect } from "react";
function App() {
// Load the widget script once (served via the MilkyWay proxy).
useEffect(() => {
const s = document.createElement("script");
s.src = "/widget.umd.js";
s.async = true;
document.body.appendChild(s);
return () => document.body.removeChild(s);
}, []);
return (
<div>
{/* MilkyWay feedback widget — web component in JSX */}
<my-widget project-id="YOUR_PROJECT_ID"></my-widget>
{/* rest of your app */}
</div>
);
}
export default App;templates/base.html
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>{% block title %}My Site{% endblock %}</title>
</head>
<body>
{% block content %}{% endblock %}
<!-- MilkyWay feedback widget -->
<my-widget project-id="YOUR_PROJECT_ID"></my-widget>
<script src="https://www.mrdmilkyway.com/widget.umd.js"></script>
</body>
</html>index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>My Site</title>
</head>
<body>
<h1>Hello world</h1>
<!-- MilkyWay feedback widget -->
<my-widget project-id="YOUR_PROJECT_ID"></my-widget>
<script src="https://www.mrdmilkyway.com/widget.umd.js"></script>
</body>
</html>script line once per page — you can place multiple my-widget elements if you want the button in more than one place./widget.umd.js — a relative path served by our middleware proxy. On other domains, use the full $https://www.mrdmilkyway.com/widget.umd.js URL.