{"id":13495550,"url":"https://github.com/darklang/rescript-tea","last_synced_at":"2026-02-07T07:05:09.432Z","repository":{"id":51060331,"uuid":"520218061","full_name":"darklang/rescript-tea","owner":"darklang","description":"The Elm Architecture for Rescript","archived":false,"fork":false,"pushed_at":"2022-11-12T05:33:37.000Z","size":971,"stargazers_count":120,"open_issues_count":13,"forks_count":12,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-10-19T12:38:50.661Z","etag":null,"topics":["rescript"],"latest_commit_sha":null,"homepage":"","language":"ReScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"OvermindDL1/bucklescript-tea","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/darklang.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-08-01T18:18:31.000Z","updated_at":"2025-08-05T20:05:18.000Z","dependencies_parsed_at":"2022-11-08T20:00:24.359Z","dependency_job_id":null,"html_url":"https://github.com/darklang/rescript-tea","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/darklang/rescript-tea","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darklang%2Frescript-tea","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darklang%2Frescript-tea/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darklang%2Frescript-tea/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darklang%2Frescript-tea/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/darklang","download_url":"https://codeload.github.com/darklang/rescript-tea/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/darklang%2Frescript-tea/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29188322,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T05:07:31.176Z","status":"ssl_error","status_checked_at":"2026-02-07T05:06:15.227Z","response_time":63,"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":["rescript"],"created_at":"2024-07-31T19:01:35.798Z","updated_at":"2026-02-07T07:05:09.416Z","avatar_url":"https://github.com/darklang.png","language":"ReScript","funding_links":[],"categories":["ReScript"],"sub_categories":[],"readme":"# Rescript-TEA\n\n[![NPM](https://nodei.co/npm/rescript-tea.png?compact=true)](https://nodei.co/npm/rescript-tea/)\n\n[![Build Status](https://circleci.com/gh/darklang/rescript-tea.svg?style=svg)](https://circleci.com/darklang/rescript-tea)\n\n## Description\n\nThis is a library that enables The Elm Architecture for Rescript.\n\n[The Elm Architecture](https://guide.elm-lang.org/architecture/) is an MVU pattern\nfor organizing frontend applications and components. Another example a\nTEA-influenced project is React/Redux.\n\nIn TEA, each component has single model. The model is updated by receiving messages\n(typically named `msg`) - all relevent browser and user events, including keyboard,\nmouse, fetch, clipboard, etc, are converted into messages. An `update` method\nreceives a model and message, and returns a new model. It can also return commands,\nwhich affect the outside world, for example by making API calls. And, that's it.\nThat's the whole idea.\n\nThe model is used to render HTML via a built-in virtual DOM. The entire application\nis just a single component with a single model and `update` function.\n\n## Advantages\n\n- Entirely event driven, this is like React/Redux but type-safe and significantly faster.\n- Amazingly fast compile-times, especially with Rescript's built-in watcher\n- Open license.\n\nYou can read more about it [here](http://blog.overminddl1.com/tags/bucklescript-tea/).\n\n## Project design\n\n- [X] Elm API: Following the Elm API as closely as Rescript allows. Converting code back and forth between Elm and OCaml should be made as easy as possible and there exists both a [converter](https://github.com/darklang/philip2), as well as [documentation](https://github.com/darklang/philip2#how-to-port-your-project) for that process.\n\n## Installation\n\n### NPM\n\nFirst verify you have `rescript` installed, whether globally or just in your project.\n\nThen install via npm by:\n\n```sh\nnpm install --save-dev rescript-tea\n```\n\nThen in your current Rescript project just use this as a dependency add this to your bsconfig.json file:\n\n```json\n  \"bs-dependencies\" : [\"rescript-tea\"]\n```\n\n## Usage\n\n### Example project\n\nOnce you have your Rescript project set up and the dependencies configured as above\nthen lets make a new TEA module, the Counter, as is traditional in Elm tutorials,\nthis file will be named `counter.res` in your `src` directory for this example. Code\nis described via inline comments:\n\n```rescript\n// This line opens the Tea.App modules into the current scope for Program access functions and types\nopen Tea.App\n\n// This opens the Elm-style virtual-dom functions and types into the current scope\nopen Tea.Html\n\n// Let's create a new type here to be our main message type that is passed around\ntype msg =\n  | Increment // This will be our message to increment the counter\n  | Decrement // This will be our message to decrement the counter\n  | Reset     // This will be our message to reset the counter to 0\n  | Set(int)  // This will be our message to set the counter to a specific value\n\n// the model for Counter is just an integer\ntype model = int\n\n// This is optional for such a simple example, but it is good to have an `init` function to define your initial model default values\nlet init = () =\u003e 4\n\n// This is the central message handler, it takes the model as the first argument\nlet update = (model: model, msg: msg) : model =\u003e\n  switch msg {\n  | Increment =\u003e model + 1\n  | Decrement =\u003e model - 1\n  | Reset =\u003e 0\n  | Set(v) =\u003e v\n  }\n\n// This is just a helper function for the view, a simple function that returns a button based on some argument\nlet viewButton = (title: string, msg: msg) =\u003e\n  button(list{Events.onClick(msg)}, list{text(title)})\n\n// This is the main callback to generate the virtual-dom.\n// This returns a virtual-dom node that becomes the view, only changes from call-to-call are set on the real DOM for efficiency, this is also only called once per frame even with many messages sent in within that frame, otherwise does nothing\nlet view = (model: model): Vdom.t\u003cmsg\u003e =\u003e\n  div(\n    list{},\n    list{\n      span(list{Attributes.style(\"text-weight\", \"bold\")}, list{text(string_of_int(model))}),\n      br(list{}),\n      viewButton(\"Increment\", Increment),\n      br(list{}),\n      viewButton(\"Decrement\", Decrement),\n      br(list{}),\n      viewButton(\"Set to 42\", Set(42)),\n      br(list{}),\n      model != 42 ? viewButton(\"Reset\", Reset) : noNode\n    })\n\n// This is the main function, it can be named anything you want but `main` is\n// traditional.  The Program returned here has a set of callbacks that can easily be\n// called from Rescript or from javascript for running this main attached to an\n// element, or even to pass a message into the event loop.  You can even expose the\n// constructors to the messages to javascript via the above [@@bs.deriving\n// {accessors}] attribute on the `msg` type or manually, that way even javascript can\n// use it safely.\nlet main = beginnerProgram({\n    model: init (),\n    update: update,\n    view: view\n  })\n```\n\n\nIf anything is typed wrong then the Rescript type checker will catch it and advise.\n\nTo use this from javascript (with your bundler of choice) you can just do:\n\n```javascript\n  var app = require(\"src/counter.res\").main(document.getElementById(\"my-element\"));\n```\n\nAnd if you need to shut it down or pass it a message or so then you can do so via the `app` variable, or feel free to not assign it to a variable as well.\n\nFor further examples see the [test\ndirectory](https://github.com/darklang/rescript-tea/tree/main/test), which has many\nexamples.\n\nFor a large-scale example, see the [Darklang client/editor](https://github.com/darklang/dark/tree/main/client).\n\n## Starter-Kits\n\nA list of starter-kits that get you up and running.\n\n\u003e Feel free to extend this list!\n\n#### [celsobonutti/vite-template-rescript-tea](https://github.com/celsobonutti/vite-template-rescript-tea)\n\n* build-system: [rollup](https://github.com/rollup/rollup)\n* dev-server: [vite](https://github.com/vitejs/vite)\n\n### Outdated started kits\n\n#### [tcoopman/bucklescript-tea-starter-kit](https://github.com/tcoopman/bucklescript-tea-starter-kit)\n\n* syntax: OCaml\n* build-system: [rollup](https://github.com/rollup/rollup)\n* dev-server: [zeit/serve](https://github.com/zeit/serve)\n\n#### [feluxe/bs-tea-starter-kit](https://github.com/feluxe/bs-tea-starter-kit)\n\n* syntax: ReasonML\n* build-system: [webpack](https://github.com/webpack/webpack)\n* dev-server: [webpack-dev-server](https://github.com/webpack/webpack-dev-server)\n* css: [bs-css](https://github.com/SentiaAnalytics/bs-css)\n\n#### [darklang/philip2](https://github.com/darklang/philip2)\n\nThis one is not so much a starter kit as it is a porting kit, it can actually take in Elm files, parse them, and output Rescript-tea code (though in OCaml, which can be converted to Rescript via `rescript convert`) with only minor'ish tweaks there-after needed to get it working.\n\nSee its announcement article at: https://medium.com/@paulbiggar/philip2-an-elm-to-reasonml-compiler-a210aaa6cd04\n\nAnd its porting guide at: https://github.com/darklang/philip2#how-to-port-your-project\n\n## History\n\nRescript-tea is a fork of\n[bucklescript-tea](https://github.com/OvermindDL1/bucklescript-tea), aimed to\nmodernize it base on how Rescript has developed since bucklescript-tea was created. We greatly appreciate the work that [OvermindDL1](https://github.com/OvermindDL1) put into it.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarklang%2Frescript-tea","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdarklang%2Frescript-tea","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdarklang%2Frescript-tea/lists"}