{"id":23019855,"url":"https://github.com/tneely/jelly","last_synced_at":"2026-04-15T16:32:19.444Z","repository":{"id":40285898,"uuid":"264291709","full_name":"tneely/jelly","owner":"tneely","description":"A Jamstack in CDK","archived":false,"fork":false,"pushed_at":"2023-01-08T02:00:07.000Z","size":2872,"stargazers_count":1,"open_issues_count":8,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-22T05:49:55.575Z","etag":null,"topics":["aws-cdk","cdk","cdk-constructs","jamstack","jelly"],"latest_commit_sha":null,"homepage":"https://cdk-jelly.com/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tneely.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-05-15T20:26:06.000Z","updated_at":"2022-12-23T07:44:36.000Z","dependencies_parsed_at":"2023-02-08T04:16:18.809Z","dependency_job_id":null,"html_url":"https://github.com/tneely/jelly","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/tneely/jelly","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tneely%2Fjelly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tneely%2Fjelly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tneely%2Fjelly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tneely%2Fjelly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tneely","download_url":"https://codeload.github.com/tneely/jelly/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tneely%2Fjelly/sbom","scorecard":{"id":890387,"data":{"date":"2025-08-11","repo":{"name":"github.com/tneely/jelly","commit":"ea21b9bf4f477fc1cda055771f5da96389f9b1a9"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.2,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/build.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:37: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:52: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:75: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/stale.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/stale.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/upgrade-release.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/upgrade-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/upgrade-release.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/upgrade-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/upgrade-release.yml:54: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/upgrade-release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/upgrade-release.yml:62: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/upgrade-release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/upgrade-release.yml:71: update your workflow using https://app.stepsecurity.io/secureworkflow/tneely/jelly/upgrade-release.yml/master?enable=pin","Info:   0 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Token-Permissions","score":8,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'checks' permission set to 'write': .github/workflows/build.yml:11","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/build.yml:12","Warn: jobLevel 'actions' permission set to 'write': .github/workflows/build.yml:13","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:13","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release.yml:48","Info: jobLevel 'contents' permission set to 'read': .github/workflows/release.yml:71","Warn: jobLevel 'contents' permission set to 'write': .github/workflows/upgrade-release.yml:49","Warn: jobLevel 'checks' permission set to 'write': .github/workflows/upgrade-release.yml:51","Info: jobLevel 'contents' permission set to 'read': .github/workflows/upgrade-release.yml:13","Warn: no topLevel permission defined: .github/workflows/build.yml:1","Warn: no topLevel permission defined: .github/workflows/release.yml:1","Warn: no topLevel permission defined: .github/workflows/stale.yml:1","Warn: no topLevel permission defined: .github/workflows/upgrade-release.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":0,"reason":"dangerous workflow patterns detected","details":["Warn: script injection with untrusted input ' github.event.pull_request.head.ref ': .github/workflows/build.yml:35"],"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"27 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-crh6-fp67-6883","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-pfrx-2q88-qq97","Warn: Project is vulnerable to: GHSA-rc47-6667-2j5j","Warn: Project is vulnerable to: GHSA-78xj-cgh5-2h22","Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-82v2-mx6x-wq7q","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-4rq4-32rv-6wp6","Warn: Project is vulnerable to: GHSA-64g7-mvw6-v9qj","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-24T11:35:34.819Z","repository_id":40285898,"created_at":"2025-08-24T11:35:34.820Z","updated_at":"2025-08-24T11:35:34.820Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31849737,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-15T15:24:51.572Z","status":"ssl_error","status_checked_at":"2026-04-15T15:24:39.138Z","response_time":63,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aws-cdk","cdk","cdk-constructs","jamstack","jelly"],"created_at":"2024-12-15T12:11:45.620Z","updated_at":"2026-04-15T16:32:19.424Z","avatar_url":"https://github.com/tneely.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"```\n       _      _ _\n      | |    | | |\n      | | ___| | |_   _\n  _   | |/ _ \\ | | | | |\n | |__| |  __/ | | |_| |\n  \\____/ \\___|_|_|\\__, |\n                   __/ |\n                  |___/\n```\n\nJelly is a high level CDK construct that defines everything you'll need to deploy a JAMstack application.\n\n## Usage\n\n### Install\n\n```\nnpm install cdk-jelly\n```\n\n### Declaration\n\n```typescript\nnew Jelly(this, {\n  api: {\n    code: lambda.Code.fromAsset(dirname(require.resolve(\"example-api\"))),\n  },\n  client: {\n    source: s3deploy.Source.asset(dirname(require.resolve(\"example-app\"))),\n  },\n});\n```\n\n### Client\n\n```typescript\nnew Jelly(this, {\n  client: {\n    source: s3deploy.Source.asset(dirname(require.resolve(\"example-app\"))),\n  },\n  httpHeaders: {\n    // optional, these are default\n    contentSecurityPolicy: \"default-src 'self'\", // highly recommend changing this default\n    strictTransportSecurity: \"max-age=63072000; includeSubDomains; preload\",\n    xContentTypeOptions: \"nosniff\",\n    xXssProtection: \"1; mode=block\",\n    xFrameOptions: \"DENY\",\n    referrerPolicy: \"strict-origin-when-cross-origin\",\n    featurePolicy: \"microphone 'self'; geolocation 'self'; camera 'self'\",\n    accessControlAllowOrigin: \"*\",\n  },\n  isSPA: true, // optional, this is default\n  // ...\n});\n```\n\nJelly hosts your client in S3 and distributes it globally using CloudFront. It uses secure HTTP headers by default via Lambda@Edge. Though you need want to relax some of them - especially the CSP.\n\nIf you are not creating a single page app, set `isSPA` to `false` in order to not reroute 404s back to your index.html page.\n\n### API\n\n```typescript\nconst jelly = new Jelly(this, {...});\nconst apiTable = jelly.api.newTable(\"MyApiTable\", {...});\nconst apiDataSource = api.addDynamoDbDataSource(\"apiDataSource\", apiTable);\n```\n\nJelly uses AppSync for its GraphQL API. Use the `Api` construct exposed by Jelly to build out your AppSync schema and resolvers.\n\n### Authentication\n\n```typescript\nnew Jelly(this, {\n  // ...\n  withUserAuthentication: true, // optional, this is default\n});\n```\n\nJelly uses Cognito for user authentication, creating both a user pool and user pool client. You will need to make use of both of these resource IDs in order to authenticate users using tools like Amplify.\n\nWe provide an authentication handler that is available to your API through the `AUTH_LAMBDA_ARN` environment variable. You can pass this lambda the Cognito authentication token to verify whether it is valid.\n\n```typescript\nconst verifyCognitoJwt = async (token: string) =\u003e {\n  const response = await lambdaClient\n    .invoke({\n      FunctionName: process.env.AUTH_LAMBDA_ARN!,\n      Qualifier: \"Prod\",\n      Payload: JSON.stringify({ token }),\n    })\n    .promise();\n\n  const payload: VerificationResponse = JSON.parse(response.Payload as string);\n  if (!payload.authenticated) {\n    throw new Error(`Could not authenticate user: ${payload.errorMessage}`);\n  }\n};\n```\n\n### Database\n\n```typescript\nnew Jelly(this, {\n  // ...\n  database: {\n    tables: {\n      DATABASE_NAME: {\n        partitionKey: {\n          name: \"id\",\n          type: AttributeType.STRING,\n        },\n        sortKey: {\n          name: \"created\",\n          type: AttributeType.NUMBER,\n        },\n        timeToLiveAttribute: \"ttl\",\n      },\n    },\n  },\n});\n```\n\nJelly will spin up and make available to your API any number of DynamoDB tables. We directly make use of CDK's `dynamodb.TableProps` interface to define the tables. The keys set in `tables` above are used as environment variables in your API lambda in order to expose the table names.\n\n### Routing\n\n```typescript\nnew Jelly(this, {\n  // ...\n  routing: {\n    baseDomainName: \"cdk-jelly.com\",\n    apiSubdomain: \"api\", // optional, this is default\n    authSubdomain: \"auth\", // optional, this is default\n  },\n});\n```\n\nIf using a custom domain name, Jelly uses Route 53 to act as a DNS for your application.\nJelly also leverages AWS Certificate Manager and CloudFormation's DNS validation to provide HTTPS across your domain and subdomains.\n\nWhen deploying a Jelly application for the first time, you will need to register the name servers in your root domain's hosted zone with your domain provider. The stack deployment will hang until the certificates can be verified through DNS.\n\nThe base domain name (e.g. cdk-jelly.com) will be set up to redirect to the www subdomain, which serves your app through CloudFront. Jelly will create also subdomains for your API (e.g. api.cdk-jelly.com) and authentication (e.g. auth.cdk-jelly.com) endpoints.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftneely%2Fjelly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftneely%2Fjelly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftneely%2Fjelly/lists"}