Skip to content

Instantly share code, notes, and snippets.

@JakubAndrysek
Created February 22, 2025 09:13
Show Gist options
  • Save JakubAndrysek/90c3fdd84305a982a9ce360f88ed51a4 to your computer and use it in GitHub Desktop.
Save JakubAndrysek/90c3fdd84305a982a9ce360f88ed51a4 to your computer and use it in GitHub Desktop.
web-nfc for NextJS

web-nfc for NextJS

Creating a custom module to support Web NFC in NextJS projects (TypeScript). Add the following code to your project to be able to compile and run the Web NFC API in NextJS.

Declare module

Declare the module in a .d.ts file in the root of your project or in the types directory.

declare module 'web-nfc' {

    interface Window {
        NDEFMessage: NDEFMessage
    }
    ...
}

Basic usage

import {NDEFReader} from "web-nfc";
// ...

try {
    if ("NDEFReader" in window) {
        const ndef = new NDEFReader();
        await ndef.scan(); // Start NFC scan
        console.log("Scan started successfully.");

        ndef.onreading = (event) => {
            const { message } = event;
            console.log("NFC reading detected.");
            for (const record of message.records) {
                if (record.recordType === "text") {
                    const decoder = new TextDecoder("utf-8");
                    const data = decoder.decode(record.data);
                    console.log("NFC Data:", data);
                    // Process NFC data
                }
            }
        };

        ndef.onreadingerror = () => {
            console.error("Failed to read NFC data.");
        };
    } else {
        alert("Web NFC is not supported on this device/browser.");
    }
} catch (error) {
    console.error("Error accessing NFC:", error);
}
// Type definitions for Web NFC
// Project: https://github.com/w3c/web-nfc
// Definitions by: Takefumi Yoshii <https://github.com/takefumi-yoshii>
// TypeScript Version: 3.9
// This type definitions referenced to WebIDL.
// https://w3c.github.io/web-nfc/#actual-idl-index
declare module 'web-nfc' {
interface Window {
NDEFMessage: NDEFMessage
}
declare class NDEFMessage {
constructor(messageInit: NDEFMessageInit)
records: ReadonlyArray<NDEFRecord>
}
declare interface NDEFMessageInit {
records: NDEFRecordInit[]
}
declare type NDEFRecordDataSource = string | BufferSource | NDEFMessageInit
interface Window {
NDEFRecord: NDEFRecord
}
declare class NDEFRecord {
constructor(recordInit: NDEFRecordInit)
readonly recordType: string
readonly mediaType?: string
readonly id?: string
readonly data?: DataView
readonly encoding?: string
readonly lang?: string
toRecords?: () => NDEFRecord[]
}
declare interface NDEFRecordInit {
recordType: string
mediaType?: string
id?: string
encoding?: string
lang?: string
data?: NDEFRecordDataSource
}
declare type NDEFMessageSource = string | BufferSource | NDEFMessageInit
interface Window {
NDEFReader: NDEFReader
}
declare class NDEFReader extends EventTarget {
constructor()
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onreading: (this: this, event: NDEFReadingEvent) => any
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onreadingerror: (this: this, error: Event) => any
scan: (options?: NDEFScanOptions) => Promise<void>
write: (message: NDEFMessageSource, options?: NDEFWriteOptions) => Promise<void>
makeReadOnly: (options?: NDEFMakeReadOnlyOptions) => Promise<void>
}
interface Window {
NDEFReadingEvent: NDEFReadingEvent
}
declare class NDEFReadingEvent extends Event {
constructor(type: string, readingEventInitDict: NDEFReadingEventInit)
serialNumber: string
message: NDEFMessage
}
interface NDEFReadingEventInit extends EventInit {
serialNumber?: string
message: NDEFMessageInit
}
interface NDEFWriteOptions {
overwrite?: boolean
signal?: AbortSignal
}
interface NDEFMakeReadOnlyOptions {
signal?: AbortSignal
}
interface NDEFScanOptions {
signal: AbortSignal
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment