@vaibhavjha/qrfy 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Vaibhav Jha
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,110 @@
1
+ # QRfy
2
+
3
+ **Scan your dev server instantly.**
4
+
5
+ QRfy wraps any dev server command and generates a QR code in your terminal so you can open it on your phone in seconds. No more typing `192.168.x.x:3000` manually.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/qrfy.svg)](https://www.npmjs.com/package/qrfy)
8
+ [![license](https://img.shields.io/npm/l/qrfy.svg)](https://github.com/vaibhavjha-dev/qrfy/blob/main/LICENSE)
9
+
10
+ ---
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install -g qrfy
16
+ ```
17
+
18
+ Or with other package managers:
19
+
20
+ ```bash
21
+ # yarn
22
+ yarn global add qrfy
23
+
24
+ # pnpm
25
+ pnpm add -g qrfy
26
+
27
+ # bun
28
+ bun add -g qrfy
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ ```bash
34
+ qrfy <your-dev-command>
35
+ ```
36
+
37
+ ### Examples
38
+
39
+ ```bash
40
+ # Next.js
41
+ qrfy next dev
42
+
43
+ # Vite
44
+ qrfy vite
45
+
46
+ # npm scripts
47
+ qrfy npm run dev
48
+
49
+ # Any server
50
+ qrfy python -m http.server 8000
51
+ ```
52
+
53
+ ### Output
54
+
55
+ ```
56
+ QRfy connected
57
+
58
+ Local: http://localhost:3000
59
+ Mobile: http://192.168.1.5:3000
60
+
61
+ Scan to open on your phone:
62
+
63
+ [QR CODE]
64
+
65
+ Ensure both devices are on the same WiFi
66
+ ```
67
+
68
+ ## How It Works
69
+
70
+ 1. Spawns your dev command as a child process
71
+ 2. Watches stdout/stderr for a port number
72
+ 3. Detects your LAN IP address
73
+ 4. Generates a terminal QR code pointing to `http://<your-ip>:<port>`
74
+
75
+ Your dev server output is passed through normally — QRfy just adds the QR code on top.
76
+
77
+ ## Package.json Integration
78
+
79
+ ```json
80
+ {
81
+ "scripts": {
82
+ "dev": "qrfy next dev"
83
+ }
84
+ }
85
+ ```
86
+
87
+ Then just `npm run dev` and scan.
88
+
89
+ ## Supported Frameworks
90
+
91
+ Works with anything that prints a URL or port to the terminal:
92
+
93
+ - Next.js
94
+ - Vite
95
+ - Create React App
96
+ - Remix
97
+ - Astro
98
+ - SvelteKit
99
+ - Express / Fastify / any Node server
100
+ - Python / Go / Ruby servers
101
+ - Anything else
102
+
103
+ ## Requirements
104
+
105
+ - Node.js >= 14
106
+ - Both devices on the same WiFi network
107
+
108
+ ## License
109
+
110
+ MIT
package/bin/qrfy.js ADDED
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { getLocalIP } = require("../lib/network");
4
+ const { displayQR } = require("../lib/qr");
5
+ const { runServer } = require("../lib/runner");
6
+
7
+ const args = process.argv.slice(2);
8
+
9
+ if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
10
+ console.log("");
11
+ console.log(" \x1b[1mqrfy\x1b[0m - Scan your dev server instantly");
12
+ console.log("");
13
+ console.log(" \x1b[1mUsage:\x1b[0m");
14
+ console.log(" qrfy <command> [args...]");
15
+ console.log("");
16
+ console.log(" \x1b[1mExamples:\x1b[0m");
17
+ console.log(" qrfy next dev");
18
+ console.log(" qrfy vite");
19
+ console.log(" qrfy npm run dev");
20
+ console.log("");
21
+ process.exit(0);
22
+ }
23
+
24
+ const ip = getLocalIP();
25
+
26
+ if (!ip) {
27
+ console.error(
28
+ "\x1b[31m QRfy: No network connection found. Connect to WiFi and try again.\x1b[0m"
29
+ );
30
+ process.exit(1);
31
+ }
32
+
33
+ runServer(args, (port) => {
34
+ const localUrl = `http://localhost:${port}`;
35
+ const mobileUrl = `http://${ip}:${port}`;
36
+ displayQR(localUrl, mobileUrl);
37
+ });
package/lib/network.js ADDED
@@ -0,0 +1,15 @@
1
+ const os = require("os");
2
+
3
+ function getLocalIP() {
4
+ const interfaces = os.networkInterfaces();
5
+ for (const name of Object.keys(interfaces)) {
6
+ for (const iface of interfaces[name]) {
7
+ if (iface.family === "IPv4" && !iface.internal) {
8
+ return iface.address;
9
+ }
10
+ }
11
+ }
12
+ return null;
13
+ }
14
+
15
+ module.exports = { getLocalIP };
package/lib/parser.js ADDED
@@ -0,0 +1,23 @@
1
+ const PORT_PATTERNS = [
2
+ /https?:\/\/localhost:(\d+)/,
3
+ /https?:\/\/127\.0\.0\.1:(\d+)/,
4
+ /https?:\/\/0\.0\.0\.0:(\d+)/,
5
+ /https?:\/\/\[::\]:(\d+)/,
6
+ /port\s+(\d+)/i,
7
+ /:(\d{4,5})\b/,
8
+ ];
9
+
10
+ function extractPort(text) {
11
+ for (const pattern of PORT_PATTERNS) {
12
+ const match = text.match(pattern);
13
+ if (match) {
14
+ const port = parseInt(match[1], 10);
15
+ if (port > 0 && port <= 65535) {
16
+ return port;
17
+ }
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+
23
+ module.exports = { extractPort };
package/lib/qr.js ADDED
@@ -0,0 +1,26 @@
1
+ const qrcode = require("qrcode-terminal");
2
+
3
+ function displayQR(localUrl, mobileUrl) {
4
+ console.log("");
5
+ console.log("\x1b[1m\x1b[32m QRfy connected\x1b[0m");
6
+ console.log("");
7
+ console.log(` Local: \x1b[36m${localUrl}\x1b[0m`);
8
+ console.log(` Mobile: \x1b[36m${mobileUrl}\x1b[0m`);
9
+ console.log("");
10
+ console.log(" Scan to open on your phone:");
11
+ console.log("");
12
+ qrcode.generate(mobileUrl, { small: true }, (code) => {
13
+ const indented = code
14
+ .split("\n")
15
+ .map((line) => " " + line)
16
+ .join("\n");
17
+ console.log(indented);
18
+ console.log("");
19
+ console.log(
20
+ " \x1b[33mEnsure both devices are on the same WiFi\x1b[0m"
21
+ );
22
+ console.log("");
23
+ });
24
+ }
25
+
26
+ module.exports = { displayQR };
package/lib/runner.js ADDED
@@ -0,0 +1,56 @@
1
+ const { spawn } = require("child_process");
2
+ const { extractPort } = require("./parser");
3
+
4
+ function runServer(args, onPort) {
5
+ const child = spawn(args.join(" "), [], {
6
+ stdio: ["inherit", "pipe", "pipe"],
7
+ shell: true,
8
+ env: { ...process.env },
9
+ });
10
+
11
+ let detected = false;
12
+
13
+ function handleData(data) {
14
+ const text = data.toString();
15
+ process.stdout.write(text);
16
+
17
+ if (!detected) {
18
+ const port = extractPort(text);
19
+ if (port) {
20
+ detected = true;
21
+ onPort(port);
22
+ }
23
+ }
24
+ }
25
+
26
+ child.stdout.on("data", handleData);
27
+ child.stderr.on("data", (data) => {
28
+ const text = data.toString();
29
+ process.stderr.write(text);
30
+
31
+ if (!detected) {
32
+ const port = extractPort(text);
33
+ if (port) {
34
+ detected = true;
35
+ onPort(port);
36
+ }
37
+ }
38
+ });
39
+
40
+ child.on("error", (err) => {
41
+ console.error(`\x1b[31m QRfy error: ${err.message}\x1b[0m`);
42
+ process.exit(1);
43
+ });
44
+
45
+ child.on("close", (code) => {
46
+ process.exit(code ?? 0);
47
+ });
48
+
49
+ // Forward signals to child
50
+ process.on("SIGINT", () => child.kill("SIGINT"));
51
+ process.on("SIGTERM", () => child.kill("SIGTERM"));
52
+
53
+ return child;
54
+ }
55
+
56
+ module.exports = { runServer };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@vaibhavjha/qrfy",
3
+ "version": "1.0.0",
4
+ "description": "Scan your dev server instantly - QR code for local dev URLs",
5
+ "author": "Vaibhav Jha (https://github.com/vaibhavjha-dev)",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/vaibhavjha-dev/qrfy.git"
9
+ },
10
+ "homepage": "https://github.com/vaibhavjha-dev/qrfy#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/vaibhavjha-dev/qrfy/issues"
13
+ },
14
+ "bin": {
15
+ "qrfy": "./bin/qrfy.js"
16
+ },
17
+ "files": [
18
+ "bin/",
19
+ "lib/",
20
+ "LICENSE",
21
+ "README.md"
22
+ ],
23
+ "keywords": [
24
+ "qr",
25
+ "qrcode",
26
+ "dev-server",
27
+ "mobile",
28
+ "localhost",
29
+ "cli",
30
+ "developer-tools",
31
+ "vite",
32
+ "nextjs",
33
+ "react"
34
+ ],
35
+ "license": "MIT",
36
+ "engines": {
37
+ "node": ">=14"
38
+ },
39
+ "dependencies": {
40
+ "qrcode-terminal": "^0.12.0"
41
+ }
42
+ }