Install Vendwick on an EmDash Site
Vendwick is a native EmDash plugin that you install from a licensed tarball. This page covers what your site needs, how to install the package, and how to wire it into your Astro config and your Cloudflare Worker.
Requirements
- EmDash
^1.5.0and Astro^7.4.12(thepeerDependencies). React 19 for the admin pages. The 0.2.0 admin (sidebar folders, dashboard widgets, editor panels) relies on EmDash 1.5 behavior and was built and checked only on 1.5, so EmDash 1.4 is no longer supported; 0.1.0 still runs on 1.4. Astro 7.4.12 is the version it is built and tested with. - Cloudflare Workers with a D1 database for EmDash and a private R2 bucket for releases and downloads (and, since 0.2.0, cached invoice PDFs and store import files; the bucket and binding are unchanged). EmDash’s Node adapter with a local directory for private files also works; the demo site runs that way.
EMDASH_ENCRYPTION_KEYset as a secret. EmDash uses it to encrypt plugin secrets: gateway keys, webhook secrets and Vendwick’s signing secret.- An email provider plugin that gives plugins
ctx.email. Receipts, license keys, sign-in links and reminders go out through it. Without one they wait in the mail queue. - A cron trigger (
*/5 * * * *) so EmDash’s scheduled handler runs. Vendwick schedules one 5-minute task and does its hourly and daily work from it (unchanged in 0.2.0; webhook retries and import runs use the same task).
The plugin asks EmDash for these capabilities:
email:sendfor receipts, keys, sign-in links and reminders;network:requestfor the gateway APIs, VIES, Turnstile, its own license check and the optional Cloudflare PDF engine (api.cloudflare.com, new in 0.2.0);network:request:unrestrictedfor outgoing webhooks to your own servers (new in 0.2.0, so admins confirm it when upgrading);media:readfor product images and the invoice logo;content:readfor page access targets and product pages.
Install
Vendwick isn’t on the public npm registry. Download the tarball from your account at gauravtiwari.org, put it in your project and install it:
mkdir -p vendor
cp ~/Downloads/gatilab-emdash-vendwick-0.2.0.tgz vendor/
pnpm add ./vendor/gatilab-emdash-vendwick-0.2.0.tgz
Each release ships with its SHA-256 and SHA-512. Check the file before you install it: shasum -a 256 vendor/gatilab-emdash-vendwick-0.2.0.tgz.
Then wire it into astro.config.mjs. vendwick() is the EmDash plugin. vendwickSite() is a companion Astro integration that serves what plugin routes can’t: HTML pages, cookies, file streams and off-site redirects.
// astro.config.mjs
import { defineConfig } from "astro/config";
import emdash from "emdash/astro";
import { vendwick } from "@gatilab/emdash-vendwick";
import { vendwickSite } from "@gatilab/emdash-vendwick/site";
const site = "https://store.example.com";
// The plugin (emails, links) and the companion (pages) must agree on these paths.
const paths = { checkoutPath: "/checkout/", portalBase: "/account/", productBase: "/products/" };
export default defineConfig({
site,
output: "server",
integrations: [
emdash({
// database, storage and adapter as your EmDash site already has them
plugins: [vendwick({ siteUrl: site, ...paths })],
}),
vendwickSite({ ...paths, termsUrl: "/terms/", privacyUrl: "/privacy/" }),
],
});
Finally, enter your Vendwick license key on the admin Vendwick license page (Store settings). The check is soft: without a valid license the store keeps selling and nothing is switched off, but you see a notice and update information stops.
vendwick() options
The options are the same as in 0.1.0.
| Option | Default | Notes |
|---|---|---|
privateFiles | { kind: "r2", binding: "VENDWICK_PRIVATE" } | Where releases and downloads live. { kind: "node", directory } for Node. Never your public media bucket. |
siteUrl | none | Your public origin. Cron jobs and emails have no request to read it from. Set it. |
checkoutPath | /checkout/ | Used in emails and API responses. Must match vendwickSite(). |
portalBase | /account/ | Same. |
productBase | /products/ | Same. |
vendwickSite() options
The options are the same as in 0.1.0.
| Option | Default | Notes |
|---|---|---|
checkoutPath | /checkout/ | The native checkout page. |
portalBase | /account/ | The customer portal. |
productBase | /products/ | Product index and product pages. |
eddCompat | true | Answer EDD Software Licensing clients that send ?edd_action= to any URL. |
privateFilesBinding | VENDWICK_PRIVATE | R2 binding for private files. Must match privateFiles on the plugin. |
privateFilesDirectory | none | A Node directory instead of R2. |
termsUrl, privacyUrl | none | Linked from the checkout’s terms checkbox. Same-site paths or http(s) URLs. |
supportUrl | none | "Get support" link in the portal. |
accessPaths | [] | Paths the middleware always guards, /members (exact) or /members/* (prefix). See Page Access for Buyers. |
Wrangler bindings
// wrangler.jsonc (the parts Vendwick needs)
{
"r2_buckets": [{ "binding": "VENDWICK_PRIVATE", "bucket_name": "your-private-bucket" }],
"triggers": { "crons": ["*/5 * * * *"] }
}
Plus your D1 binding as EmDash’s Cloudflare setup describes, and EMDASH_ENCRYPTION_KEY as a secret (npx emdash secrets generate makes one). Run the EmDash migrations before the first request on a fresh D1. Deploy to Cloudflare Workers explains why and how.
Next steps
- Deploy to Cloudflare Workers covers bindings, the site URL and the first deploy.
- Set Up Your Store walks through gateways, webhooks, your first product and a test purchase.