-
Notifications
You must be signed in to change notification settings - Fork 6
Architecture
The Renku UI is a web interface written in TypeScript and based on React. We use many frameworks to make the development process easier and more efficient, and to simplify keeping a consistent approach to fetch, store, and visualize data. New code should use the latest tools and follow the conventions we set.
Mind we still have some legacy components for the previous version of Renku (pre 2.0) written in JavaScript or not following the conventions. We won't include them in this documentation, but you might find them in the codebase.
Here are the most important frameworks and tools used in the UI, organized by the task they accomplish.
We differentiate between persistent and volatile data.
Use RTK Query to fetch the data from (and push to) the backend. That's part of Redux Toolkit, built on top of Redux. Mind that the UI lives in the browser, so everything considered persistent comes from the backend and is fetched and pushed as needed.
We encourage using RTK code generation based on the OpenAPI specs of the backend APIs. You can get that from the swagger page of any deployment (available at the path /swagger
), configure a new api through createApi
, and run npm run generate-api
. We frequently enhance some APIs to leverage RTK Tags to automatically invalidate and re-fetch code. A complete example is in the client/src/features/dataConnectorsV2/api
folder.
Use React states for temporary states and user inputs that will either be saved permanently to the backend or discarded. You can use the useState
hook to store the data in the component that needs it. Mind it will be lost when the component is unmounted. The logic is simple and there are many examples in the codebase. Mind we rely on React Hook Form to simplify handling inputs and validation.
Suppose you need to share the data with other components. In that case, lifting the state up to the closest common ancestor is acceptable only if you go up to a close ancestor that belongs to the same category (E.G: ProjectProperties
stores the data and ProjectVisualizeNamespace
shows the input).
Sharing data across unrelated components is generally discouraged and is best done through persistent data stored in the backend. If you really need this approach, you can use RTK Query slices. You can check displaySlice
for an example.
Use React hooks like useParams
to access data encoded in the URL. Generally, URLs are not a good place to store data permanently. Use that to enable smooth navigation and link sharing.
We use Bootstrap as our frontend framework. It provides many classes and components that are enough for most of the UI. We encourage using the classes provided by Bootstrap instead of creating new classes. Feel free to pick the abstracted Bootstrap-specific components from Reactstrap.
We deploy Storybook to have a list of common patterns and examples. We keep there only simple components that can be reused and composed to create complex interaction. You can access it at <base_URL>/storybook/
. We encourage keeping similar patterns for new pages to have a consistent UX; there is no simple rule, but generally speaking copying the behavior of similar components is a good approach.
We use Cypress for test automation. It's a powerful tool that allows you to test the UI in a real browser. We have a bunch of tests that check the most common components and interactions. You need to run npm install
in the tests
folder to have all the necessary libraries. Then you can run the tests by running npm run e2e
from the same tests
folder, or npm run cypress
if you run the client separately.
We also have unit tests for the most complex functions and components. They are scattered around the codebase in files named *.tests.ts
, and usually accompany *.utils.ts
files. You can run the unit tests using npm test
from the client
folder.
We still have a backend-for-frontend based on Express that will be phased out in the future. It was used for authentication and still serves some limited purpose for Renku v1. For that reason, you will still see most of the API URLs contain /ui-server
. You can find the code in the server
folder.