
Security News
arXiv Is Rate Limiting Authors Following a Flood of AI Slop Submissions
arXiv now limits authors to two submissions a month as AI slop overwhelms moderators, delays good papers, and sparks debate over applying the limit to everyone.
react-sms-otp
Advanced tools
React SMS OTP — Twilio alternative for developers. Send + verify OTP codes from React, plus a polished <OtpInput /> ready-to-use UI (separators, RTL, mask, render props, error states). Drop-in <OtpForm /> for full phone-verification flow. useSms8Otp() hoo
Send and verify SMS OTP codes from React — useSms8Otp() hook, <OtpForm /> drop-in, and <OtpInput /> six-box code field. Routes through your own Android phone. No Twilio, no Vonage Verify, no MessageBird Verify. No per-OTP fees. No markups.
import { OtpForm } from 'react-sms-otp';
<OtpForm
apiKey={process.env.NEXT_PUBLIC_SMS8_API_KEY!}
onVerified={(phone) => router.push('/dashboard')}
/>
Get a free API key at sms8.io — 5-day trial, no credit card.
| Twilio Verify / Vonage Verify | react-sms-otp + SMS8 | |
|---|---|---|
| Per-OTP cost | $0.05 – $0.10 each | $0 (flat $29/mo unlimited) |
| A2P 10DLC paperwork | Required for any US OTP volume | Not required — P2P SMS from a real SIM |
| Sender ID | Short code or random LCN | Your real mobile number |
| Reply support | Extra fees, harder to wire up | Built-in — replies sync into your dashboard |
| Setup time | Days (brand registration, A2P review) | Minutes (pair Android, paste API key) |
| Free trial | Pay-as-you-go from message 1 | 5 days unlimited, no card required |
npm install react-sms-otp
# or
pnpm add react-sms-otp
# or
yarn add react-sms-otp
Works with React 17+, including Next.js 13/14/15 (App Router or Pages Router), Remix, Vite, CRA. Server-side calls (route handlers, server actions, edge functions) can use the Sms8Otp class without React.
import { OtpForm } from 'react-sms-otp';
export default function LoginPage() {
return (
<OtpForm
apiKey={process.env.NEXT_PUBLIC_SMS8_API_KEY!}
onVerified={(phone) => {
console.log('Verified:', phone);
// redirect, create session, etc.
}}
/>
);
}
That's the entire phone-verification flow. The form handles phone input → send → 6-box code input → verify → success state. iOS SMS auto-fill and Android SMS Retriever work because the inputs use autoComplete="one-time-code" and inputMode="numeric".
Tip: in production, never expose your API key to the browser. Proxy through your backend (Next.js route handler, Remix loader, Express endpoint) and call the Sms8Otp class from there.
useSms8Otp(opts) hook — full controlimport { useSms8Otp, OtpInput } from 'react-sms-otp';
function CustomLogin() {
const { send, verify, status, error, reset } = useSms8Otp({
apiKey: process.env.NEXT_PUBLIC_SMS8_API_KEY!,
});
const [phone, setPhone] = useState('');
const [code, setCode] = useState('');
return (
<>
<input
type="tel"
autoComplete="tel"
value={phone}
onChange={(e) => setPhone(e.target.value)}
/>
<button onClick={() => send({ phone })} disabled={status === 'sending'}>
{status === 'sending' ? 'Sending…' : 'Send code'}
</button>
{status === 'sent' && (
<OtpInput
length={6}
value={code}
onChange={setCode}
onComplete={(c) => verify({ phone, code: c })}
/>
)}
{status === 'verified' && <p>Welcome!</p>}
{error && <p style={{ color: 'red' }}>{error}</p>}
</>
);
}
Status values: idle | sending | sent | verifying | verified | error.
<OtpForm /> drop-in component<OtpForm
apiKey="sk_xxx"
phone="+14155550100" // optional, hides the phone input
length={6} // 4 to 8
sendOptions={{
template: 'Your YourApp code: {code}',
expiresIn: 300,
maxAttempts: 5,
deviceId: 10700, // pin a specific paired phone
simSlot: '1', // multi-SIM Android
}}
onVerified={(phone) => { /* success */ }}
onFailed={(error) => { /* retried too many times */ }}
labels={{
phone: 'Mobile number',
sendButton: 'Text me a code',
code: 'Enter the 6 digits',
verifyButton: 'Confirm',
}}
/>
<OtpInput /> ready-to-use OTP input UIA polished N-box OTP input you can drop into any auth flow — even if you already have your own send/verify logic with Twilio, Auth0, Supabase, or Clerk. Use it standalone as a pure UI component.
Features at parity with react-otp-input and more:
inputMode="numeric" + autoComplete="one-time-code" triggers iOS "From Messages" suggestion<OtpInput renderSeparator={(i) => i === 2 ? <span>-</span> : null} />rtl prop swaps direction for Arabic / Hebrewmask shows • instead of digits (useful in shared screens)error prop adds red border, sets aria-invalidrenderInput={(props, state) => ...}inputClassName, focusedClassName, filledClassName, errorClassNamearia-label per box, role="group" on containerOtpInputState, OtpInputProps, OtpRenderInputProps typesBasic usage:
import { OtpInput } from 'react-sms-otp';
<OtpInput
length={6}
value={code}
onChange={setCode}
onComplete={(c) => submitVerify(c)}
/>
With separator (e.g. 123-456 style):
<OtpInput
length={6}
value={code}
onChange={setCode}
renderSeparator={(i) => i === 2 ? <span style={{margin:'0 4px'}}>—</span> : null}
/>
Masked / hidden code:
<OtpInput length={6} value={code} onChange={setCode} mask />
RTL (Arabic, Hebrew):
<OtpInput length={6} value={code} onChange={setCode} rtl />
Error state:
<OtpInput length={6} value={code} onChange={setCode} error={!!verifyError} />
Full custom render with Tailwind / shadcn:
<OtpInput
length={6}
value={code}
onChange={setCode}
renderInput={(props, { focused, error }) => (
<input
{...props}
className={`
w-12 h-14 text-center text-xl font-bold border-2 rounded-lg
${focused ? 'border-indigo-500 ring-2 ring-indigo-200' : 'border-gray-200'}
${error ? 'border-red-500 bg-red-50' : ''}
`}
/>
)}
/>
Works with your own send/verify — drop it into a Clerk, Auth0, Supabase, or custom-backed OTP flow:
const [code, setCode] = useState('');
<OtpInput
length={6}
value={code}
onChange={setCode}
onComplete={async (c) => {
const ok = await yourBackend.verifyCode(phone, c);
if (ok) router.push('/dashboard');
}}
/>
Sms8Otp class — server-side / non-React// app/api/send-otp/route.ts (Next.js App Router)
import { Sms8Otp } from 'react-sms-otp';
export async function POST(req: Request) {
const { phone } = await req.json();
const otp = new Sms8Otp({ apiKey: process.env.SMS8_API_KEY! });
const result = await otp.send({ phone, length: 6 });
return Response.json(result);
}
// Server route handler (Next.js, Remix, etc.)
import { Sms8Otp } from 'react-sms-otp';
const otp = new Sms8Otp({ apiKey: process.env.SMS8_API_KEY! });
export async function sendOtp(phone: string) {
'use server';
return otp.send({ phone, length: 6 });
}
// Client component — call your server action, not SMS8 directly
'use client';
import { useState } from 'react';
import { OtpInput } from 'react-sms-otp';
import { sendOtp, verifyOtp } from './actions';
export function PhoneVerify() {
const [phone, setPhone] = useState('');
const [code, setCode] = useState('');
const [stage, setStage] = useState<'phone' | 'code'>('phone');
return stage === 'phone' ? (
<>
<input value={phone} onChange={(e) => setPhone(e.target.value)} />
<button onClick={async () => { await sendOtp(phone); setStage('code'); }}>
Send code
</button>
</>
) : (
<OtpInput
length={6}
value={code}
onChange={setCode}
onComplete={async (c) => {
const result = await verifyOtp(phone, c);
if (result.verified) router.push('/welcome');
}}
/>
);
}
The <OtpInput /> and <OtpForm /> components both set:
autoComplete="one-time-code" — triggers iOS SMS auto-fill suggestion above the keyboardinputMode="numeric" — shows the number pad on mobilepattern="[0-9]*" — extra hint for older keyboardsFor Android SMS Retriever API (auto-read without user pasting), you need a server-side hash appended to the SMS body. SMS8 supports this via the template option:
<OtpForm
apiKey="sk_xxx"
sendOptions={{
template: '<#> Your YourApp code: {code}\n\nABcd1234efg', // <-- 11-char app hash at end
}}
/>
See Google's SMS Retriever docs for hash generation.
sms8-cli — terminal CLI (same backend)sms8-mcp — MCP launcher for Claude Code / Cursor / Windsurfsms-otp-using-myphone — OTP-focused CLIphone-sms-gateway — phone-as-gateway CLIsend-sms-from-android — Android-first CLIMIT
FAQs
React SMS OTP — Twilio alternative for developers. Send + verify OTP codes from React, plus a polished <OtpInput /> ready-to-use UI (separators, RTL, mask, render props, error states). Drop-in <OtpForm /> for full phone-verification flow. useSms8Otp() hoo
The npm package react-sms-otp receives a total of 4 weekly downloads. As such, react-sms-otp popularity was classified as not popular.
We found that react-sms-otp demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
arXiv now limits authors to two submissions a month as AI slop overwhelms moderators, delays good papers, and sparks debate over applying the limit to everyone.

Research
/Security News
A new GhostAction wave hits hundreds of GitHub repos, expanding CI/CD secret theft to cloud and AI credentials in source code and git history.

Research
/Security News
Tensorlake npm SDK version 0.5.144 was compromised in a ChainDrop / Shai-Hulud attack, delivering credential-stealing malware.