forked from ajnart/homarr-docs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* π Add developer page * Update developer-guide.mdx
- Loading branch information
Showing
5 changed files
with
1,222 additions
and
354 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,279 @@ | ||
--- | ||
title: π» Developer Guides | ||
tags: | ||
- Developer | ||
- Technical documentation | ||
- Code | ||
- Programming | ||
--- | ||
|
||
:::caution | ||
|
||
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](/docs/introduction/installation), | ||
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. | ||
|
||
```mermaid | ||
flowchart LR | ||
subgraph "Web Browser" | ||
Browser["Your Browser"] | ||
end | ||
subgraph "WAN / GAN" | ||
Browser -- "HTTP / HTTPS" --> IFrame["Any Iframes"] | ||
Browser -- "HTTP / HTTPS" --> Video["Any Videos"] | ||
Browser -- "HTTP / HTTPS" --> DashDotIframe["Dash. Iframes"] | ||
end | ||
subgraph "Homarr" | ||
HomarrApp["Homarr π¦"] | ||
Configs[("JSON Configurations")] | ||
HomarrApp -- "Filesystem" --> Configs | ||
end | ||
Browser -- "HTTP" --> HomarrApp | ||
subgraph "LAN" | ||
HomarrApp -- "HTTP" ---> TorrentClient[Torrent clients] | ||
HomarrApp -- "HTTP" ---> UsenetClient[Usenet clients] | ||
HomarrApp -- "HTTP" ---> MediaServer[Plex / Jellyfin] | ||
HomarrApp -- "HTTP" ---> PiHole[PiHole] | ||
HomarrApp -- "HTTP" ---> Rss[RSS feeds] | ||
HomarrApp -- "HTTP / HTTPS" ---> DashDotApi[Dash. API] | ||
HomarrApp -- "HTTP / HTTPS" ---> IconsApi[Icon repositories] | ||
end | ||
``` | ||
|
||
## Technology stack | ||
Is is a coarse list of the technologies, that are in use and how we use them. | ||
- [Next.js](https://nextjs.org/): React framework that enables us to render on the server, | ||
build APIs and authenticate. | ||
- [Mantine](https://mantine.dev/): 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](https://tabler-icons.io/): Vast collection of minimal and modern icons | ||
- [Axios](https://github.com/axios/axios): Promise based HTTP client that is browser and node.js compatible. | ||
- [I18N](https://www.i18next.com/): Internationalization framework that provides globalisation and localization | ||
- [Zustand](https://github.com/pmndrs/zustand): Client-side state management for React | ||
- [Zod](https://zod.dev/): Strict Typescript schema validation for the browser and node.js | ||
- [Tanstack](https://tanstack.com/): Several packages for asynchronous storages and queries | ||
- [Emotion](https://emotion.sh/docs/introduction): 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](#deployments). | ||
|
||
<details> | ||
<summary>Online documentation</summary> | ||
<div> | ||
|
||
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](https://docusaurus.io/) to write documentation fast and efficently. | ||
The [documentation is open-source](https://github.com/ajnart/homarr-docs) and can be edited by anyone: | ||
|
||
![](./img/edit-page-button.jpg) | ||
|
||
Since many searching solutions require licensing or expensive cloud services, | ||
we use the [docusaurus-search-local](https://github.com/cmfcmf/docusaurus-search-local) plugin | ||
that builds the nessesary data at build. | ||
|
||
Graphs can be written using [mermaid.js](https://mermaid.js.org), which were in fact used for this page. | ||
|
||
</div> | ||
</details> | ||
|
||
## Principles and conventions | ||
During development and production builds, we are enforcing our [ESLint](https://eslint.org/) rules. | ||
Any errors will be marked automatically, [if you have the correct extensions installed](#development-environments--extensions). | ||
|
||
|
||
## Development environments & extensions | ||
All maintainers are using [VisualStudio Code](https://code.visualstudio.com/). | ||
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 | ||
|
||
:::note | ||
|
||
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 | ||
|
||
```mermaid | ||
flowchart | ||
ReadIssue["Read informations in the issue"] --> AssignIssue["Assign the issue"] | ||
AssignIssue --> Confirm["Confirm that implementation is possible"] | ||
Confirm --> GitNewBranch["Create a new git branch"] | ||
GitNewBranch --> Implement["Implement"] | ||
Implement --> UnitTests["Write automated unit tests"] | ||
UnitTests --> ManualTests["Manual UI tests"] | ||
ManualTests --> Translations["Write English translation preset"] | ||
Translations --> GitPush["Push on fork / repo"] | ||
GitPush --> GitPullReqquest["Create pull request"] | ||
``` | ||
|
||
:::tip | ||
|
||
Although this is not documented strictly in our workflow, it is recommended that you make frequent | ||
commits using git. | ||
|
||
::: | ||
|
||
:::tip | ||
|
||
The English translation preset will be translated automatically in other languages | ||
using [our community-driven translation program](/docs/community/translations). | ||
For this reason, <strong>we will not accept any pull request with modifications to | ||
translation files other than additions or removals in the English template.</strong> | ||
|
||
::: | ||
|
||
## 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](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-container-registry). | ||
|
||
```mermaid | ||
flowchart | ||
SetupNode["Set up node.js"] --> Checkout["Check out git code"] | ||
Checkout --> GetCache["Get cache"] | ||
GetCache --> RestoreNextJsCache["Restore next.js cache"] | ||
RestoreNextJsCache --> InstallDepends["Install dependencies"] | ||
InstallDepends --> Build["Build"] | ||
Build --> DockerMeta["Attach metadata to docker"] | ||
DockerMeta --> SetUpQEMU["Set up QEMU"] | ||
SetUpQEMU --> SetUpBuildx["Set up Buildx"] | ||
SetUpBuildx --> LoginGHCR["Login to GHCR"] | ||
LoginGHCR --> BuildAndPush["Build and push"] | ||
OnPush((" ")) | ||
OnPullRequest((" ")) | ||
OnManualWorkflowDispatch((" ")) | ||
OnPush -- "On push on 'dev'" --> SetupNode | ||
OnPullRequest -- "On pull-request to 'dev'" --> SetupNode | ||
OnManualWorkflowDispatch -- "On manual workflow dispatch" --> SetupNode | ||
BuildAndPush --> Ending((" ")) | ||
style Ending fill:black | ||
``` | ||
|
||
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](#development-environments--extensions). | ||
- Prepare the desired data (eg. read API documentations, test out using [Postman](https://www.postman.com/)) | ||
|
||
**Create the widget** | ||
|
||
<ul> | ||
<li>Widgets are located in the directory <code>/src/widgets</code>. Choose a name for your widget and create a directory with this name</li> | ||
<li>Inside the directory, create a new <code>.tsx</code> file, that has the name of the widget, suffixed by <code>WidgetTile.tsx</code> (example: <code>VideoStreamWidgetTile.tsx</code>)</li> | ||
<li>Copy and paste the following code in your new file: | ||
|
||
```tsx | ||
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; | ||
``` | ||
|
||
</li> | ||
<li>Replace all <code>YourWidget</code> in the above example with your widget name. | ||
Now you can start writing the UI of your widget.</li> | ||
<li>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 <code>/src/pages/api/modules/</code> directory. | ||
You can look at the other routes for good examples.</li> | ||
</ul> | ||
|
||
## 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: | ||
|
||
https://github.com/ajnart/homarr/blob/1c0c9cc2821333427e3d2581b1179a88960fae88/src/pages/api/configs/%5Bslug%5D.ts#L50-L82 | ||
|
||
:::note | ||
|
||
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. | ||
|
||
::: | ||
|
||
:::caution | ||
|
||
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. | ||
|
||
::: |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.