{"id":13397503,"url":"https://github.com/confetti-clj/confetti","last_synced_at":"2026-03-06T16:03:07.884Z","repository":{"id":62435346,"uuid":"43605556","full_name":"confetti-clj/confetti","owner":"confetti-clj","description":"🎉  A tool to help creating and deploying static sites with AWS","archived":false,"fork":false,"pushed_at":"2018-01-24T18:31:26.000Z","size":142,"stargazers_count":102,"open_issues_count":10,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-10-21T21:32:05.486Z","etag":null,"topics":["boot","clojure","cloudfront","deployment","s3","static-site"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/confetti-clj.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":"2015-10-03T16:26:50.000Z","updated_at":"2025-08-19T03:23:50.000Z","dependencies_parsed_at":"2022-11-01T20:45:47.373Z","dependency_job_id":null,"html_url":"https://github.com/confetti-clj/confetti","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/confetti-clj/confetti","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confetti-clj%2Fconfetti","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confetti-clj%2Fconfetti/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confetti-clj%2Fconfetti/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confetti-clj%2Fconfetti/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/confetti-clj","download_url":"https://codeload.github.com/confetti-clj/confetti/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/confetti-clj%2Fconfetti/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30184884,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T14:42:24.748Z","status":"ssl_error","status_checked_at":"2026-03-06T14:42:14.925Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: 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":["boot","clojure","cloudfront","deployment","s3","static-site"],"created_at":"2024-07-30T18:01:27.396Z","updated_at":"2026-03-06T16:03:07.866Z","avatar_url":"https://github.com/confetti-clj.png","language":"Clojure","funding_links":[],"categories":["Clojure"],"sub_categories":[],"readme":"![confetti-logo-small](https://cloud.githubusercontent.com/assets/97496/11431670/0ef1bb58-949d-11e5-83f7-d07cf1dd89c7.png)\n\n[usage](#usage) | [security](#security) | [change log](#changes) | [appendix](#appendix)\n\n**(alpha)** A tool to help authoring static sites with Amazon Web Services (AWS).\n\n**Rationale**: Static sites are fun. Deploying to S3 is pure\n  joy. CloudFront makes scaling something you don't think about\n  anymore. No servers to administrate; no tears to cry.\n  Setting it all up however is not as straightforward. Confetti is an attempt\n  at encoding best practices into a repeatable program using [CloudFormation][cf]\n  and providing handy tools for basic as well as advanced deployment scenarios.\n\n[](dependency)\n```clojure\n[confetti/confetti \"0.2.1\"] ;; latest release\n```\n[](/dependency)\n\n## Who is this for?\n\n- People that want static sites on custom domains with free SSL and minimal hassle.\n- People that want to host static sites under root domains (e.g. example.com).\n- People that want to setup new static sites often without much manual work (takes 15min of mostly waiting w/ Confetti).\n- People that want to effortlessly have multiple static sites under one domain (e.g. demo.example.com and example.com)\n- People that want excellent distribution accross the globe using a leading CDN.\n- People that want to be able to delete all resources related to a site with a single click.\n\n## Features\n\n- Create all AWS resources required for ideal deployment of static sites\n  - S3 Bucket, Bucket Policy, Cloudfront Distribution\n- All resources are created via a CloudFormation template, allowing\n  - easy deletion if something went wrong\n  - abort upon conflicting configration\n- Provide a separate user \u0026 access key that can only push to the bucket\n- Setup DNS via Route 53 *(optional)*\n- Follow [AWS best practices for deploying static sites][aws-website-hosting].\n- Efficient synchronization of files to S3.\n\n## Usage\n\n[creating a site](#creating-a-site) | [syncing your site](#syncing-your-site) | [final step: dns](#final-step-dns) | [adding subdomains](#adding-subdomains)\n\n\u003e Confetti is packaged up as a [boot][boot] task. This is mainly because\n\u003e boot makes it easy to write commandline apps in Clojure without needing\n\u003e to worry about bootstrapping or dependency resolution.\n\nConfetti provides two commands, in Boot-lingo called *tasks*. The `create-site` task\nwill create a [CloudFormation][cf] stack with all resources for your static website\nand save all important information to an [EDN](edn) file in the current directory.\n\nLet's go through an example of creating a site and syncing it for the first time.\n\n### Creating a site\n\n\u003e 💡 Confused about access keys? Check out the [Security](#security) section of this README.\n\nLet's say you want to deploy a site at `my-app.com`. To create an S3 bucket, a CloudFront\ndistribution and restricted access keys you can run the following:\n\n```\nboot -d confetti create-site --domain \"my-app.com\" --access-key XXX --secret-key YYY\n```\n\u003e Note: the `-d confetti` bit makes sure Boot will download confetti so the `create-site` task will be available.\n\n**Exception!** Because you want to use a naked/APEX domain you have to use Route53\nfor DNS. (You can find more on this in the Appendix.) Try again with DNS enabled:\n\n```\nboot -d confetti create-site --domain \"my-app.com\" --access-key XXX --secret-key YYY --dns\n```\n\nThis should kick of the process. The first feedback should be appearing on your screen.\nAt some point no new events will get printed but the process also hasn't returned yet.\nWhat you're waiting for now is the creation of your CloudFront\ndistribution. This usually takes between 10-15min.\n\n\u003e You may kill the process at this point. Everything is running\n\u003e remotely and won't be interrupted. A `.confetti.edn` file is saved\n\u003e in your current working directory and if using the `fetch-outputs`\n\u003e task with sufficient credentials you can download all useful\n\u003e information at any point in time. (The task will tell you if the\n\u003e stack isn't ready yet as well.)\n\n![Confetti create-site progress](https://cloud.githubusercontent.com/assets/97496/12223984/2dec1b0e-b7e6-11e5-889c-2ea7a4af0fec.png)\n\nAfter the `create-site` task finishes you should find a file in your\ncurrent working directory: `my-app-com.confetti.edn`. It's contents should\ncontain everything important about your newly provisioned resources:\n\n```clojure\n{:stack-id \"arn:aws:cloudformation:us-east-1:297681564547:stack/my-app-com/xxx\",\n :bucket-name \"my-app-com-sitebucket-3fu0w0729ndk\",\n :cloudfront-id \"E3760XUWU2V9R7\",\n :cloudfront-url \"d3up0oy7r2svli.cloudfront.net\",\n :access-key \"AAA\",\n :secret-key \"BBB\",\n :website-url \"http://my-app.com\",\n :hosted-zone-id \"Z3KJWNUJTT8GHO\"}\n```\n\nNow everything is ready for the first deployment!\n\n### Syncing your site\n\nNow the `sync-bucket` task comes into play. While the task provides\nmany different ways to specify what to upload we will just show the\nsimplest here: syncing a local directory. For our demo purposes lets\ncreate a directory quickly:\n\n```\nmkdir my-app-site\necho \"Hello World\" \u003e my-app-site/index.html\necho \"About Us\" \u003e my-app-site/about.html\n```\n\nNow lets sync it. Take the `bucket-name`, `access-key` and\n`secret-key` values from the *.confetti.edn* file:\n\n```\nboot -d confetti sync-bucket --bucket \"my-app-com-sitebucket-3fu0w0729ndk\" \\\n                             --access-key AAA --secret-key BBB --dir my-app-site\n;; or alternatively\nboot -d confetti sync-bucket --confetti-edn your-site.confetti.edn --dir my-app-site\n```\n\nThis will upload `index.html` and `about.html` to your bucket. To\nverify that everything was successful you can navigate to the URL\nstored as `cloudfront-url` in the edn file.\n\n\u003e There are many more ways to specify what files to upload (with\n\u003e custom metadata if wanted) which are not covered by this guide.\n\u003e Consult `boot sync-bucket --help` for details.\n\n### Final Step: DNS\n\nNow the only step missing is properly setting up DNS. What needs to be\ndone here varies depending on whether you enabled the `--dns` option\nor not. In the example above we enabled it so lets cover that case first:\n\n**DNS with Route53:** Because you have a root/naked/apex domain setup\nyou decided to use manged DNS by AWS. Now you need to set the nameservers\nfor the domain you used to AWS' nameservers. These are different for different\nHosted Zones so you need to look them up in the [AWS Console](hosted-zones-admin).\n\n**Without Route53:** When not using Route53 the only thing you have to\ndo is to add a CNAME entry to the Zonefile of your domain that points\nto the Cloudfront distribution.\n\n\u003e Both of these steps will vary from domain registrar to domain\n\u003e registrar so it's recommended to check their individual\n\u003e documentation.\n\n\u003e :lock: Want SSL? [Here's how to enable it](https://github.com/confetti-clj/confetti#add-ssl).\n\n### Adding Subdomains\n\nLet's say you used Confetti to create a site `weloveparens.com` and\nnow want to add a static site to a subdomain of that domain. You can just run:\n\n```\nboot create-site --domain \"shop.weloveparens.com\" --dns --access-key FOO --secret-key BAR\n```\n\nThis will create a Route53 RecordSet in the HostedZone which has\npreviously been created for you when setting up `weloveparens.com`.\nThe S3 bucket, CloudFront distribution and so on will be created as usual.\nAlso as always everything (including the RecordSet) will be created as\na CloudFormation stack so if you no longer need it you can just delete\nthe stack, leaving `weloveparens.com` unaffected.\n\n## Getting Help\n\nTo get help on the command line you can always run:\n\n```\nboot create-site --help\nboot fetch-outputs --help\nboot sync-bucket --help\n```\n\nAlso feel free to open issues to ask questions or suggest improvements.\n\n## Security\n\nGiving your AWS keys to some program and just letting it run with it is kind of frightening so this section is aimed at giving some comfort around that.\n\n- The `create-site` task will create a CloudFormation stack according to a template defined in [confetti-clj/cloudformation](https://github.com/confetti-clj/cloudformation).\n- If you want to see the CloudFormation template before you run anything you can pass the `--dry-run` argument.\n- The credentials you pass to `create-site` must have permissions to create the individual resources listed in the CloudFormation template. (In the future Confetti may provide an AWS IAM policy snippet so you can create a user that has all the rights Confetti needs.)\n- The CloudFormation template will also generate an Access Key + Secret. This keypair is restricted, it can only access the S3 Bucket and invalidate CloudFront caches.\n- The keypair should be sufficient to update your static site and restricted enough that you can share it with others.\n\n#### your-site.confetti.edn :warning: \n\nAs of version `0.2.0` the `create-site` command will create a file\nending in `.confetti.edn` this contains all information needed to\nmaintain your site. **The information in this file contains secrets!**\n\n\u003e Update: I've come to the conclusion that creating this file is a bad idea.\n\u003e People will inevitably commit it and publicise the keys to their S3 bucket.\n\u003e In the future I would like to just print something in a format that is understood\n\u003e by [direnv](https://direnv.net/) and recommend env vars / direnv instead.\n\n## Changes\n\n#### 0.2.1\n\n- Update various dependencies ([0b1a59decb](https://github.com/confetti-clj/confetti/commit/0b1a59decb0eabf50a9709c945d5a7c5a4e55be9))\n\n#### 0.2.0\n\n- Upgrade to `[confetti/cloudformation \"0.1.6\"]`, which brings the following improvements:\n  - Enable compression by default\n  - Fix some misconfiguration of the origin that caused problems when enabling SSL\n\n#### 0.1.5\n\n- bump [`confetti/s3-deploy`](https://github.com/confetti-clj/s3-deploy) to improve Windows compatibility\n\n#### 0.1.5-alpha\n\n- **HostedZone Reuse:** Creating a new HostedZone for each site has two drawbacks:\n  - Each HostedZone costs 50 cent\n  - Each HostedZone has a distinct set of nameservers that you'd need to supply to your domain provider\n\n  By using one HostedZone for your root domain `example.com` these problems are solved and\n  adding a new site at `demo.example.com` is just a matter of adding a RecordSet.\n  **Confetti now tries to find an existing HostedZone and only adds a RecordSet if it finds one.**\n- New `invalidation-paths` option for the `sync-bucket` task. Previously invalidation paths\n  were determined based on the files you uploaded. Now you can provide a custom set. ([#21](https://github.com/confetti-clj/confetti/issues/21) + [#29](https://github.com/confetti-clj/confetti/pull/29))\n- Fix bug with new method of supplying options via a `.confetti.edn` file\n\n#### 0.1.4\n\n- When users supply the `confetti-edn` option, we now accept both versions\n  (ending with `.confetti.edn` and just the part before that). Previously\n  it was expected that you only supply the part before the `.confetti.edn` suffix\n- Adapt Readme to suggest usage of `confetti-edn` option and `fetch-outputs` task\n- Refactor reporting into separate task that is called from `create-site`\n- Give progress-reporting a hard limit of 16min. Previously the error reporting often\n  got stuck preventing the entire process from returning. This should not happen anymore.\n- Provide copy-able command to fetch outputs as part of progress reporting\n- Move APEX domain info into `fetch-outputs` task\n- Upgrade to `[confetti/cloudformation \"0.1.3\"]` to have `:website-url` in stack outputs\n  no matter if Route53 is used or not\n- Print time when starting progress reporting\n- Print Cloudfront URL in `fetch-outputs` if Route53 isn't used\n\n#### 0.1.3\n\n- A `fetch-outputs` task has been added that can be used to download\n  outputs of Cloudformation stacks. Previously the reporting often got stuck\n  and didn't save stack outputs properly.\n  To circumvent this you may now cancel the reporting and call `fetch-outputs`\n  at any later point in time to download the outputs.\n- The `sync-bucket` task now provides a `confetti-edn` option that can be used\n  to supply the some-id part of a `{some-id}.confetti.edn`. The information\n  in that file will then be used for instead of the regular task options.\n- General improvements around error handling and option validation.\n\n## Appendix\n\n#### Additional Tweaks\n\n##### Add SSL:\n\n1. Get an SSL Cert using AWS Certificate Manager (ACM)\n1. Configure Cloudfront Distribution to use newly issued certificate (i.e. \"Custom SSL certificate\")\n1. Switch **Behavior** Viewer Protocol Policy to \"Redirect HTTP to HTTPS\"\n\n👉 If anything is not working as expected, please open an issue. 👈\n\n\u003e **Note** If you end up getting 504 errors when requesting assets\n\u003e from your Cloudfront distribution double check you're really using\n\u003e the website endpoint as origin. The Origin Protocol policy **must\n\u003e be** \"HTTP Only\" as a result of using the website endpoint.\n\n##### Enable Gzipping\n\n- **v0.1.6 and up now take care of this automatically**\n- Edit **Behavior**, set \"Compress Objects Automatically\" to \"Yes\"\n\n#### A Note On APEX Domains\n\nCloudfront supports APEX domains but only if you use Route53's `ALIAS`\nrecords. More information can be found in the\n[official announcement][apex-support].\n\nThis limitation makes it harder to automate root (APEX) domain setups\nthus it's currently not supported to create sites for root domains\nwithout also managing DNS with Route53.\n\n[boot]: https://github.com/boot-clj/boot\n[lets-encrypt]: https://letsencrypt.org/\n[edn]: https://github.com/edn-format/edn\n[cf]: https://aws.amazon.com/cloudformation/\n[apex-support]: https://aws.amazon.com/de/about-aws/whats-new/2013/06/11/announcing-custom-ssl-certificates-and-zone-apex-support-for-cloudfront/\n[hosted-zones-admin]: https://console.aws.amazon.com/route53/home?region=us-east-1#hosted-zones\n[aws-website-hosting]: http://docs.aws.amazon.com/gettingstarted/latest/swh/website-hosting-intro.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconfetti-clj%2Fconfetti","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconfetti-clj%2Fconfetti","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconfetti-clj%2Fconfetti/lists"}