npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

feojs

v1.2.0

Published

A React hook that converts speech from the microphone to text and makes it available to your React components

Readme

🎤 Feo (Voice in Malagasy)

A modern, TypeScript-first React hook that converts speech from the microphone to text and makes it available to your React components.

Feo is a spiritual successor to react-speech-recognition, built from the ground up with TypeScript, modern React patterns, and best practices.

npm version TypeScript License: MIT

Want to know how it works? Well, ask his parent directly react-speech-recognition by James Brill

✨ Features

  • 🎯 TypeScript First: Fully typed API with excellent IntelliSense support
  • 🪝 Modern React: Built with hooks and functional components
  • 🌐 Cross-browser: Supports polyfills for enhanced browser compatibility
  • 🎛️ Command Recognition: Sophisticated command matching with fuzzy search
  • 🔧 Configurable: Extensive customization options
  • 🧪 Well Tested: Comprehensive test coverage with Vitest
  • Lightweight: Minimal bundle size with tree-shaking support
  • 🔄 Continuous Listening: Support for continuous speech recognition

📦 Installation

npm install feojs
yarn add feojs
pnpm add feojs

🚀 Quick Start

import React from 'react'
import SpeechRecognition, { useSpeechRecognition } from 'feojs'

const VoiceRecorder = () => {
  const {
    transcript,
    listening,
    resetTranscript,
    browserSupportsSpeechRecognition
  } = useSpeechRecognition()

  if (!browserSupportsSpeechRecognition) {
    return <span>Browser doesn't support speech recognition.</span>
  }

  return (
    <div>
      <p>Microphone: {listening ? 'on' : 'off'}</p>
      <button onClick={() => SpeechRecognition.startListening()}>Start</button>
      <button onClick={SpeechRecognition.stopListening}>Stop</button>
      <button onClick={resetTranscript}>Reset</button>
      <p>{transcript}</p>
    </div>
  )
}

export default VoiceRecorder

🎯 Voice Commands

Feo supports sophisticated voice command recognition with pattern matching:

import React, { useState } from 'react'
import SpeechRecognition, { useSpeechRecognition } from 'feojs'

const VoiceAssistant = () => {
  const [message, setMessage] = useState('')
  
  const commands = [
    {
      command: 'I would like to order *',
      callback: (food: string) => setMessage(`Your order is for: ${food}`)
    },
    {
      command: 'The weather is :condition today',
      callback: (condition: string) => setMessage(`Today, the weather is ${condition}`)
    },
    {
      command: 'My top sports are * and *',
      callback: (sport1: string, sport2: string) => setMessage(`#1: ${sport1}, #2: ${sport2}`)
    },
    {
      command: 'Pass the salt (please)',
      callback: () => setMessage('My pleasure')
    },
    {
      command: ['Hello', 'Hi'],
      callback: ({ command }: { command: string }) => setMessage(`Hi there! You said: "${command}"`),
      matchInterim: true
    },
    {
      command: 'clear',
      callback: ({ resetTranscript }: { resetTranscript: () => void }) => {
        resetTranscript()
        setMessage('')
      }
    }
  ]

  const {
    transcript,
    listening,
    resetTranscript,
    browserSupportsSpeechRecognition
  } = useSpeechRecognition({ commands })

  const startListening = () => SpeechRecognition.startListening({ 
    continuous: true, 
    language: 'en-US' 
  })

  if (!browserSupportsSpeechRecognition) {
    return <span>Browser doesn't support speech recognition.</span>
  }

  return (
    <div>
      <p>Microphone: {listening ? 'on' : 'off'}</p>
      <button onClick={startListening}>Start Listening</button>
      <button onClick={SpeechRecognition.stopListening}>Stop</button>
      <button onClick={resetTranscript}>Reset</button>
      <p><strong>Transcript:</strong> {transcript}</p>
      {message && <p><strong>Response:</strong> {message}</p>}
    </div>
  )
}

export default VoiceAssistant

📚 API Reference

useSpeechRecognition(options?)

React hook that provides speech recognition state and controls.

Options

interface SpeechRecognitionHookOptions {
  transcribing?: boolean              // Whether to update transcript state (default: true)
  clearTranscriptOnListen?: boolean   // Whether to clear transcript when starting (default: true)
  commands?: SpeechRecognitionCommand[] // Array of voice commands
}

Returns

interface SpeechRecognitionHookState {
  transcript: string                           // Complete transcript
  interimTranscript: string                    // Interim (incomplete) transcript
  finalTranscript: string                      // Final (complete) transcript
  listening: boolean                           // Whether currently listening
  isMicrophoneAvailable: boolean              // Whether microphone is available
  resetTranscript: () => void                 // Function to reset transcript
  browserSupportsSpeechRecognition: boolean   // Whether browser supports speech recognition
  browserSupportsContinuousListening: boolean // Whether browser supports continuous listening
}

📄 License

MIT

🙏 Acknowledgments

🛠️ Development

Automated Release Scripts

This project includes automated scripts for version bumping and releasing:

# Preview what would be released (dry run)
npm run push:dry

# Standard release (with confirmation)
npm run push

# Force release (skip confirmations)
npm run push:force

The scripts automatically:

  • Analyze git commits since the last tag
  • Determine version bump type (major/minor/patch) based on conventional commits
  • Update package.json version
  • Run tests and build the project
  • Create git commit and tag
  • Push changes to remote repository

See scripts/README.md for detailed documentation.

Manual Development

# Start development server
npm run dev

# Run tests
npm test

# Run tests in watch mode
npm run test:watch

# Build the library
npm run build

# Lint code
npm run lint

# Type check
npm run build:types

Made with ❤️ for the React community

You can also install eslint-plugin-react-x and eslint-plugin-react-dom for React-specific lint rules:

// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default tseslint.config([
  globalIgnores(['dist']),
  {
    files: ['**/*.{ts,tsx}'],
    extends: [
      // Other configs...
      // Enable lint rules for React
      reactX.configs['recommended-typescript'],
      // Enable lint rules for React DOM
      reactDom.configs.recommended,
    ],
    languageOptions: {
      parserOptions: {
        project: ['./tsconfig.node.json', './tsconfig.app.json'],
        tsconfigRootDir: import.meta.dirname,
      },
      // other options...
    },
  },
])