{"id":17982356,"url":"https://github.com/pedrobslisboa/full-stack-reasonml-advanced-sample","last_synced_at":"2026-03-19T02:41:36.357Z","repository":{"id":233184345,"uuid":"785847020","full_name":"pedrobslisboa/full-stack-reasonml-advanced-sample","owner":"pedrobslisboa","description":"A Full Stack native reason-react application with getInitialProps","archived":false,"fork":false,"pushed_at":"2024-09-03T14:51:39.000Z","size":496,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-29T18:23:59.489Z","etag":null,"topics":["reason-react","reasonml","server-reason-react"],"latest_commit_sha":null,"homepage":"https://native-reason-react-advanced-80387dde2d3c.herokuapp.com/","language":"Reason","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/pedrobslisboa.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-04-12T18:47:27.000Z","updated_at":"2024-09-03T14:51:44.000Z","dependencies_parsed_at":"2024-12-17T04:26:41.725Z","dependency_job_id":"839a363c-5981-42e5-b49c-860930d9eb50","html_url":"https://github.com/pedrobslisboa/full-stack-reasonml-advanced-sample","commit_stats":null,"previous_names":["pedrobslisboa/full-stack-reasonml-advanced-sample"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedrobslisboa%2Ffull-stack-reasonml-advanced-sample","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedrobslisboa%2Ffull-stack-reasonml-advanced-sample/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedrobslisboa%2Ffull-stack-reasonml-advanced-sample/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pedrobslisboa%2Ffull-stack-reasonml-advanced-sample/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pedrobslisboa","download_url":"https://codeload.github.com/pedrobslisboa/full-stack-reasonml-advanced-sample/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247107833,"owners_count":20884797,"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":["reason-react","reasonml","server-reason-react"],"created_at":"2024-10-29T18:14:03.878Z","updated_at":"2026-01-15T22:40:44.247Z","avatar_url":"https://github.com/pedrobslisboa.png","language":"Reason","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fullstack ReasonML Sample\n\n![Screenshot of the app runnning](screenshot.png)\n\n## Table of Contents\n\n- [Introduction](#introduction)\n- [Installation](#installation)\n- [Routing](#routing)\n- [Running](#running)\n- [License](#license)\n- [Improvements](#improvements)\n\n## Introduction\n\nThis is an advanced full-stack application using ReasonML and React. It serves as a sample project to demonstrate how to build an application with ReasonML and React, including a native ReasonML server. \n\nThis is possible due to this library: https://github.com/ml-in-barcelona/server-reason-react\n\nTo understand better how it works check this article: https://sancho.dev/blog/server-side-rendering-react-in-ocaml\n\nAnd you can access this app running here: https://native-reason-react-advanced-80387dde2d3c.herokuapp.com/\n\nThis project utilizes the following main libraries:\n\n- reasonml\n- reason-react\n- server-reason-react\n- melange\n- styled-ppx (emotion)\n\nKeep in mind that the project is still in development and may not be production-ready. It's just a sample project I'm having fun with. :)\n\n## Routing\n\nFor an easy way to build and manage data flow, this project uses the `getInitialProps` system, which retrieves data from the server and passes it to the client. It supports both SPA and SSR functionalities.\n\nExample:\n```reason\nopen DynamicRouting;\n\nloadedRoutes\n|\u003e register(\n     ~path=\"/\",\n     ~getInitialProps=(_) =\u003e Binding.Json.from_string(\"Hello World\"),\n     ~component=initialProps =\u003e\n     \u003ch1\u003e {ReasonReact.string(initialProps |\u003e Binding.Json.to_string)} \u003c/h1\u003e\n   );\n   \n// Register more routes here\n\nlet loadedPages = getLoadedRoutes();\n```\n\nThe `~getInitialProps` is defined as:\n```reason\nlet getInitialProps: option(Bindings_Dream.request =\u003e Bindings.Js.Promise.t(Bindings.Json.t));\n```\n\nIt returns a promise with a JSON object which you must decode into your data at the component level.\n\nThe idea is to eventually provide a better way to construct a prop type with a built-in decoder, perhaps using a PPX, similar to `deriving yojson` but universal.\n\n```reason\n// Pages_Home.re\ntype props = [%json { name: string }];\n\nlet json = {\n    name: \"John\"\n};\n\nlet decodedProps = props_of_yojson(json);\nlet jsonProps = props_to_yojson(decodedProps);\n\n// Pages.re\nloadedRoutes\n|\u003e register(\n     ~path=Pages_Home.path,\n     ~getInitialProps=Pages_Home.getInitialProps,\n     ~decode=Pages_Home.decode,\n     ~component=(initialProps) =\u003e \u003cPages_Home.component ?initialProps /\u003e\n   );\n```\n\nThis approach aims to streamline data handling and type management, eliminating the need for manual decoding.\n\nHowever, we still need to specify the decoder when registering routes. An alternative improvement is to deliver a module for route registration, allowing for better organization of routes and components.\n\n```reason\nopen DynamicRouting;\n\nloadedRoutes |\u003e register((module Pages_Home): (module Binding.DynamicRouting.LoaderPage));\n```\n\nThis method simplifies route registration without specifying a decoder or any module contract, facilitating better code organization.\n\nPlease note:\n- I'm not sure if this is feasible with ReasonML, but it's worth exploring.\n- I'm still mastering Universal ReasonML, so implementation may take some time.\n- I welcome your collaboration. :)\n\n## Installation\n\n```sh\n    make install\n```\n\nWith Docker:\n\n```sh\n    make docker-build\n```\n\n## Running\n\n```sh\n    make run\n```\n\nWith Docker:\n\n```sh\n    make docker-run\n```\n\n## License\n\nMIT\n\n## Improvements\n\n- Increase test coverage.\n    - Test custom hooks with the appropriate testing library.\n- Enhance custom bindings.\n- Improve error handling.\n- Implement Git hooks.\n- Set up CI/CD\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedrobslisboa%2Ffull-stack-reasonml-advanced-sample","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpedrobslisboa%2Ffull-stack-reasonml-advanced-sample","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedrobslisboa%2Ffull-stack-reasonml-advanced-sample/lists"}