Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions .caplets.lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"version": 1,
"entries": [
{
"id": "github",
"destination": "github",
"kind": "directory",
"source": {
"type": "local",
"path": "/tmp/caplets-cli-remote-install-explicit-project-0UFEXG/project/.caplets/repo/caplets/github",
"portability": "non_portable"
},
"installedHash": "sha256:73c123669a3f22f683156dc2746d8b21442078be5e7463686506ae9057381cd6",
"installedAt": "2026-06-26T19:27:24.767Z",
"updatedAt": "2026-06-26T19:27:24.809Z",
"risk": {
"backendFamilies": ["mcp"],
"safety": "local_control",
"projectBindingRequired": false,
"mutating": false,
"destructive": false,
"bodyHash": "sha256:73c123669a3f22f683156dc2746d8b21442078be5e7463686506ae9057381cd6"
}
}
]
}
5 changes: 5 additions & 0 deletions .changeset/bright-icons-wave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@caplets/core": minor
---

Add optional `catalog.icon` metadata to Caplet files and catalog entries so catalog surfaces can show provider icons.
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["@caplets/landing", "@caplets/docs"]
"ignore": ["@caplets/landing", "@caplets/docs", "@caplets/catalog"]
}
7 changes: 7 additions & 0 deletions .changeset/fuzzy-catalogs-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@caplets/core": minor
"caplets": minor
---

Add shared catalog primitives, official catalog generation, public catalog indexing statuses,
and install-time Vault setup recovery metadata for Caplets install/update flows.
6 changes: 0 additions & 6 deletions .changeset/prebuilt-caplets-lockfile-update.md

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ jobs:
- name: Run quality gates
run: pnpm verify

- name: Deploy landing page
- name: Deploy sites
run: pnpm run alchemy:deploy
env:
ALCHEMY_STAGE: prod
Expand Down
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,9 @@ benchmark-results/

# brag
brag-output/

# wrangler
.wrangler/

# Test-generated Caplets Lockfiles
.caplets.lock.json
2 changes: 1 addition & 1 deletion .oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"$schema": "./node_modules/oxfmt/configuration_schema.json",
"ignorePatterns": ["**/.brv/**"],
"ignorePatterns": ["**/.brv/**", "apps/catalog/src/data/official-catalog.json"],
"plugins": ["prettier-plugin-astro"],
"overrides": [
{
Expand Down
18 changes: 18 additions & 0 deletions CONCEPTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,30 @@ The Prebuilt Caplets Catalog is curated as a Code Mode-first capability catalog,

Install-ready catalog entries have an explicit verification status, a reproducible validation path, and a named primary Code Mode workflow. Unverified entries may exist as drafts or recipes, but they do not count as install-ready catalog coverage.

### Catalog Search Site

The public search surface for installable Caplets at `catalog.caplets.dev`.

The Catalog Search Site is separate from the landing page and docs site. It indexes official Caplets from this repo and community Caplets discovered through public external installs, with search, readable Caplet content, source labels, install-count popularity signals, warnings, and inspection-first copyable install commands as the primary user flow.

### Public Catalog Indexing Signal

The public-source install signal that lets `catalog.caplets.dev` discover and rank community Caplets.

Public Catalog Indexing is not ordinary anonymous telemetry. It may publish public Caplet content, normalized install command, source identity needed to reproduce install, and aggregate install count; it must not publish installer identity, private source URLs, local paths, config, credentials, prompts, tool arguments, tool outputs, or hostnames. Catalog install counts are popularity and ranking signals, not safety signals, and public entries can be suppressed when automatic indexing creates stale, abusive, leaked, or high-risk catalog records.

### Catalog-Grade Caplet

A Caplet that is ready to live in the Prebuilt Caplets Catalog.

Catalog-Grade Caplets include enough frontmatter, setup or verification guidance, auth handling, least-privilege scope notes, safety notes, Code Mode workflow guidance, and local/project/runtime metadata for agents to use them without rediscovering private assumptions from the author's environment.

### Catalog Presentation Metadata

Optional Caplet frontmatter that improves how a Caplet appears in public catalog surfaces without changing runtime behavior, trust, safety status, ranking, or install readiness.

In v1, Catalog Presentation Metadata is limited to `catalog.icon`, which may identify a safe HTTPS icon URL or a bundled icon path relative to the Caplet directory.

### Caplets Lockfile

A `caplets.lock.json` file that records installed catalog Caplets, their source repository, source path, destination, tracked source channel, resolved revision when available, content hash, and portability status.
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
<a href="https://caplets.dev"><strong>caplets.dev</strong></a>
·
<a href="https://docs.caplets.dev"><strong>docs.caplets.dev</strong></a>
·
<a href="https://catalog.caplets.dev"><strong>catalog.caplets.dev</strong></a>
</p>
</div>

Expand Down
39 changes: 32 additions & 7 deletions alchemy.run.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import alchemy from "alchemy";
import { Astro } from "alchemy/cloudflare";
import { Astro, D1Database } from "alchemy/cloudflare";
import { GitHubComment } from "alchemy/github";
import { CloudflareStateStore } from "alchemy/state";

Expand All @@ -10,28 +10,52 @@ const app = await alchemy("caplets", {
password: process.env.ALCHEMY_PASSWORD!,
});

const { docsPageDomain, docsPageUrl, landingPageDomain, landingPageUrl } = buildAlchemyDomains(
app.stage,
{ local: app.local },
);
const {
catalogPageDomain,
catalogPageUrl,
docsPageDomain,
docsPageUrl,
landingPageDomain,
landingPageUrl,
} = buildAlchemyDomains(app.stage, { local: app.local });
const hostSuffix = process.env.SSH_CONNECTION ? " --host 0.0.0.0" : "";
export const landingPage = await Astro("landing-page", {
cwd: "apps/landing",
dev: {
command: "pnpm run dev" + (process.env.SSH_CONNECTION ? " --host 0.0.0.0" : ""),
command: "pnpm run dev --port 4321" + hostSuffix,
},
domains: [landingPageDomain, `www.${landingPageDomain}`],
});
export const docsPage = await Astro("docs-page", {
cwd: "apps/docs",
dev: {
command: "pnpm run dev -- --port 4322" + (process.env.SSH_CONNECTION ? " --host 0.0.0.0" : ""),
command: "pnpm run dev --port 4322" + hostSuffix,
},
domains: [docsPageDomain],
});
export const catalogDatabase = await D1Database("catalog-database", {
name: `caplets-${app.stage}-catalog`,
migrationsDir: "apps/catalog/migrations",
adopt: true,
delete: false,
});
export const catalogPage = await Astro("catalog-page", {
cwd: "apps/catalog",
entrypoint: "dist/server/entry.mjs",
assets: "dist/client",
dev: {
command: "pnpm run dev --port 4323" + hostSuffix,
},
bindings: {
CATALOG_DB: catalogDatabase,
},
domains: [catalogPageDomain],
});

console.log({
"Landing Page URL": landingPageUrl,
"Docs Page URL": docsPageUrl,
"Catalog Page URL": catalogPageUrl,
});

const [repositoryOwnerFromSlug, repositoryNameFromSlug] =
Expand All @@ -55,6 +79,7 @@ if (pullRequestNumber) {

Landing: ${landingPageUrl}
Docs: ${docsPageUrl}
Catalog: ${catalogPageUrl}

Built from commit ${shortSha}`,
});
Expand Down
50 changes: 50 additions & 0 deletions apps/catalog/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// @ts-check
import cloudflare from "@astrojs/cloudflare";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "astro/config";
import { fileURLToPath } from "node:url";

const cloudflareDevMiddleware = fileURLToPath(
new URL("./src/cloudflare-dev-middleware.ts", import.meta.url),
);
const cloudflareDevWorkers = fileURLToPath(
new URL("./src/cloudflare-workers-dev.ts", import.meta.url),
);
const isProductionBuild = process.env.NODE_ENV === "production";
const optimizeExclude = [
"tailwind-variants",
"unified",
"remark-parse",
"remark-rehype",
"rehype-sanitize",
"rehype-stringify",
];

export default defineConfig({
site: "https://catalog.caplets.dev",
output: "server",
adapter: cloudflare(),
devToolbar: {
enabled: false,
},
vite: {
build: {
assetsInlineLimit: 0,
},
plugins: [tailwindcss()],
resolve: {
alias: {
"@astrojs/cloudflare/entrypoints/middleware.js": cloudflareDevMiddleware,
...(isProductionBuild ? {} : { "cloudflare:workers": cloudflareDevWorkers }),
},
},
ssr: {
optimizeDeps: {
exclude: optimizeExclude,
},
},
optimizeDeps: {
exclude: optimizeExclude,
},
},
});
38 changes: 38 additions & 0 deletions apps/catalog/migrations/0001_catalog.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
create table if not exists catalog_counts (
entry_key text primary key,
install_count integer not null default 0,
updated_at_ms integer not null
);

create table if not exists catalog_entries (
entry_key text primary key,
provider text not null,
repository text not null,
source_path text not null,
caplet_id text not null,
resolved_revision text,
content_hash text,
entry_json text not null,
updated_at_ms integer not null
);

create table if not exists catalog_signal_dedupe (
entry_key text not null,
signal_fingerprint text not null,
provider text not null,
repository text not null,
window_start_ms integer not null,
accepted_at_ms integer not null,
primary key (entry_key, signal_fingerprint, window_start_ms)
);

create table if not exists catalog_suppressions (
entry_key text primary key,
reason text not null,
suppressed_at text not null
);

create index if not exists catalog_counts_rank_idx on catalog_counts (install_count desc);
create index if not exists catalog_entries_repository_idx on catalog_entries (provider, repository);
create index if not exists catalog_signal_dedupe_entry_time_idx on catalog_signal_dedupe (entry_key, accepted_at_ms);
create index if not exists catalog_signal_dedupe_repository_window_idx on catalog_signal_dedupe (provider, repository, window_start_ms);
41 changes: 41 additions & 0 deletions apps/catalog/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "@caplets/catalog",
"version": "0.1.0",
"private": true,
"type": "module",
"scripts": {
"astro": "astro",
"build": "astro build",
"dev": "astro dev",
"preview": "astro preview",
"test": "vitest run test",
"typecheck": "astro check"
},
"dependencies": {
"@astrojs/check": "^0.9.9",
"@astrojs/cloudflare": "^13.7.0",
"@caplets/core": "workspace:*",
"@hugeicons/core-free-icons": "^4.2.2",
"@tabler/icons": "^3.44.0",
"@tailwindcss/forms": "^0.5.11",
"@tailwindcss/vite": "^4.3.1",
"@tanstack/virtual-core": "^3.17.2",
"astro": "^6.4.6",
"rehype-sanitize": "^6.0.0",
"rehype-stringify": "^10.0.1",
"remark-parse": "^11.0.0",
"remark-rehype": "^11.1.2",
"tailwind-variants": "^3.2.2",
"tailwindcss": "^4.3.1",
"tw-animate-css": "^1.4.0",
"typescript": "^6.0.3",
"unified": "^11.0.5"
},
"devDependencies": {
"happy-dom": "^20.10.6",
"vite": "^7.3.5",
"vitest": "^4.1.8",
"wrangler": "^4.105.0"
},
"packageManager": "pnpm@11.7.0"
}
Binary file added apps/catalog/public/icon-header-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/catalog/public/icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions apps/catalog/src/cloudflare-dev-middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import type { MiddlewareHandler } from "astro";

export const onRequest: MiddlewareHandler = (_context, next) => next();
1 change: 1 addition & 0 deletions apps/catalog/src/cloudflare-workers-dev.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const env = {};
Loading