diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..2543160 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,20 @@ +name: CI + +on: + push: + branches: ["**"] + pull_request: + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 20 + cache: npm + - run: npm ci + - run: npm run typecheck + - run: npm run build + - run: npm test diff --git a/README.md b/README.md index 0553821..3d96edb 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,24 @@ Props: `listening` · `canTranscribe` · `waveform` · `elapsed` · `onStart` · --- + +## Production Readiness + +VoiceDraft is publishable as a package today, but production apps should ship with a few guardrails: + +- **Capability fallback:** Always check `canTranscribe` and render a typed-input fallback path. +- **Permission handling:** Pass `onError` to show user-friendly prompts when microphone permission is denied. +- **Post-processing:** Treat transcript text as a draft and run your own validation/moderation before submit. +- **Cross-browser QA:** Verify behavior in Chrome, Edge, and Safari where Web Speech support differs. + +### Launch checklist for AI apps + +1. Add product copy and onboarding around browser mic permission. +2. Persist drafts in your app state so transcripts are recoverable. +3. Add server-side logging for speech failures and cancel/confirm rates. +4. Add your preferred cloud STT fallback for unsupported browsers. +5. Run CI (`npm run typecheck`, `npm run build`, `npm test`) on every PR. + ## Browser Support Requires `SpeechRecognition` or `webkitSpeechRecognition`. Use `canTranscribe` to gracefully disable the mic path when unavailable. diff --git a/package.json b/package.json index 5e551f3..00f9828 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ "build": "npm run clean && tsc -p tsconfig.build.json && node scripts/copy-styles.mjs", "prepack": "npm run build", "typecheck": "tsc --noEmit", - "benchmark:stt": "node scripts/benchmark-stt.mjs" + "benchmark:stt": "node scripts/benchmark-stt.mjs", + "test": "npm run build && node tests/format.test.mjs" }, "keywords": [ "voice", diff --git a/tests/format.test.mjs b/tests/format.test.mjs new file mode 100644 index 0000000..e1903bd --- /dev/null +++ b/tests/format.test.mjs @@ -0,0 +1,10 @@ +import assert from "node:assert/strict"; +import { formatElapsed } from "../dist/utils/format.js"; + +assert.equal(formatElapsed(0), "0:00"); +assert.equal(formatElapsed(65), "1:05"); +assert.equal(formatElapsed(600), "10:00"); +assert.equal(formatElapsed(-1), "0:00"); +assert.equal(formatElapsed(Number.NaN), "0:00"); + +console.log("format tests passed");