App Review
How the Reeve App Store review process works, quality requirements, security standards, and common rejection reasons.
App Review Guidelines
Every app submitted to the Reeve Marketplace goes through a review process to protect merchants and maintain platform quality. This page explains exactly what reviewers check and how to ensure your app passes on the first submission.
The Review Process
Submit Your App
Go to meetreeve.com/developers/submit and submit:
- Your production app URL (must be HTTPS)
- Your
reeve-manifest.json - Your app icon (512×512 PNG)
- At least 2 screenshots (1280×800 PNG recommended)
- A short description of what the app does and how reviewers can test it
Current review SLA: 3–5 business days for initial review, 1–2 days for resubmissions.
Automated Check
The moment you submit, an automated scanner runs:
- Manifest validation (all required fields, valid permissions, valid semver)
- Permission audit: scans your app bundle for SDK calls and verifies they match declared permissions
- Load time test: your app must be interactive within 5 seconds on a standard connection
- HTTPS verification: the app URL and all loaded resources must use HTTPS
- CSP check: your app must not load scripts from untrusted external domains
If the automated check fails, you receive an email with specific errors within minutes. Fix and resubmit — automated checks don't count against your review attempt count.
Manual Review
A Reeve reviewer installs your app in a test Cockpit with a connected Shopify store and evaluates it against the quality bar below. Reviewers test both light and dark themes.
You receive feedback via email with specific, actionable notes. Most apps need 1–2 rounds of revision before approval.
Approved & Published
Once approved, your app appears in the Marketplace within 24 hours. Reeve handles:
- App listing page
- Install flow with permission consent
- Subscription billing and trials
- Merchant support escalations (serious bugs get expedited review)
Quality Bar Requirements
Functionality
| Requirement | Pass Criteria |
|---|---|
| Core use case works end-to-end | A reviewer can complete the primary workflow without confusion |
| Loading states shown | Skeleton loaders or spinners shown while data fetches; no blank white flashes |
| Error states handled | If a data source is unavailable, app shows a helpful message (not a raw error or blank screen) |
| Empty states handled | If a collection is empty (no orders, no drafts), the app shows a friendly empty state |
| No console errors | The browser console must be clean during normal usage |
Performance
| Metric | Requirement |
|---|---|
| Time to Interactive | < 5 seconds on a standard connection |
| First Contentful Paint | < 2 seconds |
| Memory usage | App must not grow unbounded with normal use (memory leak check) |
| Polling intervals | If polling data, minimum interval is 30 seconds |
Security Requirements
Data Handling
No external data exfiltration. Your app must not send merchant data (orders, customers, revenue figures, etc.) to any server outside of Reeve's SDK APIs. Reviewers inspect network requests during review. Sending merchant data to a third-party analytics service (Mixpanel, Amplitude, Segment, etc.) is grounds for rejection unless explicitly disclosed and consented to.
Permissions must match usage. The automated scanner checks that every SDK method you call has a corresponding permission in your manifest. Requesting permissions you don't use is also rejected — over-permission is a red flag.
Storage is scoped. You cannot access another app's storage namespace. Attempting to do so results in a ReevePermissionError at runtime and permanent rejection.
Code Standards
✅ Allowed
- External CSS fonts (Google Fonts, etc.)
- External image CDNs for your own assets
- Reeve SDK API calls for all ecommerce data
❌ Not allowed
- External JavaScript loaded at runtime from untrusted domains
- eval() or Function() with dynamic code
- Fetching merchant data and posting it to your own servers
- Reading cookies or localStorage from the parent Cockpit frame
- Accessing window.parent beyond what the Reeve SDK providesAuthentication
Your app may not implement its own authentication layer that collects merchant credentials. All merchant authentication is handled by Reeve's OAuth flows. If your app requires a separate account on your service, this must be clearly disclosed in the listing and implemented via OAuth (not password collection in the iframe).
UX Standards
Theme Compatibility
Your app must work in both light and dark themes. Reviewers test both. Use the CSS variables provided by the Cockpit:
/* ✅ Do this */
background: var(--reeve-bg);
color: var(--reeve-text);
border-color: var(--reeve-border);
/* ❌ Don't do this */
background: #ffffff;
color: #000000;Hard-coded colors that look fine in dark mode often become unreadable in light mode (or vice versa). Use CSS variables throughout.
Responsive Layout
The Cockpit iframe has a variable width between 320px and 1400px depending on the user's screen size and sidebar state. Your app must be usable at all widths in this range. Test with your browser DevTools at 400px, 768px, and 1200px widths.
Typography
Use the Reeve font stack variable: font-family: var(--reeve-font). Do not load heavy font files that slow down initial render — if you want a custom font, keep it to ≤2 weights.
Interactions
| Standard | Requirement |
|---|---|
| Buttons | Must have hover and disabled states |
| Loading | All async operations must show a loading indicator |
| Destructive actions | "Delete" and similar must have a confirmation step |
| Keyboard navigation | Primary workflows must be keyboard-accessible |
| Focus indicators | Visible focus rings on all interactive elements |
Common Rejection Reasons
These are the most frequent reasons apps fail review. Check these before submitting:
1. Undeclared permissions
Your code calls reeve.data.query({ source: 'shopify' }) but data.shopify isn't in your manifest.
Fix: Run through every SDK method you call and ensure each has a corresponding permission.
2. Declared but unused permissions
You listed ai.stream in your manifest but never call reeve.ai.stream().
Fix: Remove permissions your app doesn't use.
3. Hard-coded colors breaking light mode
The app looks great in dark mode but text is invisible in light mode.
Fix: Replace all color values with var(--reeve-*) CSS variables.
4. No error handling for disconnected data sources
The app crashes or shows a blank screen when Shopify isn't connected.
Fix: Wrap all reeve.data.query() calls in try/catch and show a user-friendly message.
5. Sending data to external servers
Network inspector shows merchant order data being sent to your analytics service. Fix: Either remove the tracking, or disclose it prominently and get merchant opt-in.
6. App fails to load within 5 seconds
Large JS bundles or slow third-party CDNs delay interactivity. Fix: Code-split with dynamic imports, lazy-load non-critical dependencies, use a fast CDN.
7. Incomplete Marketplace listing
Missing icon, screenshots, or a vague description. Fix: 512×512 icon, 2+ screenshots at 1280×800, description that clearly explains what the app does and who it's for.
8. No empty or loading states
The app shows a blank white area while data loads or when collections are empty. Fix: Add skeleton loaders for loading states and meaningful empty state UI.
9. Breaking on mobile-width Cockpit
The app is unusable at 400px width.
Fix: Test at narrow widths, add CSS @media queries, use flexible layouts.
10. Console errors during normal usage
JavaScript errors in the console during typical user flows. Fix: Fix the errors, or add proper error boundaries so they don't surface to users.
After Approval
Updates
Updating your app doesn't require a full re-review for minor changes. Use this guide:
| Change Type | Review Required? |
|---|---|
| Bug fixes (no new permissions) | No — submit via fast-track update |
| UI improvements | No — submit via fast-track update |
| New feature with existing permissions | Light review (1–2 days) |
| New permissions added | Full review (3–5 days) |
| Major version bump | Full review |
Version Management
Always increment version in your manifest before submitting an update. Reeve uses the version number to notify merchants of updates.
Takedowns
Reeve may take down an app that:
- Begins exfiltrating merchant data after approval
- Has a critical security vulnerability under active exploitation
- Violates the developer agreement
You'll be notified 48 hours before a non-emergency takedown, except for active security incidents.
Developer Support
- Slack community: meetreeve.com/slack —
#developerschannel - Review questions: review@meetreeve.com
- Bug reports: github.com/reeve/app-sdk/issues
- Documentation: docs.meetreeve.com/developers
If your app is rejected, you can appeal the decision by replying to the rejection email with additional context. Appeals are reviewed by a senior developer advocate within 3 business days.
Related
- Manifest Reference — ensure your manifest is complete
- SDK Reference — full API docs
- Getting Started — build your first app