{"id":17141644,"url":"https://github.com/martinklepsch/tenzing","last_synced_at":"2025-04-13T00:44:31.468Z","repository":{"id":23959168,"uuid":"27341288","full_name":"martinklepsch/tenzing","owner":"martinklepsch","description":"⚡️ Clojurescript application template using Boot","archived":false,"fork":false,"pushed_at":"2018-05-14T21:59:45.000Z","size":702,"stargazers_count":403,"open_issues_count":15,"forks_count":39,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-04-04T03:11:16.931Z","etag":null,"topics":["clojure","clojurescript","project-template","starter-kit"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/martinklepsch.png","metadata":{"files":{"readme":"README.markdown","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":"2014-11-30T16:02:36.000Z","updated_at":"2024-11-08T23:09:51.000Z","dependencies_parsed_at":"2022-07-30T05:07:54.254Z","dependency_job_id":null,"html_url":"https://github.com/martinklepsch/tenzing","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinklepsch%2Ftenzing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinklepsch%2Ftenzing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinklepsch%2Ftenzing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/martinklepsch%2Ftenzing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/martinklepsch","download_url":"https://codeload.github.com/martinklepsch/tenzing/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248650419,"owners_count":21139672,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["clojure","clojurescript","project-template","starter-kit"],"created_at":"2024-10-14T20:26:05.489Z","updated_at":"2025-04-13T00:44:31.437Z","avatar_url":"https://github.com/martinklepsch.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tenzing, the awesome Clojurescript application template\n\n[rationale](#rationale) | [usage](#usage) | [deployment](#deployment) | [getting help](#getting-help)\n\n\nTenzing is a Clojurescript template offering the following features:\n\n1.  Incremental Clojurescript compilation\n2.  Live reloading of your Javascript, CSS, etc.\n3.  Browser-REPL\n\n**In contrast to some of the options out there it is opinionated in the following ways:**\n\n1.  Tenzing uses [Boot](https://github.com/boot-clj/boot) instead of Leiningen (see below)\n2.  Tenzing does not provide a backend layer (see below)\n3.  Tenzing allows you to choose between Om, Reagent and others\n\n# Rationale\n\n## Why Boot?\n\nIn contrast to Leiningen Boot offers a clear strategy when it comes to\ncomposing multi-step build processes such as compiling stylesheets and\nJavascript whenever a relevant file changes.\n\nMany Leinigen plugins come with an \\`auto\\` task that allows similar\nbehavior. If you want to run multiple of those tasks it's usually done\nby starting multiple JVM instances which can lead to\n[high memory usage](https://github.com/plexus/chestnut/issues/49). Boot\nallows this sort of behaviour to reside in one JVM process while\nmaking sure that build steps don't interfere with each other.\n\nYou can learn more about Boot in\n[a blog post by one of the authors](http://adzerk.com/blog/2014/11/clojurescript-builds-rebooted/),\nits [github project](https://github.com/boot-clj/boot) or\n[a blog post I wrote about it](http://www.martinklepsch.org/posts/why-boot-is-relevant-for-the-clojure-ecosystem.html).\n[Mimmo Costanza's modern-cljs tutorial](https://github.com/magomimmo/modern-cljs) also uses Boot throughout - \n[Tutorial 2](https://github.com/magomimmo/modern-cljs/blob/master/doc/second-edition/tutorial-02.md)\nwalks through the setup of a typical Boot-based development environment.\n\n## Why #noBackend?\n\nTenzing is designed with prototyping in mind. Instead of writing your\nown backend you're encouraged to use services like\n[Firebase](https://www.firebase.com),\n[Usergrid](http://usergrid.incubator.apache.org) and others.\n\nIf you figure out that you need a Clojure based backend down the road\nit's simple to either add it yourself or create it as a standalone\nservice that's being used by your clients.\n\nPlease, also consider\n[offline first](http://alistapart.com/article/offline-first) as an\napproach for building early iterations of your application.\n\n\u003e If you're wondering how files are served during development: there\n\u003e is a boot task \\`serve\\` that allows you to serve static files.\n\n# Usage\n\n## Create a Project\n\nTo create a new project, [install boot](https://github.com/boot-clj/boot#install) and run:\n\n```shell\n$ boot -d boot/new new -t tenzing -n your-app\n```\n\nTemplate options are specified using the `-a` switch. For example:\n\n```shell\n$ boot -d boot/new new -t tenzing -n your-app -a +reagent -a +test\n```\n\nAlternatively, if you have leiningen installed, you can run\n\n```shell\n$ lein new tenzing your-app\n```\n\nor to specify options:\n\n```shell\n$ lein new tenzing your-app +reagent +test\n```\n\nThere are a bunch of options that determine what your newly created\nproject will contain:\n\n-   `+om` provides a basic [Om](https://github.com/omcljs/om)\n    application and adds relevant dependencies\n-   `+reagent` provides a basic\n    [Reagent](https://github.com/reagent-project/reagent) application\n    and adds relevant dependencies\n-   `+rum` provides a basic\n    [Rum](https://github.com/tonsky/rum) application\n    and adds relevant dependencies\n-   `+garden` sets up [Garden](https://github.com/noprompt/garden) and\n    integrates into the build process\n-   `+sass` sets up [Sass](http://sass-lang.com) and integrates into\n    the build process (requires [libsass](http://libsass.org))\n-   `+less` sets up [Less](http://lesscss.org/) and integrates into\n    the build process.\n-   `+test` adds a\n    [cljs test-runner](https://github.com/crisptrutski/boot-cljs-test)\n    and adds a `test` task.\n-   `+devtools` adds a\n    [cljs-devtools](https://github.com/binaryage/cljs-devtools) through\n    [boot-cljs-devtools](https://github.com/boot-clj/boot-cljs-devtools)\n-   `+dirac` adds a\n    [dirac](https://github.com/binaryage/dirac) through\n    [boot-cljs-devtools](https://github.com/boot-clj/boot-cljs-devtools).\n\nIf you want to add an option,\n[pull-requests](https://github.com/martinklepsch/tenzing) are welcome.\n\n## Running it\n\nAfter you [installed Boot](https://github.com/boot-clj/boot#install)\nyou can run your Clojurescript application in \"development mode\" by\nexecuting the following:\n\n    $ boot dev\n\nAfter a moment of waiting you can head to\n[localhost:3000](http://localhost:3000) to see a small sample app. If\nyou now go and edit one of the Clojurescript source files or a SASS\nfile (if you've used the `+sass` option) this change will be picked up\nby Boot and the respective source file will get compiled. When a\ncompiled file changes through that mechanism it will get pushed to the\nbrowser.\n\nIf you used the `+test` option, then you'll be able to run unit\ntests via `boot test`. Use `boot auto-test` to have tests\nautomatically rerun on file changes.\n\n### Connecting to the browser REPL\n\nAfter you started your application with `boot dev` there will be a\nline printed like the following:\n\n    nREPL server started on port 63518 on host 0.0.0.0\n\nThis means there now is an nREPL server that you can connect to. You\ncan do this with your favorite editor or just by running `boot repl\n--client` in the same directory.\n\nOnce you are connected you can get into a Clojurescript REPL by\nrunning `(start-repl)`. At this point I usually reload my browser one\nlast time to make sure the REPL connection is properly setup.\n\nNow you can run things like `(.log js/console \"test\")`, which should\nprint \"test\" in the console of your browser.\n\n### How it works\n\nIf you look at the `build` and `run` tasks in the `build.boot` file of\nyour newly created project you will see something like the following:\n\n```clojure\n(deftask build [] (comp (speak) (cljs) (sass :output-dir \"css\")))\n\n(deftask run [] (comp (serve) (watch) (cljs-repl) (reload)\n    (build)))\n```\n\nBasically this composes all kinds of build steps into a unified `run`\ntask that will start our application. From top to bottom:\n\nThe `build` task consists of three other tasks:\n-   `speak` gives us audible notifications about our build process\n-   `cljs` will compile Clojurescript source files to Javascript\n-   `sass` will compile Sass source files to CSS\n\nNow if we just run `boot build` instead of the aforementioned `boot\ndev` we will compile our Clojurescript and Sass exactly once and then\nthe program will terminate.\n\nThis is where the `run` task comes in:\n-   `serve` starts a webserver that will serve our compiled JS, CSS\n    and anything else that is in `resources/`\n-   `watch` will watch our filesystem for changes and trigger new\n    builds when they occur\n-   `cljs-repl` sets up various things so we can connect to our\n    application through a browser REPL\n-   `reload` will watch the compiled files for changes and push them\n    to the browser\n-   `build` does the things already described above\n\n**Please note that all tasks, except the one we defined ourselves have\n  extensive documentation that you can view by running `boot\n  \u003ctaskname\u003e -h` (e.g. `boot cljs-repl -h`).**\n\n### Writing build artifacts to disk\n\nBy default, none of the tasks in projects generated by tenzing output any files. \n\nFor example, when running the `dev` task, your project's source and resources are \ncompiled to a temporary boot fileset and served from there. When boot quits, the \nfileset is no longer available.\n\n\nThis is actually boot's default and, at first, might sound like a strange choice for a build tool!\nHowever, these managed filesets are at the core of boot's philosophy and provide it with \nmany advantages over declarative, stateful build tools. See the [boot homepage](http://boot-clj.com) or the \n[`filesets` wiki entry] (https://github.com/boot-clj/boot/wiki/Filesets) for more info on these concepts.\n\nSo how do you output your built project to disk so that you can deploy it for example? \nSimple! Boot has a [built-in `target` task]\n(https://github.com/boot-clj/boot/blob/master/doc/boot.task.built-in.md#target) that you can can compose with other tasks to \noutput their results to a given directory (by convention the directory is named `target`).\n\nTo build a tenzing project with the production settings and output the\nresults to disk you would run the following:\n\n    $ boot production build target\n\nIf you look in your project directory now, you will see a `target` directory containing the\noutput of all of the tasks in this chain. By default, this directory is cleaned every time\nyou run `boot`, unless you pass the `no-clean` option to the `target` task.\n\nShould you need to filter, copy, move or rename the output files, or change the directory \nstructure, the [`sift` task](https://github.com/boot-clj/boot/blob/master/doc/boot.task.built-in.md#sift) will help you do this. If you have complex post-processing needs \nor want to save typing at the command line, it's a simple matter to define your own [tasks](https://github.com/boot-clj/boot/wiki/Tasks).\n\n## Deployment\n\nSince Tenzing comes without a backend you can easily deploy your app\nto Amazon S3 or even host it in your Dropbox. To do that just copy the\nfiles in `target/` to your desired location.\n\n\u003cimg src=\"https://cloud.githubusercontent.com/assets/97496/11431670/0ef1bb58-949d-11e5-83f7-d07cf1dd89c7.png\" alt=\"confetti logo\" align=\"left\" /\u003e\n\n\u003e PS. I'm also working on a tool called\n\u003e [Confetti](https://github.com/confetti-clj/confetti) 🎉 that helps\n\u003e you setting up static sites on AWS infrastructure. It's a bit more\n\u003e aimed at people that deploy and manage many static sites but you\n\u003e should probably check it out either way :)\n\n## Getting Help\n\nIf you run into any problems feel free to open an issue or ping me (`martinklepsch`) in the [ClojureScript room on Riot.im](https://riot.im/app/#/room/#clojurescript:matrix.org) (no signup required).\n\n## Credits\n\nThe initial release of Tenzing was prompted by the urge to have\nsomething like the awesome\n[Chestnut template](https://github.com/plexus/chestnut) but built on\ntop of Boot. Many props to [Arne Brasseur](https://lambdaisland.com/)\nfor making getting started with ClojureScript a lot easier at the\ntime!\n\n# License\n\nCopyright © 2014 Martin Klepsch\n\nDistributed under the Eclipse Public License either version 1.0 or (at\nyour option) any later version.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinklepsch%2Ftenzing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmartinklepsch%2Ftenzing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmartinklepsch%2Ftenzing/lists"}