{"id":29894213,"url":"https://github.com/juxt/jig","last_synced_at":"2025-08-01T04:45:54.369Z","repository":{"id":10139754,"uuid":"12214217","full_name":"juxt/jig","owner":"juxt","description":"Jig is an application harness providing a beautifully interactive development experience for Clojure projects.","archived":false,"fork":false,"pushed_at":"2014-03-26T13:46:22.000Z","size":1482,"stargazers_count":227,"open_issues_count":7,"forks_count":19,"subscribers_count":14,"default_branch":"master","last_synced_at":"2025-07-22T22:29:22.511Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/juxt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-08-19T10:50:54.000Z","updated_at":"2025-02-06T18:21:34.000Z","dependencies_parsed_at":"2022-08-25T11:02:08.229Z","dependency_job_id":null,"html_url":"https://github.com/juxt/jig","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/juxt/jig","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fjig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fjig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fjig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fjig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/juxt","download_url":"https://codeload.github.com/juxt/jig/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juxt%2Fjig/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268171719,"owners_count":24207418,"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","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2025-08-01T04:45:46.468Z","updated_at":"2025-08-01T04:45:54.347Z","avatar_url":"https://github.com/juxt.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Jig\n\n\u003e “Programming should be interactive, as beautiful as possible, modular, and it should generate assets that are easy to use and learn.” – [Michael O. Church](http://michaelochurch.wordpress.com/2013/08/07/why-clojure-will-win/)\n\n![A jig](console/resources/assets/main_2right-angle-jig.jpg)\n\nJig is an __application harness__ providing a beautifully interactive\ndevelopment experience __for Clojure projects__.\n\n## Releases and Dependency Information\n\n[![Current Version](https://clojars.org/jig/latest-version.svg)](https://clojars.org/jig)\n\n## Features and benefits\n\nFeedback is at the heart of all agile software development processes. If\nyou can reduce the time between making a change and seeing the result,\nyou can proceed faster, with more confidence and accuracy.\n\nFor the majority of developers, the impact of changing code cannot be\ndetermined until the entire system has been re-built and\nre-tested. While there are many advantages to frequent and thorough\ntesting, for developers the wait is long enough for us to lose our\nconcentration and focus.\n\n![Losing focus - attribution: http://xkcd.com/303/](console/resources/assets/compiling.png)\n\nUnless you have experienced a development environment that offers\n_instant feedback upon change_ it is difficult to describe the impact it\ncan have on your ability to solve difficult problems, produce reliable\ncode quickly and make programming more enjoyable.\n\n### Addressing Clojure's code reloading quirks\n\nClojure, in the tradition of dynamic languages, comes very close to\nproviding this kind of experience right out-of-the-box. In LISP,\nfunctions are bound to vars, which can be rebound, and when functions\nare applied, the latest binding of the function is used.\n\nIn practice, however, there are some minor quirks that impair the\ndependability of the code reloading : adding a new library dependency,\nredeclaring a `defmulti` or Clojure protocol, stale state referenced\nin `def`s and `defonce`s are some examples. One of Jig's aims is\nto handle these incidentals for you, letting you concentrate more fully\non your programming.\n\nJig builds upon Stuart Sierra's excellent\n[reloaded workflow](http://thinkrelevance.com/blog/2013/06/04/clojure-workflow-reloaded)\npattern. Therefore it's important that you're familiar with the general\nidea of this pattern: the developer invokes a 'reset' function at\nvarious intervals which causes a minimalist reloading of just the code\nthat has changed since the last reset, and anything else that needs\nreloading as a result (Due to the intricacies of Clojure and the JVM,\nthis is a non-trivial problem that Stuart has solved). Typically, the\nreset function is bound to a hotkey, Emacs keybinding (I use \"C-c r\") or\n[something](http://www.thegreenhead.com/2007/05/big-red-button-doomsday-device-usb-hub.php)\n[more](http://www.dreamcheeky.com/big-red-button)\n[exotic](http://www.stealthswitch2.com/products/stealthswitch-ii/). The\nprice of entry is that a developer has to ensure all application state\nis held in a single map (or record) called the _system_. Otherwise the\npattern doesn't work but in practice this is a good architectural policy\nto establish regardless.\n\nJig extends Stuart's work by providing some optional extra features that\ncan help in the development of large Clojure systems:\n\n* modularity through componentisation\n* configuration\n* support for multiple projects\n* a growing set of common re-usable infrastructure components.\n\n### Modularity\n\nStuart describes the System Constructor which creates the initial\n_state_ of a system. Jig provides an implementation of the System\nConstructor that delegates the job of creating the system to components,\neach component having the same lifecycle interface as Stuart describes:\n`init`, `start` and `stop`. The System is created by\nthreading it through all the components.\n\nA reset stops and restarts all components. Components are initialized\nand started (in dependency order) and stopped (in reverse dependency\norder) allowing for a clean shutdown of resources.\n\n#### Why?\n\nThere are many good reasons for dividing your System into separate\ncomponents. One is that it gives you looser coupling between your\ncomponents, which can make it easier to re-use them (among other\nbenefits). Another is that it allows you flexibility and architectural\noptions at deploy time.\n\nFor example, you can deploy all your components in a single JVM for a\ntest environment, while in production you could distribute components\nacross multiple JVMs, for scaleability. If you are forced to deploy lots\nof small JVMs, in all environments, this can be an inefficient use of\nprecious memory. I prefer to run a smaller number of JVMs, each with\nmore memory. Developing Clojure applications as monolithic systems works\nwell to begin with but can reduce flexibility down the road.\n\nI want the option of deploying early versions of new projects quickly,\nwithout the hassle of setting up a new server or incurring the cost of a\ndedicated JVM (200Mb is not an insignificant overhead when you have\ndozens of Clojure-based web applications). Jig lets me quickly hook up\nnew web applications and services onto an existing Clojure deployment.\n\nHere's an example of one of my component graphs.\n\n![Example component dependency graph](console/resources/assets/example-graph.png)\n\n### Separation of dev-workflow from application code\n\nRather than using a lein template to generate the project and the\ncorresponding dev System, Jig separates these concerns. You can use\nJig's workflow to develop on existing projects that don't have a\nbuilt-in dev workflow.\n\nYou can also fork and improve Jig to your own requirements. The aim is\nto retain\n[internal re-prgrammability](http://martinfowler.com/bliki/InternalReprogrammability.html)\nto your development tooling.\n\nOne Jig project can be used against many different projects, even\nsimultaneously (see Components)\n\nI wrote Jig because I wanted to create new Clojure projects quickly\nwithout having to maintain the development harness for each one. As I\nmake a small improvement to one development harness, I don't want the\nhassle of going through all my other projects to update them in the same\nway, but neither do I want dozens of development harnesses that differ\nfrom each other. _I want one development harness, re-usable 'jig' that I can\nuse against multiple Leiningen-based projects._\n\n### Configuration\n\nJig lets you specify configuration for your components in a single\nconfiguration file. However, components can source their own\nconfiguration if desired.\n\n### Injection of the System into the web request context.\n\nJig does not have opinions as to how you should build your\napplications. However, if does provide good support for writing\n[Ring](https://github.com/ring-clojure) and\n[Pedestal](http://pedestal.io) services should you wish to keep using\nJig in your deployment. More details can be found below.\n\n### Automatic provision of url-for for URI generation\n\nPedestal boasts bidirectional routes, so that URIs can be generated from\nroute definitions rather than determined some other way. Jig provides a\n`url-for` function in the Pedestal context, and defaults the\n`app-name` and `request` to make it easy to generate paths that\nmake sense in the context of the page on which the link is placed.\n\n### Portable web applications\n\nIt can be cost-effective for multiple web applications to share the same\nJVM. Jig allows you to host web applications under contextual URI\nprefixes. This is a feature made possible by the provision of the\n`url-for` function, since 'portable' web applications can use this\nto generate URIs for web links in their content, without resorting to\nhard-coding URI paths.\n\n### Component failure recovery\n\nErrors thrown from components that fail during initialization or\nstart-up do not cause the entire system to fail. This reduces the number\nof times that you have to reboot the JVM. Only components that are\nsuccessfully initialized are started, and only those that are\nsuccessfully started are stopped. Any failures are indicated in the\nREPL, with full details and stack traces written to the log file..\n\n## Usage\n\nNormally you'll be used to creating with a project with `lein new`,\ncd'ing to the newly created directory, perhaps adding some plugins to\nits `project.clj` file, and running `lein`. Working with Jig is\ndifferent, in that you run `lein` from the Jig project directory and\n'point' the configuration at one (or more) of your existing Leiningen\nprojects.\n\nClone the Jig repository as you would any other Clojure project.\n\n    $ git clone https://github.com/juxt/jig\n\nConfigure Jig by copying in a config file into the\n`config/config.edn`. You can skip this step if you want to see Jig\nrunning in its default configuration which includes examples.\n\nIf you're using Emacs, load up Jig's `project.clj` and\n\n    M-x nrepl-jack-in\n\n(that's usually bound to 'Control-c, Meta-j')\n\nIn the `*nrepl*` buffer that (eventually) appears, type\n\n    user\u003e (go)\n\nAlternatively, on the command line, type\n\n    lein repl\n\nand then\n\n    user\u003e (go)\n\nSync the application by calling `reset`\n\n    user\u003e (reset)\n\nResetting the application will cause namespaces to reload (thanks to\nStuart's work in `org.clojure/tools.namespace`) such that the\napplication will be back in sync with the code-base. This is the feature\nthat makes development fast and interactive, and it's all thanks to\nStuart's hard work.\n\nYou should find yourself typing `(reset)` rather a lot, and soon\neven that becomes burdensome. Here's some Emacs code you can paste into\nyour `$HOME/.emacs.d/init.el` to provide a shortcut.\n\n```clojure\n(defun nrepl-reset ()\n  (interactive)\n  (save-some-buffers)\n  (set-buffer \"*nrepl*\")\n  (goto-char (point-max))\n  (insert \"(user/reset)\")\n  (nrepl-return))\n\n(global-set-key (kbd \"C-c r\") 'nrepl-reset)\n```\n\nor, if you are using [cider](\"http://github.com/clojure-emacs/cider\"):\n\n```clojure\n(defun cider-repl-reset ()\n  (interactive)\n  (save-some-buffers)\n  (with-current-buffer (cider-current-repl-buffer)\n    (goto-char (point-max))\n    (insert \"(user/reset)\")\n    (cider-repl-return)))\n\n(global-set-key (kbd \"C-c r\") 'cider-repl-reset)\n```\n\nAfter re-evaluating (or restarting Emacs) you'll be able to reset the\napplication using 'Control-c r'.\n\n## Configuration\n\nA configuration specifies :\n\n* which components you want to include in your system\n* where to find these components (the Leiningen project) and\n* the configuration settings they will get\n\nUsually you've have one configuration file per project per environment (e.g. dev, uat, prod).\n\nBy default, Jig looks for a `config/config.edn` file, but you can override this by placing a config file in `$HOME/.jig/config.edn` (where $HOME is your home directory). If a configuration file can't be found, a default will be used.\n\nA configuration is a map which usually contains a `:jig/components` key listing the\ncomponents in a map (each key in the map is the component's label). You can get a good idea of the format by looking at the `config/default.edn` file.\n\n### Includes\n\nIt's also possible to link to other configuration files, which are merged into a single config :\n\n```clojure\n{\n :jig/include [\"/home/malcolm/src/octopus/config.clj\" \"/home/malcolm/src/juxtweb/config.clj\"]\n }\n```\n\n### Formats\n\nWhile `.edn` files are preferred, you can use `.clj` if you want\nto evaluate Clojure expressions, such as calculations.\n\nImportant: To avoid injection attacks, never use the `.clj` suffix\nfor configuration you don't entirely control, including user submitted\nconfiguration.\n\n### Dealing with multiple diverging configurations\n\nA very useful trick is to use Clojure's `#=` reader macro in the\n`$HOME/.jig/config.clj` (you can't use an `.edn` file for this\ntrick). A useful pattern is to load in the default configuration and\nmake tweaks to it for the environment you're running Jig in. This helps\nto prevent a proliferation of diveraging configuration files, which is a\ncommon problem with multiple environments in any configuration\nsystem. Each configuration can inherit from the defaults and use a\nClojure program to derive a modified version. What better language than\nClojure to tweak a map?\n\nHere's an example.\n\n```clojure\n#=(eval\n  (-\u003e\n    ;; Start with the original configuration, stored in the git repo\n    (clojure.core/read-string (slurp (str (System/getProperty \"user.home\") \"/src/my-proj/config.clj\")))\n\n    ;; Add a 'private' component\n    (assoc-in [:jig/components :firefox-reloader]\n      {:jig/component 'jig.web.firefox-reload/Component\n                  :jig/dependencies [:service :cljs-server]\n                  :jig.web.firefox-reload/host \"localhost\"\n                  :jig.web.firefox-reload/port 32000\n                  })\n\n    ;; Oh dear, some tricky path munging. We have to change lots of paths!\n    ;; Let's walk the tree.\n    ;; Due to symlinks not working well on Dropbox mounts,\n    ;; replace all instances of relative paths with absolute ones\n    ((partial clojure.walk/postwalk\n      (fn [x]\n        (if-let\n          [path (and (string? x)\n                     (second (re-matches #\"\\.\\./my-proj(.*)\" x)))]\n                (str \"/home/malcolm/another-path/src/my-proj\" path)\n                x))))))\n```\n\n## Components\n\nYou can write your own components by defining a type or record. At the\nvery least it needs to implement the `jig.Lifecycle` protocol.\n\n```clojure\n(:ns org.example.core\n  (:import (jig Lifecycle)))\n\n(deftype Component [config]\n  Lifecycle\n  (init [_ system] system)\n  (start [_ system] system)\n  (stop [_ system] system))\n```\n\nIn Stuart's reloaded workflow, the `init` function is responsible\nfor creating the System. In Jig's component model, the system map is\nthreaded through each component's `init` function, giving it a\nchance to add stuff. Likewise for the `start` and `stop`\nfunctions. The minimum you need to do is return the original system, for\nthe next component in the chain.\n\nOnce you have declared your component, you need to reference it in the\nconfig file `config/config.edn`. Jig needs to know which components\nyou want activated. If this file doesn't already exist, copy over the\ncontents from `config/sample.config.edn`. If you need to evaluate\nClojure expressions in your config, use a `.clj` suffix,\ne.g. `config/config.clj`\n\nFor example...\n\n```clojure\n{:jig/components\n  {:hello-app {:jig/component org.example.core/Component}}}\n```\n\nComponents will be instantiated with a single argument: the component's\nconfiguration value as specified in the config file. So if you want to\npass configuration to your component, an easy option is to add it to the\ncomponent's entry in the `config/config.edn` file.\n\nIf you want to see the state of the system at any time, it's available from the REPL\n\n    user\u003e system\n\nIt's nicer if you have pretty printing enabled at the REPL.\n\n    M-x cust-var\u003cRET\u003enrepl-use-pretty-printing\n\nAlternatively, you can be explicit.\n\n    user\u003e (pprint system)\n\n### Dependencies\n\nSometimes a component will rely on the existence of\nanother. Dependencies can be specified in the component configuration\nunder the `:jig/dependencies` key, where the value is a vector of\nkeys to other components in the configuration.\n\nFor example, let's suppose component Y is dependent on component X.\n\n```clojure\n{:jig/components\n  {\"X\" {:jig/component org.example.core/X}\n   \"Y\" {:jig/component org.example.core/Y\n        :jig/dependencies [\"X\"]}}}\n```\n\nYou can also view the component dependency graph from the REPL :-\n\n    user\u003e (graph)\n\n![Component dependency between X and Y](console/resources/assets/component-dependencies.png)\n\n### Persisting state across resets\n\nThere are some situations where you want state to survive across\nresets. Values that are stored in the system anywhere under the\n`:jig/safe` branch will not be purged. In the vast majority of cases\nyou should prefer state to be reinitialised on a reset.\n\n### Built-in components\n\nJig comes with its own components, providing useful functionality and\ndemonstrate how components are written. Each component is\nconfigurable. If you need a component which isn't in this list, I am\nhappy to provide it.\n\n#### jig.web.ring/Jetty\n\nProvides a Jetty service that can be used by Ring applications.\n\n#### jig.web.ring/Compojure\n\nAmalgamates Compojure routes contributed by other components into a single handler.\n\n#### jig.git/GitPull\n\nPulls the latest code from a remote git repository. This can be useful\nas part of an automatic continuous delivery mechanism.\n\n#### jig.jmx/JmxMBean\n\nProvides a reload capability, invokable as a JMX operation.\n\n#### jig.web.stencil/StencilLoader\n\nClears out the [stencil](https://github.com/davidsantiago/stencil) cache to ensure stale Mustache templates do not survive a system reset.\n\n#### jig.nginx/Purge\n\nPurges an nginx reverse proxy to ensure cached pages do not survive a\nsystem reset.\n\n#### jig.nrepl/Server\n\nProvides an nREPL server, useful if the system isn't started with\n`lein repl` but an nREPL service is still desired.\n\n#### jig.web.firefox-reload/Component\n\nA trigger to get Firefox to reload the current page upon every\nrest. Requires the\n[Remote Control addon](https://addons.mozilla.org/en-US/firefox/addon/remote-control/))is\ninstalled and enabled (the icon should be green).\n\n#### jig.web.server/Component\n\nProvides a Pedestal service on a Tomcat or Jetty listener, and ensures\nthat the System is made available to each Pedestal handler. This unifies\nStuart's approach with the Pedestal framework, allowing you to enjoy\nStuart's rapid development workflow while writing Pedestal services.\n\nOne of the major benefits of Pedestal over Ring is the support for\nbi-directionality between routes and handlers. For me, this is a\nstand-out feature because of the importance of hyperlinks, both in web\npages and RESTful web applications.\n\nAsking the library to generate URLs for you, rather than hard-coding\nthem in your application, reduces the risk of broken links and\nmaintenance cost. Jig injects a useful function into the Pedestal\ncontext, under the `:url-for` key, that lets you generate URLs\nrelative to request you are processing. By default, URLs are generated\nto handler within the same application, but you can specify\n`:app-name` to target other applications hosted in the same JVM.\n\nLook at the use of `url-for` in the example below. See how _easy_ it\nis to generate URLs to target other Pedestal handlers. Nice.\n\n```clojure\n(defhandler my-index-page [request]\n  {:status 200\n   :headers {\"Content-Type\" \"text/plain\"}\n   :body \"Hello World!})\n\n(defbefore my-root-page [{:keys [url-for] :as context}]\n  (assoc context :response\n    (ring.util.response/redirect\n      ;; Look, no nasty hard-coded URLs!\n      (url-for ::my-index-page))))\n```\n\n#### jig.web.app/Component\n\nProvides a web application abstraction on top of\n`jig.web.server/Component`. Other components can add Pedestal routes\nto a web application component. These are then combined to form a\ncomplete Pedestal route table.\n\nApplications can share the same `jig.web.server/Component`, allowing\nfor 'virtual hosts'. Applications can specify a different host, scheme\nor be rooted at a sub-context. This are really useful for hosting\ndifferent Clojure-powered websites on the same JVM.\n\nThese examples assume a little knowledge about Pedestal, see\nhttp://pedestal.io/documentation/service-routing/ for more details.\n\n#### jig.cljs/Builder\n\nAdding a step to compile ClojureScript on every reset can be\naccomplished with this component.\n\n```clojure\n:cljs-builder\n{:jig/component jig.cljs/Builder\n :jig/project \"../myproj/project.clj\"\n :output-dir \"../myproj/target/js\"\n :output-to \"../myproj/target/js/main.js\"\n :source-map \"../myproj/target/js/main.js.map\"\n :optimizations :none\n :clean-build false\n }\n```\n\nSetting `:clean-build` to true will cause the output directory to be\ndeleted on every reset, otherwise an incremental build will be\nperformed. The compiler environment is stored under the `:jig/safe`\nbranch to make incremental builds possible. Incremental builds are a lot\nfaster and are therefore enabled by default.\n\nYou may want to configure different builder components for different\npages, or for different optimizations. Multiple builds can be achieved\nby adding multiple instances of this component to your configuration.\n\n#### jig.cljs/FileServer\n\nOnce the JavaScript and source-map files have been generated, it is\noften useful to be able to serve it from a web server. A minimum of two\ndependencies must be specified, one should be a `jig.cljs/Builder`\ncomponent instance, the other should be the a\n`jig.web.app/Component` component instance. A web context should be\nspecified, under which resources will be available.\n\n```clojure\n:cljs-server\n{:jig/component jig.cljs/FileServer\n :jig/dependencies [:cljs-builder :web]\n :jig.web/context \"/js\"\n}\n```\n\n## Projects\n\nYou point Jig at your own projects by specifying a `:jig/project`\nconfiguration entry which specifies the project containing the component you wish to include.\n\n```clojure\n:juxtweb/service {:jig/component pro.juxt.website.core/Component\n                  :jig/dependencies [:juxtweb/web]\n                  :jig.web/app-name :juxtweb/web\n                  :jig/project \"../juxtweb/project.clj\"}\n```\n\nLeiningen dependencies that are added to a project during development\nare automatically can be added to the classpath, so you don't have to\nrestart the JVM if you are simply adding a dependency to a project.\n\n## Deployment\n\nYou can run Jig in production the same way as you run in development. If\nyou are using a single project which depends on Jig (or at least one Jig\nextension) you can uberjar your project.\n\n### uberjar\n\nCreate a main.clj or other similar namespace with the following content.\n\n```clojure\n(ns main (:gen-class))\n\n(defn -main [\u0026 args] (user/go))\n```\n\nIn your project.clj, add the following\n\n```clojure\n:main main :aot [main]\n```\n\nOr see https://github.com/mastodonc/kixi.hecuba for an example of a\nproject which deploys this way.\n\n## Caveats\n\n### The Lifecycle protocol\n\nI don't see any reason why others couldn't create their own 'jigs' (a\njig is a separate Leiningen project after all). Although this project is\nnamed eponymously, there can be others customized for specialist\ncontexts (either new projects, or forks of this one).\n\nIf that happens and there's a need to share components between jigs (for\nreasons of component portability) then it will make sense to promote the\n`Lifecycle` protocol (and maybe others) to a common library that\ndifferent jigs can use.\n\n#### EDN data readers\n\nIf an external project depends on a third-party jar which isn't on Jig's\nown classpath, then it will not have been visible to Clojure when\nclojure.core is first loaded. This means that any data readers declared\nin `/data_readers.clj` will not work. If you use the\n`edn/read-string` in these projects you cannot assume the\n`*data-readers*` dynamic var will contain the data readers declared\nin the third-party jar. The workaround is to use the 2-arg form of\nedn/read edn/read-string and supply the readers explicitly in the option\nmap.\n\nFor example, when loading Datomic data from a file, you would use the\nfollowing form :\n\n```clojure\n(edn/read-string\n   {:readers {'db/id datomic.db/id-literal\n              'db/fn datomic.function/construct\n              'base64 datomic.codec/base-64-literal}}\n   \"my-data.edn\")\n```\n\n### user.clj\n\nIf a project has a `/user.clj` file in one of its source\ndirectories, then it will be loaded on a reset and override Jig's user\nnamespace. Jig will then stop working. The current workaround is to\nensure such a file isn't visible to Jig, either by renaming it or by\nremoving the source directory containing it in the project's\n`project.clj` file. It is hoped that future versions of Jig will\navoid this issue by disabling the loading of such files by `tools.namespace`.\n\n## FAQ\n\n\u003e Clojure already does code reloading! Why do I need all this stuff?\n\nClojure, being a LISP, allows you to reload functions at will. But\nStuart's pattern (which Jig builds on) extends this to state,\ncompile-time macros, protocols/types/records and\nmulti-methods. Experienced Clojure developers know when to reload some\nnamespaces and when to restart the JVM. It seems better to raise the\nabstraction so you don't have to think about these technicalities all\nthe time, just 'reset' each time you want consistency while you develop.\n\nSee this comment for a better explanation: https://news.ycombinator.com/item?id=5819912\n\nJig is trying to provide you with a better development experience, while\nnudging you towards a modular architecture that will help you when your\nsystem grows to a certain size.\n\n\u003e Where can I find examples of projects using Jig?\n\n[Mastodon C](http://www.mastodonc.com/)'s\n[Hecuba](https://github.com/mastodonc/kixi.hecuba) project uses Jig for\ndevelopment, deploying using lein uberjar.\n\n[JUXT Accounting](https://github.com/juxt/juxt-accounting) is a full application that is developed with Jig 1.0.x.\n\nJUXT's [website](https://juxt.pro) also [uses](https://github.com/juxt/juxtweb) Jig 1.0.x, for both development and deployment.\n\n\u003e What's the relationship between Jig and Up?\n\n[Up](https://github.com/malcolmsparks/up) is deprecated, Jig replaces it\n(and has stolen all the worthy bits).\n\nThe main difference between Up and Jig is that Up added config to the\nLeiningen project and the dependency relation between projects and\ninfrastructure has been reversed. In due course Jig will add a protocol\nthat components can extend to communicate with other components over a\nSystem bus (core.async channel), and will then provide a superset of\nUp's functionality. Jig is better.\n\n## Troubleshooting\n\n### Look at the system\n\nDon't forget the system is available in the REPL, as `user/system`. That's useful for testing what functions are returning.\n\nYou can check what's in the system by outputting it to the\nconsole. `(keys user/system)` is often useful if the system gets\nvery large and you need to navigate it.\n\n### Log files\n\nBy default, Jig configures logback and logs are written to\n`$HOME/.jig/logs`. Events such as component init, startup and\nshutdown, and exceptions that occur during these phases, are written to\nhere. When the REPL tells you to check the log files, this is where you\nshould look.\n\n### Common errors in a component's init, start and stop functions\n\nYou should return the system value, modified if necessary, from each\ncomponent function. If you don't return any value, Jig will detect this\nand throw an error.\n\nMake sure that you do modify the system, but then return using the\nsymbol representing the unmodified system. That's a common mistake. Jig\nwon't detect that you have returned the same system it gave you, because\nthat's normal behaviour.\n\n### 'No implementation of method' when compiling components\n\n\u003e  java.lang.IllegalArgumentException: No implementation of method: :init of protocol: #'jig/Lifecycle found for class\n\nEnsure you `require` jig before `import`ing the `jig/Lifecycle` protocol.\n\n## Console\n\nBy default, a console is provided at http://localhost:8001.\n\nCurrently this supports the following (limited) functionality:\n\n* This README\n* A system map browser\n* Dynamically served [Codox](https://github.com/weavejester/codox) API documentation\n* A list of TODOs\n* Triggering a reload\n\nSecurity advisory: Since this console allows remote reloads, ensure that\nyou disable this console if you are intending to run production\napplications on Jig, or secure access to whatever port you run it on.\n\n## Examples\n\n### Sudoku\n\nMany people have asked for a demonstration of how to configure a simple\nRing application. This is provided as a Sudoku example in the\n`examples/` directory. It is incorporated in the default\nconfiguration and the website is accessible at http://localhost:8091/sudoku.html\n\n### MQTT broker\n\nThis is a network service built on Netty. It shows how easy it is to use\nJava service libraries directly using only Clojure and Jig. Please refer\nto the README.md in examples/mqtt-broker for more details.\n\n## Copyright and License\n\nCopyright © 2013 JUXT. All rights reserved.\n\nThe use and distribution terms for this software are covered by the\n[Eclipse Public License 1.0] which can be found in the file epl-v10.html\nat the root of this distribution. By using this software in any fashion,\nyou are agreeing to be bound by the terms of this license. You must not\nremove this notice, or any other, from this software.\n\n[Eclipse Public License 1.0]: http://opensource.org/licenses/eclipse-1.0.php\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuxt%2Fjig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuxt%2Fjig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuxt%2Fjig/lists"}