{"id":13767223,"url":"https://github.com/ameier38/equinox-tutorial","last_synced_at":"2026-03-12T03:38:59.890Z","repository":{"id":134261346,"uuid":"163534375","full_name":"ameier38/equinox-tutorial","owner":"ameier38","description":"Tutorial for Jet.com Equinox library","archived":false,"fork":false,"pushed_at":"2020-11-27T22:36:18.000Z","size":7332,"stargazers_count":11,"open_issues_count":4,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-09T03:49:32.088Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","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/ameier38.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":"2018-12-29T19:01:48.000Z","updated_at":"2024-11-04T23:45:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"433239d9-6f83-4265-95f4-f554c84f1500","html_url":"https://github.com/ameier38/equinox-tutorial","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ameier38%2Fequinox-tutorial","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ameier38%2Fequinox-tutorial/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ameier38%2Fequinox-tutorial/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ameier38%2Fequinox-tutorial/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ameier38","download_url":"https://codeload.github.com/ameier38/equinox-tutorial/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253492529,"owners_count":21916959,"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":[],"created_at":"2024-08-03T16:01:06.325Z","updated_at":"2026-03-12T03:38:59.884Z","avatar_url":"https://github.com/ameier38.png","language":"C#","funding_links":[],"categories":["Learning Resources"],"sub_categories":["Github"],"readme":"# Equinox Tutorial\r\nPractical example for learning how to model a bi-temporal domain using\r\n[Jet.com's Equinox Event Sourcing Platform](https://github.com/jet/equinox).\r\n\r\n__Features__\r\n- Bi-temporal, event sourced API in F# using \r\n[Jet.com's Equinox platform](https://github.com/jet/equinox) \r\nand [gRPC](https://grpc.io/) :milky_way:.\r\n- Protobuf files compiled with \r\n[Uber's Prototool](https://github.com/uber/prototool) :wrench:.\r\n- Fully typed GraphQL API using \r\n[FSharp.Data.GraphQL](https://github.com/fsprojects/FSharp.Data.GraphQL) :fireworks:.\r\n- Centralized logging with [Seq](https://datalust.co/seq) :scroll:.\r\n- Web application using [React](https://reactjs.org/) \r\nand [TypeScript](https://www.typescriptlang.org/) :computer:.\r\n- Fully Dockerized for fast local development :whale:.\r\n- Integration tests and example CI using [GitHub Actions](https://github.com/features/actions) :zap:.\r\n- Build automation using [FAKE](https://github.com/fsharp/FAKE) :hammer:.\r\n\r\n\u003e The domain model is a lease, such as a car lease. \r\nA more detailed explanation about the motivation for modeling a bi-temporal domain \r\ncan be found in the accompanying \r\n[blog post](https://andrewcmeier.com/bi-temporal-event-sourcing).\r\n\r\n## TL;DR\r\n```\r\ndocker-compose up -d --build web-app\r\n```\r\nEndpoints:\r\n- http://localhost:2113 -\u003e Event Store UI (database; user:admin password:changeit)\r\n- http://localhost:8081 -\u003e Seq UI (logging)\r\n- http://localhost:3000 -\u003e Web application\r\n\r\n## Structure\r\n```\r\nequinox-tutorial\r\n├── README.md           --\u003e You are here\r\n├── .github             --\u003e CI/CD\r\n├── docker-compose.yml  --\u003e Dockerization\r\n├── web-app             --\u003e Web application\r\n├── graphql-api         --\u003e GraphQL API\r\n├── lease-api           --\u003e Lease gRPC API (business logic)\r\n└── protos              --\u003e Protobuf files\r\n```\r\n\r\n## Screenshots\r\n__Application__\r\n![app](./images/app.png)\r\n\r\n__GraphQL Playground__\r\n![playground](./images/playground.png)\r\n\r\n__Seq Logs__\r\n![logs](./images/logs.png)\r\n\r\n__Event Store__\r\n![eventstore](./images/eventstore.png)\r\n\r\n## Time Travel\r\n![time-travel](./images/time-travel.gif)\r\n\r\n## Resources\r\n- [Equinox](https://github.com/jet/equinox)\r\n- [Event Sourcing Basics](https://eventstore.org/docs/event-sourcing-basics/index.html)\r\n- [12 Things You Should Know About Event Sourcing](https://blog.leifbattermann.de/2017/04/21/12-things-you-should-know-about-event-sourcing/)\r\n- [As Time Goes By Talk](https://youtu.be/xzekp1RuZbM)\r\n- [GitHub Workflow Syntax](https://help.github.com/en/articles/workflow-syntax-for-github-actions)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fameier38%2Fequinox-tutorial","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fameier38%2Fequinox-tutorial","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fameier38%2Fequinox-tutorial/lists"}