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
5 changes: 5 additions & 0 deletions .changeset/multi-backend-caplet-files.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@caplets/core": minor
---

Add multi-backend Markdown Caplet files that expand plural backend maps into parent-scoped runtime child handles.
5 changes: 5 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,8 @@ jobs:
push: true
tags: ${{ steps.docker-meta.outputs.tags }}
labels: ${{ steps.docker-meta.outputs.labels }}
build-args: |
CAPLETS_POSTHOG_TOKEN=${{ secrets.CAPLETS_POSTHOG_TOKEN }}
CAPLETS_RUNTIME_SENTRY_DSN=${{ secrets.CAPLETS_RUNTIME_SENTRY_DSN }}
CAPLETS_SENTRY_RELEASE=caplets-runtime@${{ github.sha }}
CAPLETS_SENTRY_ENVIRONMENT=production
6 changes: 6 additions & 0 deletions CONCEPTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ 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.

### Multi-Backend Caplet File

A Markdown Caplet file that describes one provider-scale capability while declaring multiple child backend entries in frontmatter.

Multi-Backend Caplet Files are for suites such as Google Workspace where one catalog card, install unit, setup flow, auth story, and operating guide should expand into several stable runtime child Caplets. They compile into the existing backend maps rather than introducing a new runtime backend kind.

### 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.
Expand Down
30 changes: 19 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,50 +1,58 @@
# syntax=docker/dockerfile:1.7

ARG NODE_VERSION=24-bookworm-slim
ARG PNPM_VERSION=11.0.9
ARG PNPM_VERSION=11.9.0

FROM node:${NODE_VERSION} AS build
ARG PNPM_VERSION
ARG CAPLETS_POSTHOG_TOKEN
ARG CAPLETS_RUNTIME_SENTRY_DSN
WORKDIR /app

RUN corepack enable && corepack prepare pnpm@${PNPM_VERSION} --activate

COPY package.json pnpm-lock.yaml pnpm-workspace.yaml turbo.json ./
COPY apps/catalog/package.json apps/catalog/package.json
COPY apps/docs/package.json apps/docs/package.json
COPY apps/landing/package.json apps/landing/package.json
COPY packages/core/package.json packages/core/package.json
COPY packages/cli/package.json packages/cli/package.json
COPY packages/opencode/package.json packages/opencode/package.json
COPY packages/pi/package.json packages/pi/package.json
COPY packages/benchmarks/package.json packages/benchmarks/package.json
COPY packages/web-observability/package.json packages/web-observability/package.json

RUN pnpm install --frozen-lockfile

COPY . .

RUN pnpm build && CI=true pnpm prune --prod --ignore-scripts
RUN node -e "const fs=require('node:fs'); fs.writeFileSync('packages/core/src/telemetry/intake.generated.ts', ['// Generated by Dockerfile build args during image builds.', 'export const BUNDLED_POSTHOG_TOKEN = '+JSON.stringify(process.env.CAPLETS_POSTHOG_TOKEN || undefined)+' as string | undefined;', 'export const BUNDLED_SENTRY_DSN = '+JSON.stringify(process.env.CAPLETS_RUNTIME_SENTRY_DSN || undefined)+' as string | undefined;', ''].join('\\n'))"

RUN pnpm build && pnpm --filter caplets deploy --prod --legacy /deploy

FROM node:${NODE_VERSION} AS runtime
ARG CAPLETS_SENTRY_RELEASE
ARG CAPLETS_SENTRY_ENVIRONMENT=production
ENV NODE_ENV=production \
XDG_CONFIG_HOME=/data/config \
XDG_STATE_HOME=/data/state \
CAPLETS_SERVER_URL=http://127.0.0.1:5387
CAPLETS_SERVER_URL=http://127.0.0.1:5387 \
CAPLETS_REMOTE_SERVER_STATE_DIR=/data/state/caplets/remote-server \
CAPLETS_SENTRY_RELEASE=${CAPLETS_SENTRY_RELEASE} \
CAPLETS_SENTRY_ENVIRONMENT=${CAPLETS_SENTRY_ENVIRONMENT}
WORKDIR /app

RUN mkdir -p /data/config /data/state && \
chown -R node:root /app /data

COPY --from=build --chown=node:root /app/package.json /app/pnpm-workspace.yaml ./
COPY --from=build --chown=node:root /app/node_modules ./node_modules
COPY --from=build --chown=node:root /app/packages/core/package.json ./packages/core/package.json
COPY --from=build --chown=node:root /app/packages/core/dist ./packages/core/dist
COPY --from=build --chown=node:root /app/packages/cli/package.json ./packages/cli/package.json
COPY --from=build --chown=node:root /app/packages/cli/dist ./packages/cli/dist
COPY --from=build --chown=node:root /deploy ./

VOLUME ["/data"]
EXPOSE 5387

USER node

HEALTHCHECK --interval=30s --timeout=5s --retries=5 --start-period=10s \
CMD node -e "fetch('http://127.0.0.1:5387/healthz').then((response) => process.exit(response.ok ? 0 : 1)).catch(() => process.exit(1))"
CMD node -e "fetch('http://127.0.0.1:5387/v1/healthz').then((response) => process.exit(response.ok ? 0 : 1)).catch(() => process.exit(1))"

CMD ["sh", "-c", "test -f /data/config/caplets/config.json || CAPLETS_MODE=local node packages/cli/dist/index.js init && exec env CAPLETS_MODE=local node packages/cli/dist/index.js serve --transport http --host 0.0.0.0"]
CMD ["sh", "-c", "test -f /data/config/caplets/config.json || CAPLETS_MODE=local node dist/index.js init --global && exec env CAPLETS_MODE=local node dist/index.js serve --transport http --host 0.0.0.0"]
2 changes: 1 addition & 1 deletion apps/catalog/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,5 @@
"vitest": "^4.1.9",
"wrangler": "^4.105.0"
},
"packageManager": "pnpm@11.7.0"
"packageManager": "pnpm@11.9.0"
}
Loading