The devtools overlay
Mount the in-app devtools overlay so you and your team can file bugs and feature requests without leaving the product.
The devtools overlay is the in-app panel behind every bug report and feature request. It mounts as an isolated, shadow-DOM floating rail on your own site, captures the page context for you, and posts straight into your project's feedback queue. The same overlay also surfaces your flags, configs, experiments, and i18n keys, so it doubles as a control panel while you're building.
It ships as a standalone script that works on any platform — Next.js, Rails, Django, Laravel, static HTML — without requiring a server-side SDK or a build step.
Add the script tag
Drop this into your HTML <head> (or your framework's equivalent):
<script
src="https://cdn.shipeasy.ai/se-devtools.js"
data-client-api-key="YOUR_CLIENT_KEY"
data-project-id="YOUR_PROJECT_ID"
></script>Both attributes are required. If either is missing the script logs a clear
console.error and exits without mounting anything.
| Attribute | Where to find it |
|---|---|
data-client-api-key | Dashboard → Settings → API Keys → Client key (public, safe in HTML) |
data-project-id | Dashboard → Settings → Project ID |
Open the overlay
~30 secondsDrop the script tag into <head>
Works in any HTML template regardless of backend language or framework.
Append ?se to any page
The rail appears bottom-right. Toggle it any time with Shift+Alt+S.
Sign in once, then report
First open prompts a one-time sign-in popup. The report lands in your dashboard within seconds.
The overlay is loaded lazily — the script tag itself adds no visible weight to normal page loads.
It only activates when ?se=1 is in the URL or the user presses Shift+Alt+S.
Next.js / TypeScript
In a Next.js App Router root layout, read the keys from env:
// app/layout.tsx
export default async function RootLayout({ children }) {
return (
<html>
<head>
<script
src={
process.env.NODE_ENV !== "production"
? "/se-devtools.js" // local build
: "https://cdn.shipeasy.ai/se-devtools.js"
}
data-client-api-key={process.env.NEXT_PUBLIC_SHIPEASY_CLIENT_KEY}
data-project-id={process.env.NEXT_PUBLIC_SHIPEASY_PROJECT_ID}
/>
</head>
<body>{children}</body>
</html>
);
}Add to .env.local (or your CI secrets):
NEXT_PUBLIC_SHIPEASY_CLIENT_KEY=se_live_client_…
NEXT_PUBLIC_SHIPEASY_PROJECT_ID=<your-project-id>Mount it unconditionally with init()
For programmatic control — always-on internal tools, staging builds, demos — call
init() directly from any JavaScript:
import { init as initDevtools } from "@shipeasy/devtools";
initDevtools({ accentColor: "var(--brand)" });init() is framework-agnostic — call it from a useEffect, onMounted, or a
plain inline <script>. It is idempotent and tears itself down via destroy().
Prop
Type
Signing in
The overlay is team-facing and authenticated. On first open it pops a window to
{adminUrl}/devtools-auth, you approve access, and it stores a short-lived,
browser-scoped admin token in sessionStorage (valid ~10 minutes). Reports post
to the admin endpoints (POST /api/admin/bugs, /api/admin/feature-requests) with
that token — no cookies, no SDK key embedded in the page.
If the sign-in popup never returns or the overlay never appears, check that the
<script> tag with both data-client-api-key and data-project-id is present
in the page source. Open the browser console — a missing attribute logs a clear
error.
What a report captures
The bug form asks for a title, steps to reproduce, actual result, expected result, and an optional priority. On top of what the user types, the overlay attaches the page context automatically:
Auto-attached context→
pageUrl (the current location.href), userAgent, and viewport (width×height) — so a
report is reproducible without asking "where were you?"
Screenshot & screen recording→
One click grabs a screenshot or a screen recording (with audio) via the browser's
getDisplayMedia() and uploads it alongside the report.
Feature requests use the same flow with a title, description, and use-case, plus the same auto-attached page context.
Demo mode
Pass seed to skip the sign-in popup and preload a project — useful for marketing
pages, screenshots, and tests. Seeded values are written to sessionStorage only
when absent, so a real session is never clobbered:
initDevtools({
seed: {
session: { token: "demo", projectId: "proj_demo" },
project: { id: "proj_demo", name: "Acme", modules: { feedback: true } },
activePanel: "feedback",
},
});Verify the install
# The overlay needs the Feedback module enabled — toggle it in
# Settings → Modules in the dashboard, then verify from the CLI:
shipeasy ops list --type bug # expect [] or rows, never 403
# then load any page with ?se=1 and confirm the rail appears/shipeasy:ops:install runs these checks for you and drops the project pointer
skills.
Where to next
The one shipeasy() boot the overlay rides on.
Auto-capture and see() — a separate flow from the manual overlay.
Custom report buttons, Slack forwarding, roadmap voting.
Read →