💻 Developer Guides
Hold on! This is a technical documentation that explains the logic and structure of Homarr. A certain degree of technical knowledge about programming is required to interpret these informations.
If you're looking for the installation guide, please use our detailed documentation.
Architecture overview
The following UML package diagram shows the relations and dependencies, that Homarr has. Each arrow indicates a relation between two components. The arrow itself shows the direction of communication.
Technology stack
Is is a coarse list of the technologies, that are in use and how we use them.
- Next.js: React framework that enables us to render on the server, build APIs and authenticate.
- Mantine: Complex UI library, that provides useful components, easy inline styling, custom forms and more. Can easily be extended and modified for Homarr's design.
- Tablericons: Vast collection of minimal and modern icons
- Axios: Promise based HTTP client that is browser and node.js compatible.
- I18N: Internationalization framework that provides globalisation and localization
- Zustand: Client-side state management for React
- Zod: Strict Typescript schema validation for the browser and node.js
- Tanstack: Several packages for asynchronous storages and queries
- Emotion: Inline CSS
There are other packages as well, but those are not of significant importance to the architecture. If you want to know those technologies are used for production builds & deplyoments, check out the deployments section.
Online documentation
The above only covers the application itself. For the online documentation, we are using different technologies to remove as much overhead as possible.
As the base, we use Docusaurus to write documentation fast and efficently. The documentation is open-source and can be edited by anyone:
Since many searching solutions require licensing or expensive cloud services, we use the docusaurus-search-local plugin that builds the nessesary data at build.
Graphs can be written using mermaid.js, which were in fact used for this page.
Principles and conventions
During development and production builds, we are enforcing our ESLint rules. Any errors will be marked automatically, if you have the correct extensions installed.
Development environments & extensions
All maintainers are using VisualStudio Code. Although it is possible to use other IDEs (like Jetbrain's), we advise against using them, as some extensions may not be available in other IDEs.
The minimal setup includes the following extensions:
- https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
- https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode
- https://marketplace.visualstudio.com/items?itemName=unifiedjs.vscode-mdx (for documentation only)
- https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense
- https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode
Additional extensions may include:
- https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker
- https://marketplace.visualstudio.com/items?itemName=seatonjiang.gitmoji-vscode
- https://marketplace.visualstudio.com/items?itemName=yoavbls.pretty-ts-errors
- https://marketplace.visualstudio.com/items?itemName=shardulm94.trailing-spaces
All of our repositories contain the required files to tell extensions,
what rules should be applied. You do not need to make additional configurations.
Please do not commit any files in the .vscode
directory or other of
your personal extensions.
Contribution workflow
Although this is not documented strictly in our workflow, it is recommended that you make frequent commits using git.
The English translation preset will be translated automatically in other languages using our community-driven translation program. For this reason, we will not accept any pull request with modifications to translation files other than additions or removals in the English template.
Deployments
Deployments are done using GitHub's action system. The build is created on Ubuntu (latest), which builds the project and pushes the finalized docker image to GHCR.
As a developer, you do not need to know anything about what each of these steps specifically does. However, it is recommended that you know the differences between development and production builds.
Creating a new widget
Creating your own widget may look overwheling at first, but using this guide, it will be very easy.
Preparations
- Ensure, that you've set up your development environment correctly.
- Prepare the desired data (eg. read API documentations, test out using Postman)
Create the widget
- Widgets are located in the directory
/src/widgets
. Choose a name for your widget and create a directory with this name - Inside the directory, create a new
.tsx
file, that has the name of the widget, suffixed byWidgetTile.tsx
(example:VideoStreamWidgetTile.tsx
) - Copy and paste the following code in your new file:
const definition = defineWidget({
id: 'your-widget-name',
icon: IconClock,
options: {},
gridstack: {
minWidth: 1,
minHeight: 1,
maxWidth: 12,
maxHeight: 12,
},
component: YourWidgetTile,
});
export type IYourWidget = IWidget<(typeof definition)['id'], typeof definition>;
interface YourWidgetTileProps {
widget: IYourWidget;
}
function YourWidgetTile({ widget }: YourWidgetTileProps) {
/* hooks go here */
...
/* return JSX */
return (
<span>Hello World</span>
);
}
export default definition; - Replace all
YourWidget
in the above example with your widget name. Now you can start writing the UI of your widget. - If your widget makes requests over the network, it is recommended that requests are sent from Homarr instead of the client. This ensures that credentials will stay on the server. You can write new APIs for the widgets in the
/src/pages/api/modules/
directory. You can look at the other routes for good examples.
Secrets
Homarr has a built-in secrets management system. They are stored in the same JSON configuration, where your dashboard is configured & saved. For this reason, you should never share your config directly or commit it via git.
When the config is being sent to the client, the credentials are removed by the following code:
Public properties in the configuration will not be removed from the response. All passwords, usernames and tokens should be marked as private, so they get removed. Public properties can be used for public encryption keys or other values, that do not expose any important information.
Although this is already a big improvements to previous systems, it is still not considered 100% safe. In future versions of Homarr, the JSON configuration will be replaced with a relational database, that will enable us to never read out credentials, when sending data to the client.
Helper components
InfoCard
When making something in homarr, if you wish to add some information for the user, you may do so using the InfoCard. An element preprogrammed and easy to implement.
The element includes the info Icon and the hover card. Simply enter your message and the link if there is one.
Simply insert it as any other element:
import { InfoCard } from '~/components/InfoCard/InfoCard'
return(
<InfoCard message="Leave empty to keep the title hidden." link="https://homarr.dev/docs/"/>
)
Component Prop
Component Prop | Description | Input value | Default state |
---|---|---|---|
message | Message in plain text to be shown to the user upon hover. | Text | Obligatory value upon using the element |
link | Link shown at the end of the text under the translated text "See More...", if left empty the "See More..." will not show. | URL | Optionnal value |
bg | The background of the HoverCard is by default set to follow the Dark/Light modes, but can be changed using this prop. | Color | Optionnal value |
Position | Position from where the HoverCard will open. |
| Optionnal value, default at Top |
hoverProp | Prop directly linked to the HoverCard element in the InfoCard. | Partial<HoverCardProp> | - |
cardProp | Prop directly linked to the RichTextEditor element in the InfoCard | Partial<RichTextEditorProps> | - |
If you wish for more control over the hovercard, go check it out directly in src/components/InfoCard/InfoCard.tsx
.
Widget options
The InfoCard is already implemented onto the Widget's Options.
If your widget option is a bit ambiguous, you can give more information by activating it's infocard automatically like in the following exemple that will directly use the translation point, using info: true
.
This exemple is the one that leads to the first screenshot. It shows it being implemented onto the text widget option but is in fact available on ALL widget options.
As stated before, it supports links and here you just need to add it onto the infoLink
component to which we recommend linking to the Homarr docs.
const definition = defineWidget({
id: '',
icon: Icon,
options: {
name: {
type: 'text',
defaultValue: '',
info: true,
infoLink: 'https://homarr.dev/docs/',
},
}
})