app-shopify-built-for-shopify
Built for Shopify Guidelines
This skill enforces Shopify's Built for Shopify (BFS) quality standards during development to ensure apps meet the highest quality bar for the Shopify App Store.
Reference: https://shopify.dev/docs/apps/launch/built-for-shopify/requirements
Quick Compliance Checklist
Use this checklist when reviewing code or building features:
BFS Compliance Review:
- [ ] App is embedded in Shopify admin (App Bridge)
- [ ] Uses session token authentication
- [ ] Primary workflows stay within Shopify admin
- [ ] No additional login/signup required
- [ ] Uses theme app extensions (not Asset API for writes)
- [ ] Meets Web Vitals targets (LCP ≤2.5s, CLS ≤0.1, INP ≤200ms)
- [ ] Uses Polaris components matching admin styling
- [ ] Mobile responsive design
- [ ] Uses nav menu (s-app-nav) and contextual save bar
- [ ] Error messages are red, contextual, and helpful
- [ ] No dark patterns or pressure tactics
- [ ] Premium features are disabled and labeled
- [ ] Promotional content is dismissible
1. Integration Requirements
Embedding (MANDATORY)
Apps MUST be embedded in the Shopify admin:
<!-- Add to <head> of every document -->
<script src="https://cdn.shopify.com/shopifycloud/app-bridge.js"></script>
// Use session token authentication
import { authenticate } from "@shopify/shopify-app-remix/server";
export async function loader({ request }) {
const { session } = await authenticate.admin(request);
// ...
}
Primary Workflows
All primary app workflows MUST be completable within the Shopify admin:
- No external website required for core functionality
- Third-party connection settings must be accessible in-app
- Simplified monitoring/reporting on app homepage
Clean Installation
For storefront apps, use theme app extensions instead of Asset API:
<!-- extensions/theme-extension/blocks/my-block.liquid -->
{% schema %}
{
"name": "My App Block",
"target": "section",
"settings": []
}
{% endschema %}
Do NOT use Asset API to create, modify, or delete theme files (reading is allowed).
2. Performance Requirements
Web Vitals Targets (75th percentile)
| Metric | Target | Description |
|---|---|---|
| LCP | ≤ 2.5s | Largest Contentful Paint |
| CLS | ≤ 0.1 | Cumulative Layout Shift |
| INP | ≤ 200ms | Interaction to Next Paint |
Optimization Strategies
// Lazy load heavy components
const HeavyChart = lazy(() => import('./HeavyChart'));
// Use React.memo for expensive renders
const ExpensiveList = memo(({ items }) => (
// ...
));
// Avoid layout shifts with skeleton loaders
<Suspense fallback={<SkeletonPage />}>
<AppContent />
</Suspense>
Storefront Performance
- Must not reduce Lighthouse score by more than 10 points
- Checkout requests: p95 ≤ 500ms, failure rate ≤ 0.1%
3. Design Requirements
Familiar (Match Shopify Admin)
Use Polaris web components to match admin styling:
<!-- Use s-page for page structure -->
<s-page>
<s-title-bar title="My Page">
<s-button slot="primary-action">Save</s-button>
</s-title-bar>
<s-layout>
<s-layout-section>
<s-card>
<s-text>Content in cards</s-text>
</s-card>
</s-layout-section>
</s-layout>
</s-page>
Rejection reasons to avoid:
- Custom button colors (use Polaris defaults)
- Serif/script fonts
- Non-standard background colors
- Content not in card containers
- Poor contrast (must meet WCAG 2.1 AA)
Navigation
Use App Bridge nav menu:
<s-app-nav>
<s-nav-item href="/dashboard" selected>Dashboard</s-nav-item>
<s-nav-item href="/settings">Settings</s-nav-item>
</s-app-nav>
Do NOT:
- Create custom navigation menus
- Use emojis in nav items
- Have separate "Home" link (app name should link to home)
Contextual Save Bar
Use for all form inputs:
import { useAppBridge } from "@shopify/app-bridge-react";
import { SaveBar } from "@shopify/app-bridge/actions";
function SettingsForm() {
const app = useAppBridge();
const showSaveBar = () => {
const saveBar = SaveBar.create(app, {
saveAction: { disabled: false, loading: false },
discardAction: { disabled: false, loading: false },
});
saveBar.dispatch(SaveBar.Action.SHOW);
};
// ...
}
Modals
Use s-modal with proper slots:
<s-modal heading="Confirm Action">
<p>Modal content here</p>
<s-button slot="secondary-action">Cancel</s-button>
<s-button slot="primary-action" variant="primary">Confirm</s-button>
</s-modal>
Mobile Responsiveness
- No horizontal scrolling on mobile
- Content must wrap/stack appropriately
- All content accessible (no hidden without expand mechanism)
4. Helpful UX Requirements
Onboarding
- Concise, guiding merchants to completion
- Dismissible after completion
- No requirement to install additional apps
- Justify any merchant information requests
Homepage
Must include:
- Theme block/embed status (if applicable)
- Relevant metrics/analytics
- Dynamic content (not just static links)
Error Messages
<!-- CORRECT: Red, contextual, persistent -->
<s-text-field
label="Email"
error="Please enter a valid email address"
/>
<!-- WRONG: Using toast for errors -->
<!-- WRONG: Non-red error colors -->
<!-- WRONG: Top-of-page errors for field issues -->
5. User-Friendly Requirements (No Dark Patterns)
Prohibited Practices
| Don't | Why |
|---|---|
| Countdown timers for upgrades | Pressures merchants |
| "No thanks, I prefer less sales" | Guilt/shame language |
| Auto-appearing modals/popovers | Distracts merchants |
| Guarantee outcomes ("increase sales 18%") | False claims |
| Review incentives ("5-star for Pro") | Manipulative |
| Non-dismissible promotions | Overwhelms merchants |
| Shopify-like icons/colors | Impersonation |
Premium Features
<!-- Features must be visually AND functionally disabled -->
<s-card>
<s-text variant="headingMd">Advanced Analytics</s-text>
<s-badge tone="info">Pro Plan</s-badge>
<s-button disabled>View Analytics</s-button>
<s-link url="/upgrade">Upgrade to unlock</s-link>
</s-card>
- Shopify Plus-only features must be hidden (not just disabled) for non-Plus merchants
6. Category-Specific Requirements
If Building: Ads/Analytics/Affiliate Apps
// MUST use Web Pixel extensions, NOT script tags
// extensions/web-pixel/src/index.ts
import { register } from "@shopify/web-pixels-extension";
register(({ analytics }) => {
analytics.subscribe("page_viewed", (event) => {
// Track event
});
});
If Building: Email/SMS Marketing Apps
- Sync customer data to/from Shopify
- Use Shopify segments via customer segment action extension
- Use visitors API for identifying store visitors
If Building: Discount Apps
# Use discount functions or native APIs
# Do NOT use draft orders for custom discounts
# Use discountRedeemCodeBulkAdd for multiple codes
mutation {
discountRedeemCodeBulkAdd(
discountId: "gid://shopify/DiscountCodeNode/123"
codes: [{ code: "CODE1" }, { code: "CODE2" }]
) {
bulkCreation {
id
}
}
}
If Building: Subscription Apps
- Use Selling Plan API, Subscription Contract API, Customer Payment Method API
- Use theme app blocks for product pages
- Display subscription info clearly (name, price, savings)
- Use Customer Account UI extensions for subscription management
If Building: Fulfillment Apps
- Wait for merchant fulfillment requests before fulfilling
- Respond to fulfillment requests within 4 hours
- Respond to cancellation requests within 1 hour
- Add tracking info within 1 hour of fulfillment creation
- 99% completion rate, 99.9% callback success rate
If Building: Returns Apps
Sync all return lifecycle events:
- returnCreate, reverseDeliveryCreateWithShipping
- reverseFulfillmentOrderDispose, returnLineItemRemoveFromReturn
- returnCancel, returnClose, refundCreate
Code Review Checklist
When reviewing Shopify app code for BFS compliance:
Technical:
- [ ] App Bridge script in <head>
- [ ] Session token auth (no cookie auth)
- [ ] Theme app extensions (no Asset API writes)
- [ ] Web Pixel extensions (no script tags for tracking)
- [ ] Proper API usage for app category
UI/UX:
- [ ] Polaris components throughout
- [ ] s-app-nav for navigation
- [ ] Contextual save bar for forms
- [ ] s-modal with proper slots
- [ ] Responsive design
- [ ] WCAG 2.1 AA contrast
Content:
- [ ] No outcome guarantees
- [ ] No pressure tactics
- [ ] Dismissible promotional content
- [ ] Disabled + labeled premium features
- [ ] Clear error messages (red, contextual)
- [ ] Helpful onboarding
- [ ] Dynamic homepage content