QR Share is a small open-source PWA for handing off short text and URLs between nearby devices with QR codes.
It creates app-specific URLs like /view#v1.p.<payload>, renders them as QR codes, and decodes them locally on the receiving device. There is no backend, no account system, and no cloud storage.
Live demo: https://jacksoncurrie.github.io/qrshare/
QR Share is intentionally narrow in scope:
- share short text, links, codes, and snippets between nearby devices
- work offline after the first successful load
- avoid servers, sign-ins, syncing, and analytics
- stay simple enough to audit and maintain
It is not trying to be a secret-sharing tool, a file transfer app, or a general QR utility suite.
- Enter short text and generate an app-specific QR Share link automatically.
- Switch to URL mode and generate a direct QR code for any valid
httporhttpslink. - Render that link as a QR code and copy the generated link directly from the QR area.
- Open a QR Share URL directly and decode the payload locally.
- Scan QR Share codes with the device camera.
- Copy the decoded text with one click.
- Install and reuse the app offline after it has been cached once.
Type once, or switch to URL mode, and get the QR code immediately. The QR area also acts as the copy target for the generated link.
Open a QR Share payload locally and copy the decoded text.
QR Share v1 uses a simple payload format:
v1.p.<payload>
v1is the protocol versionpmeans plain-text mode<payload>is UTF-8 text encoded as URL-safe base64 without padding
The app generates full URLs that look like:
/view#v1.p.<payload>
The payload lives in the URL fragment, which means it is not sent in normal HTTP requests. That improves privacy, but it does not make the content secret.
- No accounts
- No backend
- No analytics
- No ads
- No server-side storage
- No long-term persistence of generated payloads by default
Important caveats:
- Anyone with the QR code or link can read the content.
- QR Share is not suitable for high-value secrets in public settings.
- Camera access is only requested when the user enters the scan flow.
- The scan flow only accepts QR Share payloads, not arbitrary QR content.
See SECURITY.md for reporting guidance and security boundaries.
- Create mode supports plain text payloads and direct
http/httpsURLs. - Payloads above 800 UTF-8 bytes are blocked.
- QR Share only accepts app-specific QR payloads in the in-app scan and view flows.
- First-time visitors who are fully offline cannot load the app until it has been cached once.
- Camera scanning depends on
getUserMediasupport and user permission.
QR Share targets current evergreen browsers:
- Chrome
- Edge
- Firefox
- Safari
Camera scanning depends on browser camera support and device permissions. The create and direct-view flows still work without camera access.
- Vue 3
- TypeScript
- Vite
- Vue Router
- Vitest + Vue Test Utils
- Playwright
- ESLint + Prettier
vite-plugin-pwa- GitHub Actions
- GitHub Pages
npm ci
npm run devThe default development server runs at http://localhost:5173.
npm run dev
npm run build
npm run preview
npm run lint
npm run check
npm run verify
npm run format
npm run typecheck
npm run test:unit
npm run test:e2eQR Share includes unit, component, and browser-level tests.
npm run check
npm run verify
npm run test:e2eNotes:
npm run checkruns linting plus Vue/TypeScript typechecking.npm run verifyruns the main non-browser verification pass: check, unit tests, and production build.- Playwright runs against a production preview server.
- The scanner flow is tested with a deterministic mock instead of a real camera in CI.
npm run buildis part of the expected verification flow before release.
Production is designed for GitHub Pages.
- The production base path is
/qrshare/. npm run buildalso copiesdist/index.htmltodist/404.htmlfor SPA fallback support on GitHub Pages.- CI and deployment workflows live in ci.yml and deploy.yml.
- Keyboard accessible controls and navigation
- Semantic labels on all inputs and buttons
- Clear inline error messaging and visible focus styles
- Strong contrast across light and dark themes
- Mobile-first layout with a single-column flow
src/
components/ UI pieces like header, scanner, QR panel, copy button
lib/ payload, base64url, QR, scanner, and URL helpers
router/ route setup and document titles
styles/ tokens and global styles
views/ create, view, and not-found screens
tests/
unit/ pure logic tests
component/ Vue component tests
e2e/ Playwright browser tests
Contributions are welcome.
Before opening a PR:
- keep the app small and dependency-light
- prefer pure helpers in
src/lib - avoid adding persistence, backend logic, or product scope creep without discussion
- preserve accessibility and test coverage
See CONTRIBUTING.md for the development workflow.
- Better QR density guidance based on rendered output
- Optional compression if the complexity stays justified
- Potential visual regression checks for the two main screens
MIT. See LICENSE.

