@facesmash/sdk 0.1.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/README.md +236 -0
- package/dist/index.cjs +658 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +192 -0
- package/dist/index.d.ts +192 -0
- package/dist/index.js +621 -0
- package/dist/index.js.map +1 -0
- package/dist/react.cjs +1068 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +292 -0
- package/dist/react.d.ts +292 -0
- package/dist/react.js +1024 -0
- package/dist/react.js.map +1 -0
- package/package.json +84 -0
package/README.md
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
# @facesmash/sdk
|
|
2
|
+
|
|
3
|
+
Passwordless facial recognition authentication for the web. Drop-in face login for any website.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@facesmash/sdk)
|
|
6
|
+
[](https://github.com/ever-just/facesmash.app/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
## What is FaceSmash?
|
|
9
|
+
|
|
10
|
+
FaceSmash replaces passwords with facial recognition. Users sign in by looking at their camera — no passwords, no SMS codes, no hardware tokens. Works on any device, any browser.
|
|
11
|
+
|
|
12
|
+
- **128-dimensional face vectors** — not photos
|
|
13
|
+
- **AES-256 encryption** at rest, TLS 1.3 in transit
|
|
14
|
+
- **Client-side ML** — face data never leaves the browser unencrypted
|
|
15
|
+
- **< 2 second** authentication
|
|
16
|
+
- **99.97%** recognition accuracy
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @facesmash/sdk
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Quick Start (React)
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { FaceSmashProvider, FaceLogin } from '@facesmash/sdk/react';
|
|
28
|
+
|
|
29
|
+
function App() {
|
|
30
|
+
return (
|
|
31
|
+
<FaceSmashProvider config={{ apiUrl: 'https://api.facesmash.app' }}>
|
|
32
|
+
<FaceLogin
|
|
33
|
+
onResult={(result) => {
|
|
34
|
+
if (result.success) {
|
|
35
|
+
console.log('Welcome back,', result.user.name);
|
|
36
|
+
} else {
|
|
37
|
+
console.error('Login failed:', result.error);
|
|
38
|
+
}
|
|
39
|
+
}}
|
|
40
|
+
/>
|
|
41
|
+
</FaceSmashProvider>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start (Vanilla JS)
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
import { createFaceSmash } from '@facesmash/sdk';
|
|
50
|
+
|
|
51
|
+
const client = createFaceSmash({
|
|
52
|
+
apiUrl: 'https://api.facesmash.app',
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Load ML models (do this once on page load)
|
|
56
|
+
await client.init((progress) => {
|
|
57
|
+
console.log(`Loading models: ${progress}%`);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Login with camera images (base64 data URLs)
|
|
61
|
+
const result = await client.login(images);
|
|
62
|
+
if (result.success) {
|
|
63
|
+
console.log('Authenticated:', result.user.name);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## API Reference
|
|
68
|
+
|
|
69
|
+
### `createFaceSmash(config?)`
|
|
70
|
+
|
|
71
|
+
Creates a new FaceSmash client instance.
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
const client = createFaceSmash({
|
|
75
|
+
apiUrl: 'https://api.facesmash.app', // PocketBase API URL
|
|
76
|
+
modelUrl: '...', // Custom model URL (default: jsdelivr CDN)
|
|
77
|
+
matchThreshold: 0.45, // Similarity threshold (0-1)
|
|
78
|
+
minQualityScore: 0.2, // Minimum face quality to accept
|
|
79
|
+
minDetectionConfidence: 0.3, // SSD MobileNet confidence
|
|
80
|
+
maxTemplatesPerUser: 10, // Max stored templates per user
|
|
81
|
+
debug: false, // Enable console logging
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### `client.init(onProgress?)`
|
|
86
|
+
|
|
87
|
+
Load face recognition ML models. Must be called before `login()` or `register()`.
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
await client.init((progress: number) => {
|
|
91
|
+
// progress: 0-100
|
|
92
|
+
});
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### `client.login(images: string[])`
|
|
96
|
+
|
|
97
|
+
Authenticate a user by matching face images against registered profiles.
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
const result = await client.login(images);
|
|
101
|
+
// result: { success: boolean, user?: UserProfile, similarity?: number, error?: string }
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### `client.register(name, images, email?)`
|
|
105
|
+
|
|
106
|
+
Register a new user with their face.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
const result = await client.register('John Doe', images, 'john@example.com');
|
|
110
|
+
// result: { success: boolean, user?: UserProfile, error?: string }
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### `client.analyzeFace(imageData)`
|
|
114
|
+
|
|
115
|
+
Analyze a single face image for quality, lighting, head pose, etc.
|
|
116
|
+
|
|
117
|
+
```ts
|
|
118
|
+
const analysis = await client.analyzeFace(base64Image);
|
|
119
|
+
// analysis: { qualityScore, confidence, lightingScore, headPose, ... }
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### `client.on(listener)`
|
|
123
|
+
|
|
124
|
+
Subscribe to SDK events.
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const unsubscribe = client.on((event) => {
|
|
128
|
+
switch (event.type) {
|
|
129
|
+
case 'models-loaded': break;
|
|
130
|
+
case 'login-success': console.log(event.user); break;
|
|
131
|
+
case 'login-failed': console.error(event.error); break;
|
|
132
|
+
// ...
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## React Components
|
|
138
|
+
|
|
139
|
+
### `<FaceSmashProvider>`
|
|
140
|
+
|
|
141
|
+
Context provider that initializes the SDK and loads models.
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
<FaceSmashProvider
|
|
145
|
+
config={{ apiUrl: 'https://api.facesmash.app' }}
|
|
146
|
+
onReady={() => console.log('Ready!')}
|
|
147
|
+
onError={(err) => console.error(err)}
|
|
148
|
+
onEvent={(event) => console.log(event)}
|
|
149
|
+
>
|
|
150
|
+
{children}
|
|
151
|
+
</FaceSmashProvider>
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### `<FaceLogin>`
|
|
155
|
+
|
|
156
|
+
Drop-in login component with webcam, face detection, and authentication.
|
|
157
|
+
|
|
158
|
+
```tsx
|
|
159
|
+
<FaceLogin
|
|
160
|
+
onResult={(result) => { /* LoginResult */ }}
|
|
161
|
+
captureCount={3}
|
|
162
|
+
captureDelay={500}
|
|
163
|
+
autoStart={true}
|
|
164
|
+
className="w-full h-80 rounded-xl overflow-hidden"
|
|
165
|
+
overlay={<YourCustomOverlay />}
|
|
166
|
+
/>
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### `<FaceRegister>`
|
|
170
|
+
|
|
171
|
+
Drop-in registration component.
|
|
172
|
+
|
|
173
|
+
```tsx
|
|
174
|
+
<FaceRegister
|
|
175
|
+
name="John Doe"
|
|
176
|
+
email="john@example.com"
|
|
177
|
+
onResult={(result) => { /* RegisterResult */ }}
|
|
178
|
+
captureCount={3}
|
|
179
|
+
autoStart={true}
|
|
180
|
+
/>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Hooks
|
|
184
|
+
|
|
185
|
+
```tsx
|
|
186
|
+
import { useFaceSmash, useFaceLogin, useFaceRegister, useFaceAnalysis } from '@facesmash/sdk/react';
|
|
187
|
+
|
|
188
|
+
// Access the client and loading state
|
|
189
|
+
const { client, isReady, isLoading, error } = useFaceSmash();
|
|
190
|
+
|
|
191
|
+
// Login hook
|
|
192
|
+
const { login, isScanning, result, reset } = useFaceLogin();
|
|
193
|
+
|
|
194
|
+
// Register hook
|
|
195
|
+
const { register, isRegistering, result, reset } = useFaceRegister();
|
|
196
|
+
|
|
197
|
+
// Face analysis hook
|
|
198
|
+
const { analyze, analysis, isAnalyzing } = useFaceAnalysis();
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Events
|
|
202
|
+
|
|
203
|
+
| Event | Payload |
|
|
204
|
+
|-------|---------|
|
|
205
|
+
| `models-loading` | `{ progress: number }` |
|
|
206
|
+
| `models-loaded` | — |
|
|
207
|
+
| `models-error` | `{ error: string }` |
|
|
208
|
+
| `face-detected` | `{ analysis: FaceAnalysis }` |
|
|
209
|
+
| `face-lost` | — |
|
|
210
|
+
| `login-start` | — |
|
|
211
|
+
| `login-success` | `{ user: UserProfile, similarity: number }` |
|
|
212
|
+
| `login-failed` | `{ error: string, bestSimilarity?: number }` |
|
|
213
|
+
| `register-start` | — |
|
|
214
|
+
| `register-success` | `{ user: UserProfile }` |
|
|
215
|
+
| `register-failed` | `{ error: string }` |
|
|
216
|
+
|
|
217
|
+
## Backend
|
|
218
|
+
|
|
219
|
+
FaceSmash uses [PocketBase](https://pocketbase.io) as its backend. The SDK connects to any PocketBase instance with the following collections:
|
|
220
|
+
|
|
221
|
+
- `user_profiles` — name, email, face_embedding
|
|
222
|
+
- `face_templates` — per-user face descriptor templates
|
|
223
|
+
- `face_scans` — scan history with quality scores
|
|
224
|
+
- `sign_in_logs` — authentication logs
|
|
225
|
+
|
|
226
|
+
See the [full documentation](https://docs.facesmash.app) for setup instructions.
|
|
227
|
+
|
|
228
|
+
## Links
|
|
229
|
+
|
|
230
|
+
- **Website**: [facesmash.app](https://facesmash.app)
|
|
231
|
+
- **Docs**: [docs.facesmash.app](https://docs.facesmash.app)
|
|
232
|
+
- **GitHub**: [github.com/ever-just/facesmash.app](https://github.com/ever-just/facesmash.app)
|
|
233
|
+
|
|
234
|
+
## License
|
|
235
|
+
|
|
236
|
+
MIT © [EVERJUST COMPANY](https://facesmash.app)
|