

Also from Kynth Studios


Also from Kynth Studios


Also from Kynth Studios
123456# 📱 React Native Mobile Development Patterns78## 🎯 Project Overview - Mobile POS Applications910### GitHub Milestones Integration11Based on [GitHub Milestones](https://github.com/madebyaris/poinf-of-sales/milestones), we're developing:12131. **Kitchen Staff Mobile App (iOS & Android)** - Tablet and TV display optimization142. **Server Group Mobile App (iOS & Android)** - Smartphone and tablet flexibility1516## 🏗️ Cross-Platform Architecture1718### Project Structure for React Native Apps19```20mobile/21├── kitchen-app/ # Kitchen Staff Mobile App22│ ├── src/23│ │ ├── components/24│ │ │ ├── kitchen/ # Kitchen-specific components25│ │ │ ├── ui/ # Shared UI components26│ │ │ └── common/ # Cross-app components27│ │ ├── screens/28│ │ │ ├── KitchenDisplay/ # Main kitchen interface29│ │ │ ├── OrderDetails/ # Individual order management30│ │ │ └── Settings/ # App configuration31│ │ ├── services/32│ │ │ ├── api/ # API integration33│ │ │ ├── sync/ # Real-time synchronization34│ │ │ └── offline/ # Offline mode handling35│ │ └── utils/36│ ├── android/ # Android-specific code37│ ├── ios/ # iOS-specific code38│ └── package.json39├── server-app/ # Server Group Mobile App40│ ├── src/41│ │ ├── components/42│ │ │ ├── pos/ # POS interface components43│ │ │ ├── payment/ # Mobile payment processing44│ │ │ └── tables/ # Table management45│ │ ├── screens/46│ │ │ ├── OrderEntry/ # Mobile order creation47│ │ │ ├── TableView/ # Table management interface48│ │ │ └── PaymentFlow/ # Mobile payment processing49│ │ └── services/50│ └── package.json51└── shared/ # Shared code between apps52 ├── components/ # Reusable UI components53 ├── types/ # TypeScript definitions54 ├── api/ # API client55 └── utils/ # Utility functions56```5758## 🍳 Kitchen Staff Mobile App Patterns5960### Tablet & TV Display Optimization61```typescript62// Kitchen app main component with device optimization63import React, { useEffect, useState } from 'react'64import { Dimensions, Platform } from 'react-native'65import DeviceInfo from 'react-native-device-info'66import Orientation from 'react-native-orientation-locker'6768interface DeviceConfig {69 type: 'smartphone' | 'tablet' | 'tv'70 screenSize: 'small' | 'medium' | 'large' | 'extra-large'71 touchTargetSize: number72 fontSize: number73 spacing: number74}7576export const KitchenApp: React.FC = () => {77 const [deviceConfig, setDeviceConfig] = useState<DeviceConfig>()78 const [orders, setOrders] = useState<KitchenOrder[]>([])7980 useEffect(() => {81 initializeDeviceOptimization()82 setupRealTimeSync()83 enableOfflineMode()84 }, [])8586 // ✅ CORRECT: Device-specific optimization87 const initializeDeviceOptimization = async () => {88 const { width, height } = Dimensions.get('window')89 const isTablet = await DeviceInfo.isTablet()90 const deviceType = await DeviceInfo.getDeviceType()9192 // Determine device configuration93 let config: DeviceConfig9495 if (deviceType === 'tv' || width > 1200) {96 // Large screen TV display97 config = {98 type: 'tv',99 screenSize: 'extra-large',100 touchTargetSize: 60, // Extra large for wall-mounted displays101 fontSize: 24,102 spacing: 32103 }104105 // TV-specific optimizations106 Orientation.lockToLandscape()107 await setupTVDisplayMode()108109 } else if (isTablet || width > 768) {110 // Tablet optimization111 config = {112 type: 'tablet',113 screenSize: 'large',114 touchTargetSize: 50, // Standard tablet touch targets115 fontSize: 18,116 spacing: 24117 }118119 // Tablet-specific optimizations120 Orientation.lockToLandscape()121 await setupTabletMode()122123 } else {124 // Smartphone fallback (not primary use case for kitchen)125 config = {126 type: 'smartphone',127 screenSize: 'medium',128 touchTargetSize: 44,129 fontSize: 16,130 spacing: 16131 }132 }133134 setDeviceConfig(config)135 }136137 // TV display mode configuration138 const setupTVDisplayMode = async () => {139 // Enable full-screen mode140 if (Platform.OS === 'android') {141 // Hide navigation bar for TV displays142 await DeviceInfo.getSystemName() // Android TV detection143 }144145 // High contrast mode for distance viewing146 const tvSettings = {147 contrast: 'high',148 colorScheme: 'high-visibility',149 animations: 'reduced', // Minimize distractions150 autoRefresh: 3000 // 3-second refresh for TV displays151 }152153 await applyDisplaySettings(tvSettings)154 }155156 // Tablet mode configuration157 const setupTabletMode = async () => {158 // Enable gesture navigation159 const tabletSettings = {160 swipeGestures: true,161 hapticFeedback: true,162 multiTouch: false, // Prevent accidental gestures163 autoRefresh: 5000 // 5-second refresh for tablets164 }165166 await applyDisplaySettings(tabletSettings)167 }168169 return (170 <KitchenDisplayLayout171 deviceConfig={deviceConfig}172 orders={orders}173 onOrderUpdate={handleOrderUpdate}174 />175 )176}177```178179### Real-Time Order Synchronization180```typescript181// Real-time sync service for kitchen app182import { io, Socket } from 'socket.io-client'183import AsyncStorage from '@react-native-async-storage/async-storage'184import NetInfo from '@react-native-netinfo/netinfo'185186class KitchenSyncService {187 private socket: Socket | null = null188 private offlineQueue: OfflineOperation[] = []189 private isOnline: boolean = true190191 async initialize(): Promise<void> {192 // Monitor network connectivity193 NetInfo.addEventListener(state => {194 this.isOnline = state.isConnected ?? false195196 if (this.isOnline && this.offlineQueue.length > 0) {197 this.processOfflineQueue()198 }199 })200201 // Initialize WebSocket connection202 await this.connectWebSocket()203 }204205 // ✅ CORRECT: WebSocket connection with reconnection logic206 private async connectWebSocket(): Promise<void> {207 const token = await AsyncStorage.getItem('auth_token')208209 this.socket = io('ws://localhost:8080', {210 auth: { token },211 transports: ['websocket'],212 reconnection: true,213 reconnectionAttempts: 5,214 reconnectionDelay: 1000,215 })216217 // Kitchen-specific event listeners218 this.socket.on('order-created', this.handleNewOrder)219 this.socket.on('order-updated', this.handleOrderUpdate)220 this.socket.on('item-status-changed', this.handleItemStatusChange)221222 // Connection management223 this.socket.on('connect', () => {224 console.log('✅ Kitchen app connected to server')225 this.processOfflineQueue()226 })227228 this.socket.on('disconnect', () => {229 console.log('❌ Kitchen app disconnected from server')230 })231 }232233 // Handle new orders with sound notifications234 private handleNewOrder = (order: KitchenOrder) => {235 // Play new order sound (800Hz beep)236 this.soundService.playNewOrderSound()237238 // Add to kitchen display239 this.orderManager.addOrder(order)240241 // Show notification242 this.notificationService.showNewOrderNotification(order)243 }244245 // Update item status with optimistic updates246 async updateItemStatus(orderId: string, itemId: string, status: ItemStatus): Promise<void> {247 // Optimistic update for immediate UI feedback248 this.orderManager.updateItemStatusOptimistic(orderId, itemId, status)249250 if (this.isOnline) {251 try {252 await this.apiClient.updateItemStatus(orderId, itemId, status)253254 // Play status change sound255 if (status === 'ready') {256 this.soundService.playItemReadySound() // 1200Hz257 } else if (status === 'served') {258 this.soundService.playItemServedSound() // 1400Hz259 }260261 } catch (error) {262 // Revert optimistic update on error263 this.orderManager.revertItemStatusUpdate(orderId, itemId)264265 // Queue for offline processing266 this.queueOfflineOperation({267 type: 'update-item-status',268 orderId,269 itemId,270 status,271 timestamp: Date.now()272 })273 }274 } else {275 // Queue for offline processing276 this.queueOfflineOperation({277 type: 'update-item-status',278 orderId,279 itemId,280 status,281 timestamp: Date.now()282 })283 }284 }285286 // Offline operation queuing287 private queueOfflineOperation(operation: OfflineOperation): void {288 this.offlineQueue.push(operation)289 AsyncStorage.setItem('offline_queue', JSON.stringify(this.offlineQueue))290 }291292 // Process queued operations when back online293 private async processOfflineQueue(): Promise<void> {294 if (this.offlineQueue.length === 0) return295296 console.log(`📤 Processing ${this.offlineQueue.length} offline operations`)297298 for (const operation of this.offlineQueue) {299 try {300 await this.executeOfflineOperation(operation)301 } catch (error) {302 console.error('Failed to process offline operation:', error)303 }304 }305306 // Clear processed queue307 this.offlineQueue = []308 await AsyncStorage.removeItem('offline_queue')309 }310}311```312313## 👨💼 Server Group Mobile App Patterns314315### Adaptive UI for Smartphones & Tablets316```typescript317// Server app with adaptive UI based on device size318import React, { useEffect, useState } from 'react'319import { useDeviceOrientation } from '@react-native-community/hooks'320321export const ServerApp: React.FC = () => {322 const [layoutMode, setLayoutMode] = useState<'smartphone' | 'tablet'>()323 const orientation = useDeviceOrientation()324325 useEffect(() => {326 determineLayoutMode()327 }, [orientation])328329 // ✅ CORRECT: Adaptive layout based on device capabilities330 const determineLayoutMode = async () => {331 const { width, height } = Dimensions.get('window')332 const isTablet = await DeviceInfo.isTablet()333334 // Determine layout mode335 if (isTablet || width > 768) {336 setLayoutMode('tablet')337 await setupTabletLayout()338 } else {339 setLayoutMode('smartphone')340 await setupSmartphoneLayout()341 }342 }343344 // Tablet layout: Multi-column with side navigation345 const setupTabletLayout = async () => {346 const tabletConfig = {347 layout: 'multi-column',348 navigation: 'side',349 touchTargets: 50,350 splitView: true, // Menu + cart simultaneously351 gestures: {352 swipe: true,353 pinch: false,354 longPress: true355 }356 }357358 await applyLayoutConfig(tabletConfig)359 }360361 // Smartphone layout: Single column with bottom navigation362 const setupSmartphoneLayout = async () => {363 const smartphoneConfig = {364 layout: 'single-column',365 navigation: 'bottom',366 touchTargets: 44,367 reachability: true, // One-handed operation368 gestures: {369 swipe: true,370 pullToRefresh: true,371 quickActions: ['add-item', 'view-cart', 'checkout']372 }373 }374375 await applyLayoutConfig(smartphoneConfig)376 }377378 return (379 <ServerLayout380 mode={layoutMode}381 orientation={orientation}382 />383 )384}385```386387### Mobile Payment Integration388```typescript389// Mobile payment processing with card reader integration390import { StripeTerminal } from '@stripe/stripe-terminal-react-native'391import { NfcManager, NfcTech } from 'react-native-nfc-manager'392393class MobilePaymentProcessor {394 private stripeTerminal: StripeTerminal395 private cardReaderConnected: boolean = false396397 async initialize(): Promise<void> {398 // Initialize Stripe Terminal for card readers399 await this.stripeTerminal.initialize({400 fetchConnectionToken: this.fetchConnectionToken401 })402403 // Initialize NFC for contactless payments404 await NfcManager.start()405406 // Discover and connect to card readers407 await this.discoverCardReaders()408 }409410 // ✅ CORRECT: Card reader integration411 async processCardPayment(amount: number): Promise<PaymentResult> {412 if (!this.cardReaderConnected) {413 throw new Error('Card reader not connected')414 }415416 try {417 // Create payment intent418 const paymentIntent = await this.createPaymentIntent(amount)419420 // Collect payment method421 const result = await this.stripeTerminal.collectPaymentMethod(paymentIntent)422423 // Process payment424 const confirmation = await this.stripeTerminal.processPayment(result.paymentIntent)425426 return {427 success: true,428 transactionId: confirmation.paymentIntent.id,429 amount,430 method: 'card',431 timestamp: new Date().toISOString()432 }433434 } catch (error) {435 return {436 success: false,437 error: error.message,438 amount,439 method: 'card'440 }441 }442 }443444 // NFC/Contactless payment processing445 async processContactlessPayment(amount: number): Promise<PaymentResult> {446 try {447 // Request NFC technology448 await NfcManager.requestTechnology(NfcTech.Ndef)449450 // Read NFC tag/card451 const tag = await NfcManager.getTag()452453 // Process contactless payment454 const result = await this.processNfcPayment(tag, amount)455456 return result457458 } catch (error) {459 return {460 success: false,461 error: 'Contactless payment failed',462 amount,463 method: 'contactless'464 }465 } finally {466 NfcManager.cancelTechnologyRequest()467 }468 }469470 // Mobile wallet integration (Apple Pay, Google Pay)471 async processMobileWallet(amount: number): Promise<PaymentResult> {472 const { ApplePay, GooglePay } = await import('react-native-payments')473474 const paymentRequest = {475 id: 'pos-payment',476 displayItems: [{477 label: 'Order Total',478 amount: { currency: 'USD', value: amount.toString() }479 }],480 total: {481 label: 'Total',482 amount: { currency: 'USD', value: amount.toString() }483 },484 methodData: [{485 supportedMethods: ['apple-pay', 'google-pay'],486 data: {487 merchantIdentifier: 'merchant.pos.system',488 supportedNetworks: ['visa', 'mastercard', 'amex']489 }490 }]491 }492493 try {494 const paymentResponse = Platform.OS === 'ios'495 ? await ApplePay.show(paymentRequest)496 : await GooglePay.show(paymentRequest)497498 return {499 success: true,500 transactionId: paymentResponse.transactionIdentifier,501 amount,502 method: 'mobile_wallet',503 timestamp: new Date().toISOString()504 }505506 } catch (error) {507 return {508 success: false,509 error: 'Mobile wallet payment cancelled',510 amount,511 method: 'mobile_wallet'512 }513 }514 }515}516```517518## 🔄 Cross-Platform Synchronization519520### Shared State Management521```typescript522// Shared state management between web and mobile523import { create } from 'zustand'524import { persist } from 'zustand/middleware'525import AsyncStorage from '@react-native-async-storage/async-storage'526527interface PosState {528 orders: Order[]529 currentUser: User | null530 isOnline: boolean531 lastSync: number532533 // Actions534 addOrder: (order: Order) => void535 updateOrder: (orderId: string, updates: Partial<Order>) => void536 syncWithServer: () => Promise<void>537 setOnlineStatus: (status: boolean) => void538}539540// ✅ CORRECT: Zustand store with persistence541export const usePosStore = create<PosState>()(542 persist(543 (set, get) => ({544 orders: [],545 currentUser: null,546 isOnline: true,547 lastSync: 0,548549 addOrder: (order) =>550 set((state) => ({551 orders: [...state.orders, order]552 })),553554 updateOrder: (orderId, updates) =>555 set((state) => ({556 orders: state.orders.map(order =>557 order.id === orderId ? { ...order, ...updates } : order558 )559 })),560561 syncWithServer: async () => {562 const { orders, lastSync } = get()563564 try {565 // Sync orders modified since last sync566 const modifiedOrders = orders.filter(order =>567 order.updated_at > lastSync568 )569570 if (modifiedOrders.length > 0) {571 await apiClient.syncOrders(modifiedOrders)572 }573574 // Fetch server updates575 const serverUpdates = await apiClient.getOrderUpdates(lastSync)576577 set({578 orders: mergeOrderUpdates(orders, serverUpdates),579 lastSync: Date.now()580 })581582 } catch (error) {583 console.error('Sync failed:', error)584 }585 },586587 setOnlineStatus: (status) =>588 set({ isOnline: status })589 }),590 {591 name: 'pos-storage',592 storage: {593 getItem: (name) => AsyncStorage.getItem(name),594 setItem: (name, value) => AsyncStorage.setItem(name, value),595 removeItem: (name) => AsyncStorage.removeItem(name)596 }597 }598 )599)600```601602## 🎨 UI Component Patterns603604### Touch-Optimized Components605```typescript606// Touch-optimized button component for mobile607import React from 'react'608import { TouchableOpacity, Text, StyleSheet, ViewStyle, TextStyle } from 'react-native'609import { useHapticFeedback } from 'react-native-haptic-feedback'610611interface TouchButtonProps {612 title: string613 onPress: () => void614 variant?: 'primary' | 'secondary' | 'danger'615 size?: 'small' | 'medium' | 'large'616 disabled?: boolean617 hapticFeedback?: boolean618}619620// ✅ CORRECT: Touch-optimized component with haptic feedback621export const TouchButton: React.FC<TouchButtonProps> = ({622 title,623 onPress,624 variant = 'primary',625 size = 'medium',626 disabled = false,627 hapticFeedback = true628}) => {629 const triggerHaptic = useHapticFeedback()630631 const handlePress = () => {632 if (hapticFeedback) {633 triggerHaptic('impactLight')634 }635 onPress()636 }637638 const buttonStyle: ViewStyle = {639 ...styles.base,640 ...styles[variant],641 ...styles[size],642 opacity: disabled ? 0.6 : 1643 }644645 return (646 <TouchableOpacity647 style={buttonStyle}648 onPress={handlePress}649 disabled={disabled}650 activeOpacity={0.7}651 hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }} // Larger touch area652 >653 <Text style={[styles.text, styles[`${variant}Text`]]}>{title}</Text>654 </TouchableOpacity>655 )656}657658const styles = StyleSheet.create({659 base: {660 borderRadius: 8,661 alignItems: 'center',662 justifyContent: 'center',663 minHeight: 44, // iOS minimum touch target664 },665666 // Size variants667 small: {668 paddingHorizontal: 16,669 paddingVertical: 8,670 minHeight: 44,671 },672 medium: {673 paddingHorizontal: 24,674 paddingVertical: 12,675 minHeight: 50, // Tablet-optimized676 },677 large: {678 paddingHorizontal: 32,679 paddingVertical: 16,680 minHeight: 60, // TV display optimized681 },682683 // Variant styles684 primary: {685 backgroundColor: '#007AFF',686 },687 secondary: {688 backgroundColor: '#F2F2F7',689 borderWidth: 1,690 borderColor: '#C7C7CC',691 },692 danger: {693 backgroundColor: '#FF3B30',694 },695696 // Text styles697 text: {698 fontSize: 16,699 fontWeight: '600',700 },701 primaryText: {702 color: '#FFFFFF',703 },704 secondaryText: {705 color: '#007AFF',706 },707 dangerText: {708 color: '#FFFFFF',709 },710})711```712713## 🚀 Performance Optimization714715### Memory Management for Long-Running Apps716```typescript717// Memory optimization for kitchen displays that run 24/7718class MobilePerformanceManager {719 private memoryWarningListener: any720 private backgroundTimer: NodeJS.Timeout | null = null721722 initialize(): void {723 // Monitor memory warnings724 this.memoryWarningListener = DeviceEventEmitter.addListener(725 'memoryWarning',726 this.handleMemoryWarning727 )728729 // Setup background optimization730 AppState.addEventListener('change', this.handleAppStateChange)731 }732733 // ✅ CORRECT: Memory management for long-running apps734 private handleMemoryWarning = (): void => {735 console.log('⚠️ Memory warning received - optimizing...')736737 // Clear non-essential caches738 ImageCache.clear()739740 // Limit order history in memory741 OrderManager.limitHistoryItems(25)742743 // Force garbage collection (if available)744 if (global.gc) {745 global.gc()746 }747748 // Reduce image quality temporarily749 ImageManager.setQuality('low')750 }751752 private handleAppStateChange = (nextAppState: string): void => {753 if (nextAppState === 'background') {754 // Reduce background activity755 this.enablePowerSaveMode()756 } else if (nextAppState === 'active') {757 // Resume normal operation758 this.disablePowerSaveMode()759 }760 }761762 private enablePowerSaveMode(): void {763 // Reduce polling frequency764 SyncManager.setPollingInterval(30000) // 30s instead of 5s765766 // Pause animations767 AnimationManager.pauseNonCriticalAnimations()768769 // Reduce network activity770 NetworkManager.enableBatchMode()771 }772773 private disablePowerSaveMode(): void {774 // Resume normal polling775 SyncManager.setPollingInterval(5000)776777 // Resume animations778 AnimationManager.resumeAnimations()779780 // Resume normal network activity781 NetworkManager.disableBatchMode()782 }783784 cleanup(): void {785 if (this.memoryWarningListener) {786 this.memoryWarningListener.remove()787 }788789 if (this.backgroundTimer) {790 clearInterval(this.backgroundTimer)791 }792 }793}794```795796## 📱 Development & Deployment797798### Build Configuration799```javascript800// metro.config.js - Optimized for POS mobile apps801const { getDefaultConfig } = require('expo/metro-config')802803const config = getDefaultConfig(__dirname)804805// Optimize for POS system requirements806config.resolver.platforms = ['native', 'ios', 'android', 'web']807808// Enable shared code between kitchen and server apps809config.resolver.alias = {810 '@shared': './shared',811 '@kitchen': './kitchen-app/src',812 '@server': './server-app/src'813}814815// Optimize bundle size for tablet deployment816config.transformer.minifierConfig = {817 keep_fnames: true, // Keep function names for debugging818 mangle: {819 keep_fnames: true820 }821}822823module.exports = config824```825826### Deployment Scripts827```bash828#!/bin/bash829# deploy-mobile-apps.sh - Deploy both kitchen and server apps830831echo "🚀 Deploying POS Mobile Applications..."832833# Build kitchen app834echo "📱 Building Kitchen Staff App..."835cd kitchen-app836npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle837npx react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios/main.jsbundle838839# Build server app840echo "👨💼 Building Server Group App..."841cd ../server-app842npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle843npx react-native bundle --platform ios --dev false --entry-file index.js --bundle-output ios/main.jsbundle844845echo "✅ Mobile apps built successfully!"846echo "📋 Next steps:"847echo " 1. Test on target devices (tablets for kitchen, phones/tablets for servers)"848echo " 2. Deploy to app stores or internal distribution"849echo " 3. Configure device management for restaurant deployment"850```851852This comprehensive React Native pattern guide ensures your mobile POS applications are optimized for restaurant environments, with proper device-specific optimizations, offline capabilities, and seamless integration with the existing web-based POS system.
One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| madebyaris/poinf-of-sales.cursor/rules/admin-interface-patterns.mdc · 118 | Cursor rules | stylearchsecurityapi+2 | 62/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/api-patterns.mdc · 118 | Cursor rules | lint-formatstylesecuritydatabase+3 | 62/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/authentication-and-security-patterns.mdc · 118 | Cursor rules | setupteststylesecurity+4 | 81/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/backend-golang.mdc · 118 | Cursor rules | testlint-formatstylearch+5 | 69/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/business-logic-patterns.mdc · 118 | Cursor rules | teststyledatabaseperformance+1 | 50/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/database-patterns.mdc · 118 | Cursor rules | stylearchtypessecurity+2 | 62/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/development-workflow.mdc · 118 | Cursor rules | setupbuildteststyle+3 | 86/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/docker-deployment.mdc · 118 | Cursor rules | setupbuildteststyle+8 | 77/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/frontend-react.mdc · 118 | Cursor rules | buildtestlint-formatstyle+4 | 69/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/makefile-scripting.mdc · 118 | Cursor rules | setuplint-formatstylearch+2 | 81/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/performance-optimization-patterns.mdc · 118 | Cursor rules | buildteststyledatabase+3 | 66/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/project-architecture.mdc · 118 | Cursor rules | setupteststylearch+6 | 78/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/role-based-access-patterns.mdc · 118 | Cursor rules | styletypessecuritydatabase+2 | 58/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/tech-debt-prevention.mdc · 118 | Cursor rules | styletesting-strategyui | 50/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/testing-patterns.mdc · 118 | Cursor rules | setupteststylearch+4 | 74/100 | 14 days ago | |
| madebyaris/poinf-of-sales.cursor/rules/user-journey-optimization.mdc · 118 | Cursor rules | styleperformanceagent-behaviour | 50/100 | 14 days ago |
Same format, overlapping stack, ranked by quality.
| Repository | Format | Stack | Covers | Score | Changed |
|---|---|---|---|---|---|
| hiromaily/go-crypto-wallet.cursor/rules/typescript.mdc · 126 | Cursor rules | setupbuildtestlint-format+6 | 100/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/10-hermes-api.mdc · 46 | Cursor rules | testlint-formatstylearch+5 | 100/100 | 14 days ago | |
| markstev/mark-starter.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+6 | 99/100 | 14 days ago | |
| deifos/clipmira-subtitles.cursor/rules/frontend.mdc · 1 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| dodgecfr/combatfilms-webapp.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| Allymahmoud/case-intake-platform.cursor/rules/frontend.mdc · 0 | Cursor rules | setuptestlint-formatstyle+7 | 99/100 | 14 days ago | |
| langflow-ai/langflow.cursor/rules/docs_development.mdc · 153k | Cursor rules | setupbuildtestlint-format+7 | 97/100 | 14 days ago | |
| TechSquidTV/Hermes.cursor/rules/20-hermes-api-tests.mdc · 46 | Cursor rules | teststyletesting-strategysecurity+3 | 97/100 | 14 days ago |
A badge carrying the measured quality of the strongest agent config file in this repository, out of 100. It reads from this index every time somebody loads your page, so it changes when the measurement changes and there is nothing to keep up to date. Free, no account, and the value is not something you or we can set by hand.
[](https://rulestack.kynth.studio/configs/madebyaris-poinf-of-sales-cursor-rules-react-native-mobile-patterns)Would rather not hotlink us? Every badge is also served in shields.io’s endpoint schema, so shields renders the image and your readers never talk to our domain:
Published by Toolproof, the masthead over this index and eight others. The method behind the number is at toolproof.kynth.studio/methodology, and the whole thing is readable as JSON with no key at /api.