This document describes the NFC tag functionality for tracking clothing items when removed from and returned to the closet.
The NFC feature allows you to:
NFC works in:
This app now supports the Web NFC API, which enables NFC functionality directly in web browsers on Android without requiring a native app build!
| Browser | Platform | Support | Version |
|---|---|---|---|
| Chrome | Android | ✅ Yes | 89+ |
| Edge | Android | ✅ Yes | 89+ |
| Safari | iOS | ❌ No | - |
| Firefox | Android | ❌ No | - |
| Desktop | Any | ❌ No | - |
localhostThe app automatically detects the best NFC method available:
No code changes needed - the app handles the fallback automatically!
Stores the association between NFC tags and items:
id - Unique identifiertagId - NFC tag UID (unique hardware identifier)label - Optional human-readable label (e.g., “Blue hanger”, “Closet 1”)itemId - Reference to the item this tag is attached tocreatedAt, updatedAt - TimestampsTracks all NFC scan events:
id - Unique identifiertagId - NFC tag UID that was scanneditemId - Reference to the itemaction - Either “removed” or “returned”notes - Optional user notes about the eventcreatedAt - When the scan occurredRun the following migration to add NFC support:
cd app
npx prisma migrate dev --name add_nfc_support
npx prisma generate
No setup required! Just:
The app will automatically use the Web NFC API.
For iOS support or enhanced Android experience, you can build a native app. See MOBILE_APPS.md for building instructions.
Add to ios/App/App/Info.plist:
<key>NFCReaderUsageDescription</key>
<string>We need NFC access to scan clothing tags</string>
Add to android/app/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="false" />
/nfc-scan or use the NFC Scan shortcutWhen marking as “Removed”:
lastWornDate is updatedwearsBeforeWash, clean status changes to “needs_wash”When marking as “Returned”:
Associate an NFC tag with an item.
Request:
{
"tagId": "04:A1:B2:C3:D4:E5:F6",
"itemId": "clx123...",
"label": "Blue hanger (optional)"
}
Response:
{
"success": true,
"nfcTag": {
"id": "...",
"tagId": "04:A1:B2:C3:D4:E5:F6",
"itemId": "...",
"label": "Blue hanger",
"item": { ... }
}
}
Remove an NFC tag assignment.
Query params: ?tagId=... or ?itemId=...
Response:
{
"success": true,
"deletedCount": 1
}
Record an NFC tag scan event.
Request:
{
"tagId": "04:A1:B2:C3:D4:E5:F6",
"action": "removed", // or "returned"
"notes": "Going to work (optional)"
}
Response:
{
"success": true,
"event": { ... },
"item": { ... },
"message": "Blue Shirt marked as removed from closet"
}
List all NFC tags with their items and recent events.
Response:
{
"tags": [
{
"id": "...",
"tagId": "04:A1:B2:C3:D4:E5:F6",
"label": "Blue hanger",
"item": { ... },
"recentEvents": [ ... ]
}
],
"total": 5
}
Custom hook for NFC functionality.
import { useNFC } from '@/app/lib/hooks/useCapacitor';
function MyComponent() {
const nfc = useNFC();
const scanTag = async () => {
if (!nfc.isAvailable || !nfc.isEnabled) {
alert('NFC not available');
return;
}
const tagId = await nfc.startScanning();
console.log('Scanned:', tagId);
};
return (
<div>
{nfc.isSupported ? (
<button onClick={scanTag} disabled={nfc.isScanning}>
{nfc.isScanning ? 'Scanning...' : 'Scan NFC Tag'}
</button>
) : (
<p>NFC not supported on this device</p>
)}
</div>
);
}
isAvailable - Whether NFC hardware is availableisEnabled - Whether NFC is enabled in settingsisScanning - Whether a scan is in progressisSupported - Whether the device supports NFCstartScanning() - Start scanning for NFC tagsstopScanning() - Stop scanningreadTag() - Read tag datawriteTag(text) - Write text to tagaddTagListener(callback) - Listen for tag detectionFull-featured NFC scanner with UI.
import NFCScanner from '@/app/components/NFCScanner';
<NFCScanner
onTagScanned={(tagId, itemInfo) => {
console.log('Tag scanned:', tagId, itemInfo);
}}
onError={(error) => {
console.error('Error:', error);
}}
autoScan={true} // Start scanning automatically
/>
Component for assigning NFC tags to items.
import NFCAssign from '@/app/components/NFCAssign';
<NFCAssign
itemId={item.id}
itemTitle={item.title}
currentTag={nfcTag}
onAssigned={(tag) => setNfcTag(tag)}
onRemoved={() => setNfcTag(null)}
/>
“NFC is not available on this device”
“Please enable NFC in your device settings”
“NotAllowedError” in browser
“NFC tag is already assigned to another item”
“NDEFReader is not defined”
HTTPS Required Error
Permission Denied
Label your tags: Use descriptive labels like “Blue hanger” or “Closet section A”
Consistent placement: Always place tags in the same spot on hangers
Tag quality: Use good quality NFC tags (NTAG213 recommended)
Backup: NFC tags can fail - keep item info in the app too
Regular checks: Periodically verify tag associations are still correct
Potential future features:
wardrobe:item:{itemId}