No description
  • TypeScript 93.1%
  • CSS 6.9%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Razvan M. 24c8f4aa75 stuff
2026-08-29 10:43:14 +03:00
.alchemy/log stuff 2026-08-29 10:43:14 +03:00
.wrangler stuff 2026-08-29 10:43:14 +03:00
public stuff 2026-08-29 10:43:14 +03:00
server stuff 2026-08-29 10:43:14 +03:00
.gitignore stuff 2026-08-29 10:43:14 +03:00
AGENTS.md stuff 2026-08-29 10:43:14 +03:00
alchemy.run.ts stuff 2026-08-29 10:43:14 +03:00
CLAUDE.md stuff 2026-08-29 10:43:14 +03:00
monitor.config.ts stuff 2026-08-29 10:43:14 +03:00
nitro.config.ts stuff 2026-08-29 10:43:14 +03:00
package.json stuff 2026-08-29 10:43:14 +03:00
pnpm-lock.yaml stuff 2026-08-29 10:43:14 +03:00
pnpm-workspace.yaml stuff 2026-08-29 10:43:14 +03:00
README.md stuff 2026-08-29 10:43:14 +03:00
tsconfig.json stuff 2026-08-29 10:43:14 +03:00

Virgil

Virgil runs as a Nitro v3 application on Cloudflare Workers. Alchemy provisions the Worker and its Cloudflare KV namespace.

How the pieces fit together

Alchemy owns the infrastructure lifecycle:

  1. Cloudflare.KV.Namespace("KV") provisions a KV namespace.
  2. Command.Build runs Nitro's Cloudflare-module build.
  3. Cloudflare.Worker uploads Nitro's prebuilt Worker output.
  4. The Worker receives the namespace as the VIRGIL_KV binding.

Nitro mounts that binding through unstorage:

storage: {
    kv: {
        driver: "cloudflare-kv-binding",
        binding: "VIRGIL_KV",
    },
},

Application code only depends on Nitro's storage API:

import { useStorage } from "nitro/storage";

const kv = useStorage("kv");
await kv.setItem("domains", ["example.com"]);
const domains = await kv.getItem<string[]>("domains");

pnpm dev:nitro uses the filesystem-backed devStorage mount at .data/kv. pnpm dev runs Alchemy's local Cloudflare environment, where the same mount is backed by an emulated KV binding.

Local development

pnpm install
pnpm dev

Use the local Nitro server without Alchemy when Cloudflare emulation is not needed:

pnpm dev:nitro

Plan and deploy

Set the Discord webhook used by the checker task:

export DISCORD_WEBHOOK_URL="https://discord.com/api/webhooks/..."

Alchemy deploys this value as a Cloudflare secret binding. The domain monitor runs every day at 00:00 UTC and keeps each domain in KV after it expires. It stores the RDAP expiry date and sends one-time notifications at 30, 14, 7, 3, and 1 day before expiry, when the domain expires, and when RDAP reports it as available. If a domain is renewed, the notification schedule resets for its new expiry date.

Authenticate with Alchemy when prompted, then inspect the plan before applying it:

pnpm plan
pnpm deploy

Use the project-local Alchemy binary through these scripts or with pnpm exec alchemy. Do not use pnpm dlx alchemy: it downloads a separate version instead of using the version pinned in this project.