Skip to content

tn3w/OpenAge

Repository files navigation

OpenAge - Privacy-first age verification for the web

Privacy-first age verification for the web

OpenAge runs face tracking, liveness checks, and age estimation on-device. Use it as a drop-in age gate with a checkbox-style widget, modal flow, or button binding.

Version Downloads License Demo

At a Glance

Browser-side Server-backed UI
On-device face analysis Optional WASM verification Widget popup, inline embed, bind
No raw camera upload Signed sessions and tokens Normal, compact, invisible
Serverless soft gates Hosted or custom backend Auto, light, dark

Install

npm install @tn3w/openage
<script src="https://cdn.jsdelivr.net/npm/@tn3w/openage/dist/openage.min.js"></script>

Quick Start

CDN

<div class="openage" data-sitekey="ag_live_xxxx" data-callback="onVerified"></div>

<script src="https://cdn.jsdelivr.net/npm/@tn3w/openage/dist/openage.min.js"></script>
<script>
    function onVerified(token) {
        console.log('verified', token);
    }
</script>

npm

import OpenAge from '@tn3w/openage';

OpenAge.render('#gate', {
    mode: 'serverless',
    layout: 'inline',
    minAge: 18,
    callback: (token) => console.log(token),
    errorCallback: (error) => console.error(error),
});

Inline Embed

OpenAge.render('#gate', {
    mode: 'serverless',
    layout: 'inline',
    minAge: 18,
});

layout: 'inline' removes the checkbox shell and renders the verification panel directly in the container. The first verification step starts immediately after loading.

Bound Flow

OpenAge.bind('#buy-btn', {
    sitekey: 'ag_live_xxxx',
    callback: (token) => submitForm(token),
});

Modes

Mode Backend Use case
serverless none client-only soft gates
sitekey OpenAge hosted production verification
custom your server self-hosted verification

serverless keeps everything local and returns a client-signed token. sitekey and custom use a server session and a WASM VM for stronger checks.

Core API

OpenAge.render(container, params);
OpenAge.open(params);
OpenAge.bind(element, params);

OpenAge.reset(widgetId);
OpenAge.remove(widgetId);
OpenAge.getToken(widgetId);
OpenAge.execute(widgetId);

await OpenAge.challenge(params);

Runtime errors keep the popup open long enough to explain what happened. If no camera is available, OpenAge tells the user to plug one in and closes the popup automatically after 5 seconds.

Main Params

Param Values
mode serverless, sitekey, custom
layout widget, inline
theme light, dark, auto
size normal, compact, invisible
minAge number, default 18
sitekey required for hosted mode
server required for custom mode

Demo

cd server
pip install -r requirements.txt
python server.py

The repository also includes demo/, a minimal GitHub Pages build that loads the jsDelivr bundle for @tn3w/openage in inline embedded serverless mode.

Development

npm install
npm test
npm run build
npm run dev

Optional server:

cd server
pip install -r requirements.txt
python server.py

Formatting

pip install black isort
isort . && black .
npx prtfm
clang-format -i server/wasm/src/*.c server/wasm/src/*.h

License

Apache 2.0

About

Privacy-first age check that keeps face processing on the device but still gives the server something it can verify.

Topics

Resources

License

Stars

Watchers

Forks

Contributors