Source Maps
Production JavaScript is minified, so raw stack traces point at meaningless positions like
index-Cd3xyz.js:1:54321. Upload your build's source maps and booboo rewrites those
frames to the original file, line, and function — with the surrounding source code — before
grouping the error into an issue.
How it works
Symbolication happens server-side in booboo's processing pipeline, before fingerprinting.
Your maps are stored compressed, are never served publicly, and are only readable by your
organization. You don't need to deploy .map files to your CDN — booboo only
needs the uploaded copy. Frames that resolve through a map show a
source maps applied badge in the stack trace, with the original minified
position preserved alongside.
Events ingested before their map was uploaded are grouped using minified frames and will form a separate issue from later, symbolicated events. Upload maps as part of your deploy, before traffic hits the new bundle.
Generate source maps
Enable source map output in your bundler's production build:
Vite (React, Vue, vanilla)
// vite.config.ts
import { defineConfig } from "vite";
export default defineConfig({
build: {
sourcemap: true,
},
}); Next.js
// next.config.js
module.exports = {
productionBrowserSourceMaps: true,
}; Webpack
// webpack.config.js
module.exports = {
devtool: "source-map",
};
If you don't want your maps publicly reachable, that's fine — upload them to booboo and
exclude them from your deploy artifact (Vite's sourcemap: "hidden" also works).
Upload from CI
Uploads authenticate with your project's DSN secret — find it in Project Settings → Source Maps (admins only). Unlike the public DSN, the secret must never ship to browsers; keep it in your CI's secret store.
# After your production build, upload every map (e.g. in CI):
for f in dist/assets/*.js.map; do
curl -s -X POST https://api.booboo.dev/sourcemaps/ \
-H "X-Booboo-DSN-Secret: $BOOBOO_DSN_SECRET" \
-F "release=$GITHUB_SHA" \
-F "file=@$f"
done The response lists stored artifacts and any per-file errors:
{
"artifacts": [
{ "id": 12, "name": "index-Cd3xyz.js", "release": "3f1a9c2", "size": 812345 }
],
"errors": []
} Re-uploading a file with the same name and release overwrites the previous copy. You can also drag-and-drop maps in Project Settings → Source Maps for a quick manual test.
Releases
Maps are matched to events by the minified file's basename
(e.g. index-Cd3xyz.js). Content-hashed bundle names make this reliable on its own.
If your bundles have stable names (like bundle.js), set a release
on both sides so each deploy's events match that deploy's maps:
import * as booboo from "@booboo.dev/js";
booboo.init({
dsn: "https://YOUR_TOKEN@ingest.booboo.dev/your-org/your-project",
environment: "production",
release: import.meta.env.VITE_RELEASE, // e.g. the git SHA, set at build time
});
Pass the same value as the release form field when uploading (a git SHA works
well). Matching is exact-release first, then falls back to maps uploaded without a release.
The release init option requires SDK @booboo.dev/js@0.8.0 or newer.
Limits & retention
- Maximum 20 MB per source map file.
- Total per-project storage: 50 MB on Free, 250 MB on Starter, 1 GB on Team.
- Artifacts are kept for 180 days from their last upload; when a project exceeds its storage cap, the oldest artifacts are removed first.
Troubleshooting
- Frames stay minified: check the artifact list in Project Settings — the uploaded file's name (minus
.map) must match the bundle's basename in the stack trace. - Column numbers required: symbolication needs
colnoon frames, captured automatically by@booboo.dev/js0.7.0+. - Release mismatch: if you upload with a release but the SDK doesn't send one (or sends a different value), matching falls back to release-less maps only. Align both, or upload without a release.
- Indexed maps: source maps with a
sectionskey aren't supported yet — configure your bundler to emit flat maps. - Old events don't change: symbolication runs at ingestion; uploading maps doesn't rewrite previously stored events.