From vivreal-knowledge
The **public content-delivery stack**: deployed customer sites (Vivreal_Templates) call `VR_Client_API` to fetch content + run Stripe checkout + send emails, and every request first passes `VR_Client_Auth` — a tiny custom Lambda authorizer that validates the group's API key and injects tenant context. **This pair is the only Vivreal backend using API-key auth (not Cognito).** Read `C:\repos\VR_Client_API\CLAUDE.md` and `C:\repos\VR_Client_Auth\CLAUDE.md` for depth.
How this skill is triggered — by the user, by Claude, or both
Slash command
/vivreal-knowledge:vivreal-client-stack-knowledgeThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
The **public content-delivery stack**: deployed customer sites (Vivreal_Templates) call `VR_Client_API` to fetch content + run Stripe checkout + send emails, and every request first passes `VR_Client_Auth` — a tiny custom Lambda authorizer that validates the group's API key and injects tenant context. **This pair is the only Vivreal backend using API-key auth (not Cognito).** Read `C:\repos\VR_...
The public content-delivery stack: deployed customer sites (Vivreal_Templates) call VR_Client_API to fetch content + run Stripe checkout + send emails, and every request first passes VR_Client_Auth — a tiny custom Lambda authorizer that validates the group's API key and injects tenant context. This pair is the only Vivreal backend using API-key auth (not Cognito). Read C:\repos\VR_Client_API\CLAUDE.md and C:\repos\VR_Client_Auth\CLAUDE.md for depth.
A tiny, focused custom Lambda authorizer in front of VR_Client_API. Its only job: validate the incoming API key and return an IAM Allow/Deny policy + tenant context.
event.authorizationToken (raw API key from the Authorization header — no Bearer prefix) + event.methodArn.Vivreal, groups.findOne({ apiKey: token }). Found → Allow + context. Not found / any exception → Deny (fail closed).req.apiGateway.event.requestContext.authorizer): { database, bucketName, groupID, groupName, frozen }.| Tier | database injected |
|---|---|
free, basic, pro | general_shared |
proplus | pro_plus |
This is the same dbKey routing the rest of the stack uses (see vivreal-db), decided here at the edge for the public API.
serverless.yml. (See vivreal-lambda for the deploy-outlier list.)readyState === 1 check). All logic in index.js; groupSchema.js mirrors the group doc; scripts/db.js is the pooled singleton.The public content-delivery API. Single monolith Lambda, Express + serverless-express (Node 20, arm64), SAM, @vivreal/schemas. API-key auth (not Cognito) via VR_Client_Auth above. Reads tenant context from req.apiGateway.event.requestContext.authorizer — database / groupID / groupName / bucketName / frozen.
/tenant/*, all behind frozenCheckGET collectionObjects (published only), GET integrationObjects, GET siteDetails, GET preview (bypasses publishDate), POST createCheckoutSession (customer's OWN Stripe key, passed per-request), POST definedCollectionObject, POST sendContactEmail, POST sendOrderPlacedEmail.
GET /tenant/collectionObjects returns only publishDate <= now && !archived. So missing content = publishDate is null (draft), in the future (scheduled), or stored as a string instead of a Date (silently dropped by the $lte: new Date() filter — type bracketing). Check publishDate type + value first. preview bypasses this gate. (Full rules: vivreal-db; the site-product/authoring angle: vivreal-sites.)
Media served via media.vivreal.io with signed URLs (unsigned → 403). buildMediaUrl.js builds the URL, signCloudFrontUrl.js signs with the CloudFront key pair (private key in Secrets Manager CLOUDFRONT_SIGNING_PRIVATE_KEY — must be an RSA private key; public key → falls back to unsigned). TTL 300s default. The signed URL lands in currentFile.source on each media field — templates use it directly. Never build CDN URLs manually. (Infra view: vivreal-media-cdn.)
frozenCheck middleware reads frozen from authorizer context and returns 400 "The group is frozen" on every route for suspended groups.
targetField.name pattern silently no-op'd on arrays; the bug lived in 5 duplicate copies (3 inline + 2 helpers). Galleries never signed despite appearing to work. Now one shared impl. Watch for regressions in media-signing helpers; looksLikeMediaItem requires mimeType. (Full bug class: vivreal-media-cdn.)basic/ + ecommerce/ dirs at root are alternate deploy configs sharing src/.GET /health.vivreal-atlas-topology + vivreal-lambda.npx claudepluginhub hillbombcreations/vivreal-skills --plugin vivreal-knowledgeProvides CDSS development patterns for drug interaction checking, dose validation, clinical scoring (NEWS2, qSOFA), and alert classification integrated into EMR workflows.