Skip to content

Instantly share code, notes, and snippets.

@abidkhan484
Created May 16, 2026 07:57
Show Gist options
  • Select an option

  • Save abidkhan484/8005c4138060f13d2eb5cf11c325302c to your computer and use it in GitHub Desktop.

Select an option

Save abidkhan484/8005c4138060f13d2eb5cf11c325302c to your computer and use it in GitHub Desktop.

FlexiBar — BFS Fix Implementation Prompt

Use this prompt in a new Antigravity session to implement all fixes identified in the BFS audit (docs/opus-analysis-may16.md).


Context

Read docs/opus-analysis-may16.md for the full audit. FlexiBar scored 74/100 with 5 P0 blockers and 5 P1 high-risk items. This prompt covers implementing all fixes.

You can get the Shopify skills from /home/polymath/.gemini/extensions/shopify-plugin


PHASE 1 — P0 Blockers (Do these first, in order)

P0-1: Migrate REST API to GraphQL

Files to modify:

  • app/shopify.server.js (line 32 — afterAuth hook)
  • app/shop.server.js (line 188 — ensureHeymantleIdentified)

What to do: Both files call https://${shop}/admin/api/2025-07/shop.json via REST fetch. This violates BFS requirement 2.2.4 (GraphQL only for new apps since April 2025).

Replace with GraphQL. The challenge is afterAuth doesn't have admin.graphql directly. Options:

  1. In afterAuth: use unauthenticated.admin(shop) to get a GraphQL client
  2. Or restructure to do the Heymantle identify in the first authenticated route loader instead

For shop.server.js:ensureHeymantleIdentified: it receives { shop, session } — use the session to create an authenticated admin client or pass admin as a parameter from the calling loader.

The existing getShopDetails(graphql) function already demonstrates the correct GraphQL pattern:

query shopInfo {
  shop { name email id }
}

Validation: After fixing, run grep -rn "admin/api" app/ — should return zero results.

P0-2: Fix storefront font loading

File: extensions/inument-flexibar/blocks/inument-flexibar.liquid (line 77)

What to do: Replace the single <link> that loads ALL 6 Google Font families synchronously with:

  1. Load ONLY the font selected by the merchant (via fs.fontFamily)
  2. Use display=optional to prevent FOUT/CLS
  3. Use non-blocking loading pattern: <link rel="preload" as="style" onload="this.onload=null;this.rel='stylesheet'">
  4. Skip the font link entirely if fs.fontFamily == 'system'

Also remove the two <link rel="preconnect"> tags on lines 75-76 and make them conditional (only when a Google Font is actually used).

Validation: Lighthouse audit on storefront should show no render-blocking font requests from the bar.

P0-3: Replace deprecated script_tag Liquid filter

File: extensions/inument-flexibar/blocks/inument-flexibar.liquid (line 79)

What to do:

<!-- BEFORE -->
{{ 'countdown-templates.js' | asset_url | script_tag }}

<!-- AFTER -->
<script src="{{ 'countdown-templates.js' | asset_url }}" defer></script>

Validation: Use the shopify-liquid skill's validate.mjs to confirm the Liquid is valid.

P0-4: Add schema presets

File: extensions/inument-flexibar/blocks/inument-flexibar.liquid (lines 1-7)

What to do: Add presets to the schema block so merchants can discover and add the block from the theme editor:

{% schema %}
{
  "name": "Flexibar",
  "target": "body",
  "settings": [],
  "presets": [
    {
      "name": "Flexibar"
    }
  ]
}
{% endschema %}

P0-5: Implement shop/redact data deletion

File: app/routes/webhooks.shop.redact.jsx

What to do: The handler currently logs and returns 200 but doesn't delete any data. Per GDPR, within 48 hours of uninstall, all merchant data must be purged.

Implement a $transaction that deletes from these tables for the shop:

  • message_translations (via store_bar relation)
  • ai_messages
  • store_bars
  • store_bar_templates
  • subscription_history
  • webhook_logs
  • heymantle
  • store_information
  • Session (should already be deleted by uninstall, but clean up any orphans)

Use the store_domain from shop.split(".")[0] to find the store. Wrap in try/catch. Prefix all logs with [Webhook].

IMPORTANT: This is a real deletion (not soft-delete) because this is the GDPR data erasure webhook. This is the ONE exception to the "soft delete only" rule in GEMINI.md.


PHASE 2 — P1 High Risk

P1-1: Add LiquidDoc header

File: extensions/inument-flexibar/blocks/inument-flexibar.liquid

Add a {% doc %} tag BEFORE the {% schema %} tag:

{% doc %}
  Renders Flexibar announcement bars on the storefront.
  Reads bar configuration from shop.metafields.flexibar.settings.
  Supports single, multiple (slider), and running (marquee) bar types.
{% enddoc %}

P1-2: Replace custom badge with Polaris Badge

File: app/components/FlexibarEmbedStatus.jsx

Replace the custom <span> with hardcoded colors (#1a9e6e, #8c9196) with Polaris Badge component:

  • Enabled → <Badge tone="success">Enabled</Badge>
  • Disabled → <Badge>Disabled</Badge>
  • Unknown → <Badge tone="attention">Unknown</Badge>

P1-3: Fix console.log prefixes

Files:

  • app/routes/webhooks.app.uninstalled.jsx — lines 9, 15 missing [Webhook] prefix
  • app/routes/webhooks.app_subscriptions.update.jsx — multiple lines missing prefix
  • app/routes/webhooks.app.scopes_update.jsx — line 7 missing prefix

Add [Webhook] prefix to all console.log/console.error calls in these files.

P1-4: CLS mitigation

File: extensions/inument-flexibar/blocks/inument-flexibar.liquid

Add a CSS rule that reserves space for the bar before JS runs:

#{{ bar_dom_id }}.fb-bar {
  /* existing styles... */
  min-height: 44px; /* prevents CLS by reserving space before content renders */
  contain: layout style; /* improves rendering performance */
}

P1-5: Inline spacing cleanup in dashboard

File: app/routes/app._index.jsx (DraggableBarRow component)

Replace hardcoded pixel values with Polaris CSS custom properties where possible:

  • padding: "10px 16px" → use var(--p-space-300) and var(--p-space-400)
  • gap: "12px" → use var(--p-space-300)
  • fontSize: "14px" → use Polaris Text component

This is lower priority but shows BFS reviewers you follow Polaris conventions.


PHASE 3 — P2 Polish (if time permits)

  1. Extract inline JS from Liquid template into a separate flexibar-runtime.js asset file loaded with defer
  2. Reduce z-index: 999999 to 9999 in the .fb-bar CSS
  3. Review if read_products scope is truly needed — it's only used for collection listing in page targeting
  4. Add error handling for getShopGid in metafield.service.js

After All Fixes

  1. Run grep -rn "admin/api" app/ — should return 0 results
  2. Run grep -rn "script_tag" extensions/ — should return 0 results
  3. Run Lighthouse on storefront with bar active — target < 10 point drop
  4. Test full flow: install → onboard → create bar → publish → verify on storefront
  5. Verify all GDPR webhooks work correctly
  6. Re-read docs/opus-analysis-may16.md and confirm each P0/P1 item is resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment