Visora

Developer-first AI safety tooling built on AWS serverless, with the complete infrastructure designed around moderation, verification, redaction and developer workflows.

Visora landing page
Visora overview dashboard
Visora redaction playground
Visora verification playground
Context

Trust layer for every image.

Modern applications run on user-generated images - marketplace listings, social posts, profile photos, identity documents. But making those images safe, private, and trustworthy is still surprisingly hard. Adding content moderation, PII redaction, or identity verification usually means stitching together several expensive, single-purpose services like AWS Rekognition, Hive, Stripe Identity, or Onfido, or building the entire pipeline from scratch. And even then, most tools hand back raw detection labels, not a decision a product can actually act on.

I ran into this myself: a project needed to confirm that uploaded images were trustworthy, and wiring Rekognition, or any alternative, into a real, configurable decision turned out to be far more work than it should have been.

Visora was built to remove that friction. It is the trust layer for every image - a single, developer-first API that unifies three products: content moderation, image redaction, and identity verification behind one integration. Instead of raw model output, teams configure per-project policies: category actions, risk thresholds, compliance packs, blur targets, and verification rules, so every request returns a clear, tailored decision such as allow, review, reject, a redacted image, or verified / rejected rather than something you still have to interpret. It is priced to be affordable and adoption-first, and aimed at developers building marketplaces and social / UGC products.

Role

Built end to end.

Visora was designed and built entirely by me - from product strategy and pricing to UX, system architecture, and the full serverless infrastructure.

I defined the product from the ground up, designed every workflow and interface, and built the platform end-to-end: the developer dashboard with Next.js, the backend with seven purpose-built AWS Lambdas behind API Gateway, the TypeScript SDK, the documentation, Stripe billing, and the entire CI/CD deployment pipeline.

The core of the work was the AWS infrastructure, which I architected and provisioned from scratch: API Gateway, Lambda, Cognito, DynamoDB, S3, Rekognition, Textract, SQS with dead-letter queues, and SES, as a fully serverless system with no servers to manage. It scales automatically with demand and runs on pay-per-use economics, so the platform stays cheap at low volume and absorbs traffic spikes without any manual capacity work. Visora is live in production today, shipped solo in roughly two months, and actively iterating toward its first customers.

Product

The trust layer for every image.

Visora is a developer-first API platform - the trust layer for every image. It brings three products (content moderation, image redaction, and identity verification) together behind a single integration, wrapped in a full developer experience: a dashboard to configure and operate everything, a TypeScript SDK, live documentation, signed webhooks, and usage-based billing.

Everything runs on one serverless backend on AWS, so each product scales independently on pay-per-use economics.

The API

Content Moderation - Scan any image against your policy

Visora scores any image and returns a decision your product can act on directly: allow, review, or reject. Under the hood it runs Amazon Rekognition to detect unsafe content - nudity, violence, weapons, drugs, hate symbols and more - and layers a policy engine on top that turns raw labels into a real decision.

What makes it useful is not the detection, it is the control. Each project defines its own policy: which categories are blocked, the action each one takes (allow / review / reject), minimum confidence, and risk thresholds. Teams can apply compliance packs (marketplace, kids, dating, and more) and a brand-safety signal, so the same API returns a very different verdict for a kids' app than for a marketplace - with zero custom code.

/projects/visora/product/image-01.png
/projects/visora/product/image-02.png

Image Redaction - Blur the sensitive, ship the rest

Redaction detects and removes sensitive regions from an image, then returns a clean, processed version. In a single call, Visora finds faces, text, license plates and specific PII (IDs, emails, dates, financial and medical data) and blurs or black-boxes them in place - so the original never has to leave your pipeline.

Like moderation, it is fully configurable per project: choose the blur targets, the redaction style (blur or black box), which text categories to redact, custom words to always hide, and words to keep visible. The API returns a redacted image URL plus the coordinates of everything it covered.

/projects/visora/product/image-03.png
/projects/visora/product/image-04.png

Identity Verification (KYC) - Is it really them?

Verification checks an identity document against a selfie in a single request and returns one decision: verified, review, or rejected. It runs three checks - document authenticity and field extraction with Amazon Textract, a face match between the selfie and the document portrait with Rekognition CompareFaces, and selfie quality / anti-spoof signals with DetectFaces.

Thresholds are configurable per project (auto-approve similarity, reject cutoff, expired-document handling), and the response includes the extracted document fields, the face-match score, and human-readable reasons for anything not auto-approved. Logs are privacy-preserving by design - the raw PII fields are never stored.

/projects/visora/product/image-05.png
/projects/visora/product/image-06.png
Developer Experience

SDK & Quickstart - Integrate in minutes

Visora ships an official TypeScript SDK (@visoracloud/client) so any product is a few lines of code away from a running backend. It handles multipart uploads, authentication, typed responses and errors, and even verified webhook handlers - so developers never touch the raw HTTP layer.

This matters because Visora competes on adoption: the faster a developer gets from npm install to a real decision, the more likely they are to ship it. moderateImage(), redactImage(), verifyImage() - same shape, same client, one key.

/projects/visora/product/image-07.png

Documentation - Docs for every product

Every product has its own developer documentation - moderation, redaction, verify and webhooks - with copy-paste examples (SDK and cURL), response models, configuration reference and webhook signatures. It is a three-column, searchable live experience built to get a developer productive without leaving the page.

/projects/visora/product/image-08.png

Interactive Playground - Test with no code

The playground runs a real image through any of your projects directly in the dashboard - no code required. It uses the project's own configuration, so what you see is exactly what the API will return. For verification it takes a document and a selfie; for moderation and redaction, a single image, with a live preview before upload.

/projects/visora/product/image-09.png
The Control Plane

Projects & Policies - Configure the decision, not just the detection

Everything in Visora is organized around projects. A project is a moderation, redaction or verify workspace, each with its own configuration, API keys and logs. This is where the platform's flexibility lives: instead of raw model output, every project shapes its own decision - category actions and risk thresholds for moderation, blur targets for redaction, match thresholds for verify.

/projects/visora/product/image-10.png
/projects/visora/product/image-11.png

Activity & Logs - Full history, one drawer

Every request - moderation, redaction and verification - is logged and browsable, with a detail drawer to inspect the decision, the detected regions or labels, the images, and the exact settings that produced the result. It is an audit trail and a debugging surface in the same place.

/projects/visora/product/image-12.png
/projects/visora/product/image-13.png

Human Review - Close the loop with people

When a policy lands on the review action, the result is queued instead of auto-resolved. A built-in review queue lets a person approve or reject flagged content, and the decision fires a webhook so downstream systems stay in sync.

/projects/visora/product/image-14.png

API Keys - Scoped per project

API keys are scoped to a single project, so a moderation key can never touch a verify project. Keys can be created, rotated and revoked from the dashboard, and every request is authenticated and counted against the account's plan.

/projects/visora/product/image-15.png
Production Platform

Webhooks - Real-time, signed, retried

Visora delivers events (moderation.completed, redaction.completed, verification.completed, review decisions...) to your endpoints in real time. Every delivery is HMAC-signed, sent asynchronously through a queue, retried on failure, and moved to a dead-letter queue after repeated failures - so a slow or failing endpoint never blocks the API response. The SDK verifies the signature and narrows the payload by event type for you.

/projects/visora/product/image-16.png

Usage, Plans & Billing - Free tier to scale

Visora runs on a usage-based model: a free tier to try every product, and paid plans with per-product limits and overage. Verification is billed per verification (premium), while moderation and redaction share a monthly request pool. Billing is handled through Stripe - checkout, subscriptions and a customer portal - with usage surfaced live in the dashboard.

/projects/visora/product/image-17.png
/projects/visora/product/image-18.png
Architecture

Serverless foundation.

Visora is a fully serverless system on AWS. There are no servers, containers or always-on compute anywhere in the stack - every piece is either a managed service or an event-driven function.

The frontend is static, the backend is a set of AWS Lambdas behind a single API Gateway, and every heavy capability (identity, data, image AI, email, queues) is a managed AWS service.

Why serverless

Cost

You pay per use, not per uptime. As a solo-built, pre-revenue product with a generous free tier, paying for idle servers made no sense. With serverless, the platform costs almost nothing at zero traffic and scales its cost linearly with real usage. That is what lets Visora offer a free tier and still undercut incumbents on price: the infrastructure's unit economics track the product's.

No operations

There are no servers to provision, patch, autoscale or keep alive. A deploy is just updating function code. For a one-person team, removing the entire "keep the servers running" burden was as valuable as the cost savings.

Scalability & isolation

Each Lambda scales independently and automatically - from zero to thousands of concurrent requests with no capacity planning. A traffic spike on moderation does not affect verification or billing, and a failure in one domain cannot take down the others. Image workloads are bursty and stateless, which is a natural fit for Lambda paired with pay-per-call AI like Rekognition and Textract.

Building blocks
Next.js

Frontend

Next.js static export on S3 + CloudFront

Next.jsS3CloudFront
API Gateway

Edge

One REST API Gateway routing to seven Lambdas

API Gateway
Lambda

Compute

Purpose-built Lambdas for auth, dashboard, moderation, redaction, verify, billing and webhooks

Lambda
Cognito

Identity

Cognito users bridged to app accounts in DynamoDB

CognitoDynamoDB
DynamoDB

Data

13 DynamoDB tables running on on-demand capacity

DynamoDB
S3

Storage

Original and redacted images stored in S3 buckets

S3
Rekognition

Image AI

Managed image intelligence and document extraction

RekognitionTextract
SQS

Async

Webhook queue and dead-letter queue for resilient delivery

SQSDLQ
SES

Email

Transactional verification and account email delivery

SES
Stripe

Payments

Checkout, subscriptions, invoices and customer portal

Stripe
IAM

Permissions

Shared IAM role for the serverless backend

IAM
Flows

Frontend

The frontend is a Next.js app exported to static assets and served from S3 behind CloudFront. There is no server-side rendering at runtime - it is pure static + client-side, talking to the backend over the API.

That means the frontend costs almost nothing to host, is distributed globally by the CDN, and has nothing to patch; every dynamic behavior (auth, dashboard data, playground) happens through API Gateway calls from the browser.

Register

Registration creates two things: the user in Cognito (credentials and identity) and the account in DynamoDB (the business record plus an identity mapping). For email/password, the browser hits POST /auth/register, the Auth Lambda calls Cognito SignUp, Cognito triggers SES to email the verification code, and the same Lambda writes the account (accounts) and the identity mapping (account-identities).

The user then confirms via POST /auth/confirm. OAuth registration works two ways: GitHub goes through the backend (/auth/github/exchange, which issues an app-signed JWT), while Google is federated entirely through Cognito's hosted UI, without touching the backend.

Login

Login is deliberately lean. POST /auth/login goes to the Auth Lambda, then Cognito InitiateAuth, which returns the JWT (id / access / refresh) straight back to the browser. There is no SES and no DynamoDB write - the account already exists.

OAuth login reuses the same exchange endpoints as registration. They are idempotent: an existing account is found, and a new one is created when needed.

Authenticated fetch

Every dashboard request carries an Authorization: Bearer <idToken>. The Dashboard Lambda validates the token locally against Cognito's JWKS (the public signing keys, cached - not a call to Cognito per request), then resolves the account from DynamoDB and does the work.

The key property here is that authentication is stateless and local: the signature is verified in-process, so auth adds no network round-trip and scales for free with the rest of the platform.

Moderation & Redaction

Both products are synchronous, single-Lambda pipelines authenticated with an x-api-key. In one invocation, the Lambda stores or references the image in S3, calls Rekognition, applies its logic, writes a log to DynamoDB, publishes a webhook event, and responds.

Moderation uses DetectModerationLabels with a policy engine that turns labels into allow / review / reject. Redaction uses DetectFaces + DetectText, then Sharp blurs the detected regions, writes the processed image to a second S3 bucket, and returns a presigned URL. There is no S3-event trigger - the Lambda orchestrates everything inline and synchronously.

Webhooks

Webhook delivery is asynchronous, so it never blocks the API response. When a product finishes, its Lambda writes the event to DynamoDB (webhook-events) and enqueues the eventId to SQS, then returns immediately.

SQS triggers the Webhook Worker Lambda, which reads the event and the project's subscribed endpoints, HMAC-signs the payload, and POSTs it to the customer's URL. Failed deliveries are retried by SQS and moved to a dead-letter queue after repeated failures; the dashboard surfaces failed events by reading them back from DynamoDB.

Billing

Billing runs in two directions. User actions from the dashboard, authenticated with the Cognito JWT, go through the Billing Lambda to the Stripe API - creating a checkout session, subscription or customer portal - and return a hosted Stripe URL.

In the other direction, Stripe calls back to /billing/webhook, verified with Stripe's signature rather than a JWT, and the Billing Lambda updates the account's plan and subscription status in DynamoDB and logs the event. Stripe stays the source of truth for payment; DynamoDB is kept in sync through the webhook.

Systems

Engines underneath.

Visora looks simple from the outside - send an image, get a decision - but the value lives in the engines underneath.

Each product is powered by a purpose-built system that turns raw model output into a decision a product can act on, and the platform is held together by systems for delivery, identity and metering that keep it consistent and reliable under real usage.

Policy Engine

The policy engine is the core decision layer behind moderation, and the most logically complex system in Visora. Amazon Rekognition returns raw labels with confidence scores; the policy engine turns those into a single, project-specific verdict.

For every request it discards labels below a minimum confidence, maps each detected category to its configured action (allow, review or reject), scores the overall risk against review and reject thresholds, and layers in a brand-safety signal and any compliance pack the project has enabled. Human review is configurable too - a project can keep "review" as a real outcome routed to a queue, or collapse it into a binary allow/reject with a defined fallback. The result is that the same detection produces a completely different decision per project, driven entirely by configuration rather than code.

Redaction & PII Detection

Redaction combines computer vision with pattern-based detection and in-process image manipulation. Rekognition locates faces and text regions; on top of that, a detection layer classifies text into PII categories using deterministic pattern matching - Luhn-checked card numbers, dates in any format, emails and phone numbers, IDs and tax numbers, API keys and secrets - so a project can redact only the data types it cares about instead of blurring all text.

The matched regions are then processed in the same function with Sharp: each bounding box is padded and blurred or covered with a solid box, and the result is written to a dedicated bucket and returned as a presigned URL. Custom always-redact and never-redact word lists let teams tune the behavior to their own document formats.

Verification Decision Engine

Identity verification fuses three independent signals into one decision. The engine runs Textract's document analysis (fields, type and expiry), a Rekognition face comparison between the selfie and the document portrait, and a selfie quality / anti-spoof check, then reconciles them against per-project thresholds: a strong face match with a valid document and a clean selfie is auto-approved; a match below the reject cutoff, or a missing or expired document, is rejected; anything in between is sent to review with human-readable reasons.

It is privacy-preserving by design - the decision, scores and reasons are stored, but the extracted document fields never are.

Webhook Delivery System

Webhooks are an event-driven pipeline built around asynchronous, resilient delivery. When a product finishes, it persists the event and enqueues its id to a queue, then returns immediately - delivery is fully decoupled from the API response. A dedicated worker consumes the queue, looks up the project's subscribed endpoints, signs the payload with a per-endpoint HMAC secret, and delivers it.

The system is built to survive failing customer endpoints: deliveries are idempotent, every event tracks its own status (pending, delivered, failed or skipped) and attempt history, failures are retried automatically, and messages that exhaust their retries land in a dead-letter queue. Failed events stay queryable so they can be inspected or replayed from the dashboard.

Usage, Metering & Billing State

Usage, limits and payment are tracked as separate but connected systems, so no single lifecycle becomes fragile. Every request is metered per account and month; plans define the request pool and per-product limits, with a smaller free-tier cap enforced by counting a project's logs. Verification is metered on its own path rather than sharing the general pool, since it is a higher-cost operation.

Payment state lives in Stripe and is reconciled back into the account through webhooks - checkout, subscription changes and invoices update the account's plan and status independently of the request path, keeping the two in sync without coupling them.

Outcomes

Built, shipped, usable.

Visora turns something that used to require stitching together several expensive, single-purpose services - or building an entire image pipeline from scratch - into a single API.

Content moderation, redaction and identity verification now live behind one integration, one dashboard and one SDK.

It is live in production and publicly usable today: anyone can sign up, create a project and start calling the API, and the official client is published on npm as @visoracloud/client.

Product Outcome

Visora gives developers a single, configurable trust layer for images. Instead of wiring together Rekognition, a moderation vendor and a KYC provider - each with its own SDK, pricing and integration - a team adds moderation, redaction or verification through one API that returns a decision shaped by their own policy, not raw model output.

For the marketplaces and social products it targets, that collapses weeks of integration and several vendor bills into a single dependency.

Technical Outcome

The core outcome is a complete, production-grade serverless architecture on AWS, designed and provisioned end-to-end. The entire backend runs without a single server: one API Gateway routes to seven purpose-built Lambdas, backed by Cognito, DynamoDB, S3, Rekognition, Textract, SQS with a dead-letter queue, SES and Stripe - all under a single IAM role and deployed through CI/CD.

Because it is serverless, the platform scales automatically and independently per product, costs almost nothing at idle, and runs on pay-per-use economics with no capacity planning and no servers to operate. On that foundation it is genuinely production-ready: stateless JWT authentication validated against Cognito's public keys, per-project API-key scoping, usage metering and plan enforcement, and a resilient asynchronous webhook system with HMAC signing, automatic retries and dead-lettering. Each domain is isolated in its own function, so load or a failure in one product never affects the others.

Strategic Outcome

More than anything, Visora demonstrates my ability to design, build and operate a complete production system on AWS - end-to-end and solo - in roughly two months. It was not just writing application code; it was making the architectural decisions that define the system: betting on serverless for cost and scale, modeling identity and accounts across a managed provider and my own data layer, designing event-driven webhook delivery with retries and dead-letter handling, and keeping the whole platform stateless, isolated and cheap to run.

It reflects how I approach cloud systems: serverless-first, scalable, cost-aware and production-ready - architected as a set of independent, managed services rather than a monolith, and shipped as a real, publicly available product.