Skip to content

Commit

Permalink
πŸ“ Add developer page (ajnart#49)
Browse files Browse the repository at this point in the history
* πŸ“ Add developer page

* Update developer-guide.mdx
  • Loading branch information
manuel-rw authored May 4, 2023
1 parent bbe5bc4 commit 801e0ab
Show file tree
Hide file tree
Showing 5 changed files with 1,222 additions and 354 deletions.
279 changes: 279 additions & 0 deletions docs/community/developer-guide.mdx
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.

:::
Binary file added docs/community/img/edit-page-button.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 801e0ab

Please sign in to comment.