Self-host
Run the Emojisense API on your own Cloudflare account.
On this page
The Emojisense API is open source (MIT). You can run it on your own Cloudflare account, with your own Workers AI calls and your own database.
What you run
The API is one Cloudflare Worker, packages/worker. It serves the data packs, culture files and per-language vector files as static files, keeps the shared (English) emoji vectors in its own bundle and loads a language’s vectors on its first query, embeds queries with Workers AI, caches answers in each data center and stores keys and usage in D1. There are no containers, load balancers or vector databases to run.
You call the embedding model on your own account, under the model’s license. Model weights are never part of the repository.
Requirements
- Node.js 24 and pnpm 9.
- A Cloudflare account with Workers AI. For production traffic, use Workers Paid ($5 a month).
wrangler loginon the machine that embeds the emoji and deploys the Worker.
Steps
Build the data packs
This joins Emojibase, Unicode CLDR and the alias files into the locale packs.
git clone https://github.com/emojisense/emojisense.git emojisense cd emojisense pnpm install pnpm data:buildEmbed the emoji on your account
This sends the emoji descriptions to Workers AI in batches and writes the vector files: one shared file from the English descriptions and one per other language. Queries and emoji must use the same model at the same size, so keep your choice.
bge-m3at 1,024 dimensions is the production model.npx wrangler login pnpm --filter @emojisense/data embed -- --models bge-m3 --dims 1024Copy the packs and vectors into the Worker
pnpm --filter @emojisense/worker sync -- --model bge-m3 --dims 1024It also builds the culture files and writes a content hash of the packs, vectors and engine into the Worker config. The search cache key holds that hash, so run it again after every data or engine change.
Create the database
D1 holds apps, keys and monthly usage. The schema is in
packages/platform/migrations.cd packages/worker npx wrangler d1 create emojisense # copy the database_id into wrangler.jsonc npx wrangler d1 migrations apply DB --remoteConfigure
Edit
packages/worker/wrangler.jsoncbefore the first deploy:name: the Worker name, which is also itsworkers.devsubdomain.vars.DEV_KEYS: keys that need no database row, askeyorkey:plan, comma-separated. They allow any origin.ratelimits: requests per minute for keyed callers (default 120 per key and IP address) and anonymous callers (default 30 per IP address).vars.ENVIRONMENT:stagingorproductionmakes the API refuse plainhttp://on a public host with403. Leave it out, or setdevelopment, for local runs.
Deploy
pnpm --filter @emojisense/worker deployPoint your apps at it
const sense = useEmojisense({ packBaseUrl: "https://emojisense-api.<your-subdomain>.workers.dev/v1/pack/0.1.0", endpoint: "https://emojisense-api.<your-subdomain>.workers.dev", });
Keys and usage
The dashboard, apps/dashboard, issues keys, binds them to origins and shows usage per month. It is a second Worker that uses the same D1 database. Its README explains the sign-in setup with Clerk.
Try it without a Cloudflare account
Workers AI has no local emulator. The offline mode starts the Worker with an empty vector file, so it answers with dictionary results only and marks them "degraded": true. The development keys pk_demo and sk_live_local work without a database row.
pnpm --filter @emojisense/worker sync -- --placeholder
pnpm --filter @emojisense/worker db:migrate
pnpm --filter @emojisense/worker dev:offline # http://localhost:8788