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
100 changes: 100 additions & 0 deletions .claude/skills/codap-resources/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
---
name: codap-resources
description: Use when deploying, updating, or syncing assets to the codap-resources S3 bucket - plugins, example documents, boundary files, banners, or notification configs
---

# codap-resources

Manage assets in the `s3://codap-resources/` S3 bucket using the AWS CLI.

The bucket is served via CloudFront at `codap-resources.concord.org`.

## When Invoked

Display this to the user:

> **codap-resources** — Deploy and manage assets in the `codap-resources` S3 bucket
> (served at `codap-resources.concord.org`).
>
> This skill helps with copying files, syncing plugin builds, and invalidating
> the CloudFront cache for the CODAP resource bucket.
>
> **Requirements:**
> - AWS CLI installed (`aws --version`)
> - Authenticated with credentials that have write access to the `codap-resources` bucket
> and permission to create CloudFront invalidations
>
> **What do you want to do?**

Then ask the user what they want to do, or proceed with the task if it was already specified.

## Bucket Structure

| Folder | Contents | ACL | Cache |
|--------|----------|-----|-------|
| `notifications/` | Banners, announcements (JSON) | `public-read` | `no-cache, no-store, must-revalidate` |
| `boundaries/` | GeoJSON boundary documents (US states, counties, etc.) | `public-read` | default |
| `example-documents/` | CODAP example documents | `public-read` | default |
| `plugins/` | Built CODAP plugins (folders) | `public-read` | default |

## Common Commands

### Copy a single file

```bash
aws s3 cp <local-file> s3://codap-resources/<folder>/<filename> --acl public-read
```

For `notifications/` assets, always add no-cache:

```bash
aws s3 cp <local-file> s3://codap-resources/notifications/<filename> \
--acl public-read \
--cache-control "no-cache, no-store, must-revalidate"
```

### Sync a folder (plugins, examples, etc.)

**Always dry-run first** so the user can review what will change before anything is uploaded:

```bash
# 1. Dry run — show what would change
aws s3 sync <local-folder> s3://codap-resources/<folder>/<name>/ \
--acl public-read --dryrun

# 2. After user confirms, run for real
aws s3 sync <local-folder> s3://codap-resources/<folder>/<name>/ \
--acl public-read
```

Add `--delete` to remove S3 files that no longer exist locally. Omit it to preserve old files.

### CloudFront Invalidation

After updating cached assets (plugins, documents, boundaries), invalidate the CloudFront cache so changes are served immediately. Not needed for `notifications/` since those use no-cache headers.

```bash
aws cloudfront create-invalidation --distribution-id E1RS9TZVZBEEEC \
--paths "/<folder>/*"
```

### List contents of a folder

```bash
aws s3 ls s3://codap-resources/<folder>/
```

## When to Use No-Cache

Use `--cache-control "no-cache, no-store, must-revalidate"` for any asset that:
- May be updated frequently
- Must take effect immediately after changes (e.g., banners, feature flags, notifications)

Static assets (plugins, documents, boundaries) can use default caching.

## Related Repositories

Assets are typically built from sibling repos in the `codap-build` directory:
- `cloud-file-manager` - banner configs, file storage integration
- `codap-data-interactives` - plugin builds
- `codap-data` - example documents and boundary files
1 change: 1 addition & 0 deletions apps/dg/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,7 @@ DG.main = function main() {
{ name: 'DG.fileMenu.menuItem.renameDocument'.loc(), action: 'renameDialog' }
],
},
banner: 'https://codap-resources.concord.org/notifications/announcing-v3-banner.json',
appSetsWindowTitle: true, // CODAP takes responsibility for the window title
wrapFileContent: false,
mimeType: 'application/json',
Expand Down
2 changes: 1 addition & 1 deletion apps/dg/resources/cloud-file-manager/css/app.css

Large diffs are not rendered by default.

28 changes: 14 additions & 14 deletions apps/dg/resources/cloud-file-manager/js/app.js.ignore

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions cfm-version.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
version: 1.9.3
commit: 3b3230675badb43e79e282f98a31ca3741be9fad
version: 1.9.4
commit: ceb79b94dc392e8b5499b60f075d24d1edcf81ac
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
"build:bundle-prod:comment": "echo Usage: `npm run build:bundle-prod` builds a production version of the `codap-lib-bundle.js`",
"build:bundle-prod": "NODE_OPTIONS=--openssl-legacy-provider NODE_ENV=production webpack --progress",
"build:cfm:comment": "echo Usage: `npm run build:cfm` builds CFM for CODAP. Assumes that CFM repository named 'cloud-file-manager' and CODAP repository named 'codap' are siblings.",
"build:cfm": "cd ../cloud-file-manager && npm run build:codap && cd ../codap && ./bin/recordCFMVersion",
"build:cfm": "cd ../cloud-file-manager && NODE_OPTIONS=--openssl-legacy-provider npm run build:codap && cd ../codap && ./bin/recordCFMVersion",
"build:dev:comment": "echo Usage: `npm run build:dev` performs a local development build",
"build:dev": "npm run build:bundle-dev && npm run build:local",
"build:embedded:comment": "echo Usage: `npm run build:embedded` builds a CODAP embedded mode package named embeddedCODAP",
Expand Down
Loading