← Back to docs

Frontend Script Boxes

Language: EN | EN | SV

Frontend Script Boxes

Frontend Script Boxes let operators keep small JavaScript customizations inside Tools and reuse them across multiple frontend surfaces.

Current supported surfaces:

  • vbulletin – for forum/frontend HTML snippets and vBulletin-specific tweaks
  • feed – for /feed-related widgets, embeddable news boxes, and script-driven external site integrations

Admin surfaces

vBulletin admin

  • URL: /admin/security/vbulletin
  • Access: admin-only
  • Section: vBulletin frontend script boxes

Feed admin

  • URL: /feed-admin
  • Access: permission:rss
  • Section: Feed script snippets / embeddable widgets

What each script box contains

Each saved box currently supports:

  • Script title – human-readable operator label
  • External script src (optional) – URL that should be loaded as <script src="…">
  • AI instructions – operator prompt used to auto-generate or rewrite the inline script
  • Inline script – raw JavaScript body (no surrounding <script> tag)
  • Sort order – execution/load order inside the merged bundle
  • Enabled – disabled boxes stay saved in admin but are not included in the public bundle/API output

AJAX + autosave behavior

  • Add script creates a new blank script box over AJAX
  • Field changes autosave on blur/change
  • Save now forces an immediate AJAX save
  • AI → script stores the current field values, sends the AI instruction to Tools/OpenAI, and overwrites the inline script body with the generated JavaScript
  • Delete removes the box over AJAX

Public API endpoints

GET /api/managed-scripts/{surface}

Returns the current public/active script boxes for one surface.

Allowed surface values:

  • vbulletin
  • feed

Query parameters

  • format=both (default) – return both the merged script and the separated scripts[]
  • format=merged – return only the merged bundle text
  • format=separate – return only the separated scripts[]
  • feed_ids=63,91 or feeds=63,91 – optional feed URL ids for feed-widget bundles that should target specific feeds
  • categories=coding,fact-check, groups=coding,fact-check, or category_slugs=coding,fact-check – optional category/group slugs for feed-widget bundles
  • limit=10 – optional item/widget limit hint, clamped to 1..100

For the feed surface these query values are normalized and echoed back as query_context.filters, so embeddable widgets can react to the selected feeds/groups without inventing their own parsing rules.

Example response

{
  "ok": true,
  "surface": "feed",
  "count": 2,
  "bundle_url": "https://tools.tornevall.net/api/managed-scripts/feed/bundle.js",
  "bundle_tag": "<script src=\"https://tools.tornevall.net/api/managed-scripts/feed/bundle.js\"></script>",
  "query_context": {
    "surface": "feed",
    "filters": {
      "feed_ids": [63],
      "category_slugs": ["coding"],
      "limit": 10
    },
    "has_filters": true
  },
  "scripts": [
    {
      "id": 7,
      "surface": "feed",
      "title": "Compact feed widget",
      "script_body": "(() => { console.log('feed widget'); })();",
      "script_src": "",
      "ai_instruction": "Render a compact feed card widget",
      "sort_order": 10,
      "is_enabled": true,
      "updated_by_user_id": 1,
      "updated_at": "2026-04-27T21:40:00+00:00"
    },
    {
      "id": 8,
      "surface": "feed",
      "title": "External feed helper",
      "script_body": "",
      "script_src": "https://cdn.example.com/feed-helper.js",
      "ai_instruction": "",
      "sort_order": 20,
      "is_enabled": true,
      "updated_by_user_id": 1,
      "updated_at": "2026-04-27T21:41:00+00:00"
    }
  ],
  "merged_script": "(function(){\nwindow.__toolsManagedScriptBoxes = ..."
}

GET /api/managed-scripts/{surface}/bundle.js

Returns a ready-to-embed JavaScript bundle for the selected surface.

This route is intended for direct browser/frontend use, for example:

<script src="https://tools.tornevall.net/api/managed-scripts/vbulletin/bundle.js"></script>

Feed-widget example with explicit filters:

<script src="https://tools.tornevall.net/api/managed-scripts/feed/bundle.js?feed_ids=63&categories=coding&limit=10"></script>

How the merged bundle works

The merged bundle currently:

  • loads enabled boxes only
  • sorts them by sort_order, then by id
  • injects each saved script_src as an external <script src> loader
  • executes each inline script body once per page load using an internal window.__toolsManagedScriptBoxes guard
  • exposes normalized embed filters at window.__toolsManagedScriptBoxes.context.filters (feed_ids[], category_slugs[], limit)

Typical usage examples

vBulletin

  • swap logos/themes on selected pages
  • inject forum-specific helpers into HTML snippet areas
  • patch DOM text/labels for forum workflows

Feed widgets

  • render a small /feed news card on an arbitrary external site
  • fetch /api/rss or /api/rss/feed/{selector} and present custom compact summaries
  • combine a reusable external helper script with smaller per-site inline overrides

Notes

  • The current AI helper generates JavaScript only, not full HTML pages or build-tool projects.
  • If you need markup, describe the desired DOM structure in AI instructions and let the generated JavaScript inject that markup.
  • Do not paste surrounding <script> tags into the inline script field.