Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/Developer/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"label": "Developer",
"position": 4
}
88 changes: 88 additions & 0 deletions docs/Developer/docker-apps.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
title: Docker Apps
description: Guide for creating & submitting Docker applications to the Unraid Community Applications Store
sidebar_position: 2
---

## Creating and Submitting Docker Apps

Docker apps are defined by XML template files that specify the container's configuration, such as ports, volumes, environment variables, and metadata.

## Step 1: Create the Docker Template XML

1. Go to the **Docker** tab and select **Add Container**.
2. Fill in the details based on your Docker image (e.g., from Docker Hub):
- **Repository**: The Docker image name (e.g., `domistyle/idrac6`).
- **Network Type**: Typically `bridge`.
- **Privileged**: Set to `true` only if necessary (e.g., for hardware access).
- Add ports, volumes, and variables using **Add another Path, Port, Variable or Device**.
- **Ports**: Use container ports (e.g., 5800 for WebUI). Set **Host Port** to blank or optional.
- **Volumes/Paths**: Use container paths (e.g., `/config`); avoid host paths to prevent auto-creating shares.
- **Variables**: Define keys (e.g., `IDRAC_HOST`), defaults, and descriptions.
- **WebUI**: Use format like `http://[IP]:[PORT:5800]` to dynamically map host ports.
- **Icon**: URL to a PNG or JPG image (host on GitHub for reliability).
- **Overview/Description**: Provide a clear, Markdown-formatted summary (no HTML).
- **Category**: Select from official options (e.g., `Tools: Network:Management`).
- **Support**: Link to your Unraid forums support thread.
- **Project**: Link to the project's GitHub or webpage.
3. Click **Save** to generate the XML. Copy it from the displayed text (in Authoring Mode).
4. Clean the XML:
- Remove unnecessary tags (e.g., empty `<MyIP/>`, `<DateInstalled>`).
- Use `<Config>` elements for ports, volumes, and variables (v2 format preferred over legacy v1 sections like `<Data>` or `<Environment>`).
- Ensure no HTML tags; use Markdown for formatting.

Example cleaned XML for a sample app:

```xml
<?xml version="1.0"?>
<Container version="2">
<Name>idrac6</Name>
<Repository>domistyle/idrac6</Repository>
<Registry>https://hub.docker.com/r/domistyle/idrac6/</Registry>
<Network>bridge</Network>
<Privileged>false</Privileged>
<Support>https://github.com/DomiStyle/docker-idrac6/issues</Support>
<Project>https://github.com/DomiStyle/docker-idrac6/</Project>
<Overview>Allows access to the iDRAC 6 console without installing Java or messing with Java Web Start. Java is only run inside of the container and access is provided via web interface or directly with VNC.</Overview>
<Category>Tools: Network:Management</Category>
<WebUI>http://[IP]:[PORT:5800]</WebUI>
<Icon>https://raw.githubusercontent.com/user/repo/master/icon.png</Icon>
<ExtraParams/>
<PostArgs/>
<Config Name="idrac host" Target="IDRAC_HOST" Default="" Mode="" Description="Host for your iDRAC instance." Type="Variable" Display="always" Required="true" Mask="false"/>
<!-- Additional <Config> elements for other variables, ports, and paths -->
</Container>
```

## Step 2: Test the Template

- Install the container on your Unraid system using the template.
- Verify ports, volumes, and variables work as expected.
- Check for errors in CA's **Statistics** section (e.g., template errors or invalid templates).

## Step 3: Host the Template on GitHub

- Create a new GitHub repository (use "master" or "main" branch).
- Upload the XML file (name it descriptively, e.g., `my-app.xml`).
- Optionally, add a developer profile with `ca_profile.xml` in the repo root for enhanced visibility in CA searches.

Example `ca_profile.xml`:

```xml
<?xml version="1.0" encoding="utf-8"?>
<Maintainer>
<Icon>https://raw.githubusercontent.com/user/repo/master/avatar.jpg</Icon>
<Profile>Creating Docker containers with a focus on simplicity and auto-updates.</Profile>
<DonateLink>https://www.paypal.me/user</DonateLink>
<DonateText>Support my work with a donation.</DonateText>
<Forum>https://forums.unraid.net/topic/your-support-thread/</Forum>
</Maintainer>
```

## Step 4: Submit to Community Applications

1. Create a support thread on the Unraid forums.
2. Fill out the online submission form: [CA Submission Form](https://form.asana.com/?k=qtIUrf5ydiXvXzPI57BiJw\&d=714739274360802).
3. Provide your GitHub repo URL, support thread link, and other details.
4. Moderators review the submission (may request fixes). Approved templates appear in CA within \~2 hours.
5. For updates, push changes to GitHub; CA syncs automatically every 2 hours.
66 changes: 66 additions & 0 deletions docs/Developer/index.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
title: Developer Guide
description: Guide for creating and submitting apps and plugins to the Unraid Community Applications Store
sidebar_position: 1
---

import Card from '@site/src/components/Card';

Community Applications (CA) is a plugin for Unraid that provides a curated catalog of Docker containers (apps) and plugins. This guide explains how developers can create, test, and submit their own apps and plugins for inclusion in CA. Submissions are moderated to ensure safety, compatibility, and a positive user experience.

## Prerequisites

- Install the Community Applications plugin on your Unraid system via the **Plugins** tab in the Unraid web UI.
- Create a GitHub account and enable two-factor authentication (2FA) on your repositories—this is required for security.
- Create a support thread for your app or plugin on the Unraid forums (post in any relevant section; a moderator will move it to the appropriate forum, such as Docker Containers or Plugin Support).
- For Docker apps, enable **Docker Authoring Mode** in ***Settings → Docker*** (stop the Docker service first, enable Advanced View, toggle Authoring Mode, then restart the service).
- Familiarize yourself with CA policies at [CA Application Policies](https://forums.unraid.net/topic/87144-ca-application-policies/) to avoid rejection or blacklisting.

## 📚 Documentation Sections

<div style={{display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(250px, 1fr))', gap: '1rem'}}>
<Card title="Learn how to create & submit" icon="docker" href="./docker-apps">

Docker applications

</Card>

<Card title="Learn how to create & submit" icon="plugin" href="./plugins">

Unraid plugins

</Card>
</div>

## Update Process and Sync Frequency

CA maintains a centralized feed of approved apps and plugins, hosted at [https://raw.githubusercontent.com/Squidly271/AppFeed/master/applicationFeed.json](https://raw.githubusercontent.com/Squidly271/AppFeed/master/applicationFeed.json). This feed is aggregated from developer GitHub repositories and updated by moderators.

- **Sync Frequency**: CA checks and syncs with developer GitHub repositories approximately every 2 hours. Users can manually trigger a refresh in the CA interface via the **Refresh Apps** button (under the Apps tab) to pull the latest feed sooner.
- **Time for New Submissions to Appear**: After moderator approval (which can take from hours to days depending on review queue and any required fixes), the app or plugin typically becomes visible in the CA store within \~2 hours of feed update.
- **Time for Updates to Appear**: Once changes are pushed to your GitHub repository (e.g., XML updates, new versions), they propagate to the CA store within 2 hours during the next automated sync. If the update involves moderator review (e.g., significant changes to plugin code), expect additional delay for approval.
- **Local Caching**: Users' local CA instances cache the feed; manual refreshes or restarts may be needed to see updates immediately. In cases of issues (e.g., DNS or network problems), check diagnostics or forum support threads for troubleshooting.

For plugins, new submissions or major updates trigger a manual notification and code review by moderators like @Squid, which may extend timelines beyond the automated sync.

## Best Practices

- **Ports**: Reference container ports in WebUI (e.g., `[PORT:8080]`) for dynamic mapping.
- **Volumes**: Avoid host paths; use container paths to let users configure.
- **Environment Variables**: Provide defaults and clear descriptions; mask passwords.
- **Icons and Descriptions**: Use reliable URLs for icons; write concise, informative descriptions with Markdown.
- **Compatibility**: Include `<Requires>` for dependencies (e.g., hardware plugins).
- **Updates**: Set `<TemplateURL>false</TemplateURL>` in Docker XML to prevent auto-overwrites.
- **Security**: No HTML tags, no extra bash commands, no affiliate links.
- **Testing**: Use Authoring Mode; check CA Statistics for errors.
- **Uniqueness**: Avoid duplicates in saturated categories (e.g., media servers) unless offering unique features.

## Policies and Moderation

- All submissions must comply with CA policies: open-source preferred, no malicious code, 2FA required.
- Blacklisting occurs for violations (e.g., security issues, repository changes).
- Appeals: PM @Squid; escalate to @SpencerJ if needed.
- Abandoned apps/plugins may be removed without notice.
- For full details, see [CA Application Policies](https://forums.unraid.net/topic/87144-ca-application-policies/).

This documentation follows Unraid's style guide for clarity and structure. Submit updates or corrections via the Unraid forums or GitHub pull requests to relevant repos.
50 changes: 50 additions & 0 deletions docs/Developer/plugins.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: Plugins
description: Guide for developing & submitting Unraid plugins to the Community Applications Store
sidebar_position: 3
---

## Creating and Submitting Plugins

Plugins are `.plg` files (XML-based) that install software or features directly on Unraid. They have stricter moderation due to root access.

## Step 1: Create the Plugin PLG File

- PLG files define installation steps, such as downloading binaries, setting permissions, and integrating with the Unraid UI.
- Use an existing PLG as a template (e.g., from GitHub repos).

Example basic PLG structure:

```xml
<?xml version='1.0' standalone='yes'?>
<!DOCTYPE PLUGIN [
<!ENTITY name "MyPlugin">
<!ENTITY author "YourName">
<!ENTITY version "2025.10.18">
<!ENTITY pluginURL "https://github.com/user/repo">
<!ENTITY icon "plug">
]>
<PLUGIN name="&name;" author="&author;" version="&version;" pluginURL="&pluginURL;" icon="&icon;" min="6.12.0">
<DESCRIPTION>Short description of the plugin.</DESCRIPTION>
<CHANGES>Changelog here.</CHANGES>
<FILE Name="/boot/config/plugins/&name;/install.sh" Run="up">
<!-- Installation script content -->
</FILE>
<!-- Additional FILE elements for downloads, configs, etc. -->
</PLUGIN>
```

- Include scripts for installation, updates, and removal.
- Test on a local Unraid system by placing the `.plg` in `/config/plugins` on the flash drive and rebooting.

## Step 2: Host on GitHub

- Create a GitHub repo and upload the `.plg` file.
- Add `ca_profile.xml` if desired (same as for Docker apps).

## Step 3: Submit to Community Applications

- Plugins follow similar submission rules as Docker apps but are ineligible if better suited as Dockers.
- Create a support thread on the Unraid forums first.
- Submit your plugin via the official [Community Applications submission form](https://forums.unraid.net/topic/38582-plug-in-ca-application-addition-request/).
- Moderators review for security, openness (open-source preferred), and compatibility. Closed-source plugins are rarely accepted.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ The [forum announcement on counterfeit SanDisk drives](https://forums.unraid.net
:::
::::

:::

---

## Replacing your USB flash device
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Some users report intermittent issues with Time Machine and network shares on ma
:::
::::

:::

## Creating a Time Machine share

:::caution[Before you begin]
Expand Down
26 changes: 25 additions & 1 deletion src/components/Card/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,40 @@
import React, { CSSProperties } from 'react'; // CSSProperties allows inline styling with better type checking.
import React from 'react';
import clsx from 'clsx'; // clsx helps manage conditional className names in a clean and concise manner.
import Link from '@docusaurus/Link';

const Card = ({
className, // Custom classes for the container card
style, // Custom styles for the container card
children, // Content to be included within the card
shadow, // Used to add shadow under your card. Expected values are: low (lw), medium (md), tall (tl)
href, // Link URL for the card
title, // Title for the card header
icon, // Icon for the card header
}) => {
const cardShadow = shadow ? `item shadow--${shadow}` : '';

const Header = (title || icon) ? (
<div className="card__header">
{icon && <span className={`icon icon-${icon}`} aria-hidden="true"></span>}
{title && <h3 className="card__title">{title}</h3>}
</div>
) : null;

if (href) {
return (
<Link to={href} className={clsx('card', className, cardShadow)} style={style} aria-label={title}>
{Header}
{children}
</Link>
);
}
Comment on lines +23 to +30
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix undefined aria-label value.

If href is provided but title is not, the aria-label will be undefined, which degrades accessibility for screen reader users.

Apply this diff:

 if (href) {
   return (
-    <Link to={href} className={clsx('card', className, cardShadow)} style={style} aria-label={title}>
+    <Link to={href} className={clsx('card', className, cardShadow)} style={style} {...(title && { 'aria-label': title })}>
       {Header}
       {children}
     </Link>
   );
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (href) {
return (
<Link to={href} className={clsx('card', className, cardShadow)} style={style} aria-label={title}>
{Header}
{children}
</Link>
);
}
if (href) {
return (
<Link to={href} className={clsx('card', className, cardShadow)} style={style} {...(title && { 'aria-label': title })}>
{Header}
{children}
</Link>
);
}
🤖 Prompt for AI Agents
In src/components/Card/index.js around lines 23 to 30, the Link currently sets
aria-label={title} which becomes undefined when title is missing; update the JSX
to set aria-label to title if present, otherwise derive a fallback from the
children text or omit the attribute—e.g. set aria-label={title ?? (typeof
children === 'string' ? children : undefined)} so screen readers don’t receive
an undefined label.

🛠️ Refactor suggestion | 🟠 Major

🧩 Analysis chain

Verify Card usage doesn't create nested anchors.

When href is provided, the entire card becomes a Link. If children contain other links or interactive elements, this creates nested anchors (invalid HTML) and keyboard navigation issues. Verify that Card components with href don't wrap content containing links.


🏁 Script executed:

#!/bin/bash
# Search for Card usage with href that might contain nested links
# Look for patterns where Card has href and children might contain Link/a tags

echo "=== Searching for Card components with href prop ==="
rg -n --type=mdx --type=jsx --type=tsx -C 5 '<Card\s+[^>]*href=' || echo "No matches in mdx/jsx/tsx"

echo ""
echo "=== Searching for Card imports and usage patterns ==="
rg -n -A 10 "import.*Card.*from.*components/Card" 

echo ""
echo "=== Checking if Card children commonly include links ==="
ast-grep --pattern $'<Card $$$>
  $$$
  <Link $$$>$$$</Link>
  $$$
</Card>'

Length of output: 6998


Now I need to examine the actual Card implementation to verify the complete context:


Based on my comprehensive verification through web searches and codebase analysis:



**Reconsider Card implementation pattern when href is provided—current approach violates accessible card design.**

The current implementation wraps all Card content in a Link element when `href` is provided. This can result in the entire contents of the card being read out to screen reader users. Additionally, best practice is to not wrap the whole card with a link, and instead link your main distinctive piece of information and expand its hitbox with CSS, which offers a better experience when listing links and enables cards to contain other interactive elements. 

Use an overlay prop approach to make an entire component clickable as a link, ensuring proper accessibility with the Card component. Consider:
- Using a Link with `overlay` positioning instead of making it the root wrapper
- Limiting Card to only render content without `href` support, requiring users to compose navigation separately
- Applying a CSS pseudo-element approach for the clickable area without nesting structure

The current pattern creates nested link risks if children contain interactive elements, but the real issue is the implementation approach itself.

---

🏁 Script executed:

```shell
#!/bin/bash
# Retrieve the full Card component implementation
cat src/components/Card/index.js

Length of output: 1208


Refactor Card to use accessible link pattern instead of wrapping entire card in Link.

The current implementation wraps all Card content in a Link element when href is provided. This violates accessibility best practices: wrapping an entire card in a single <a> element causes screen reader users to hear all contents read as link text. Additionally, this pattern prevents the card from containing other interactive elements without creating nested anchors (invalid HTML).

Recommended approaches:

  • Remove href support entirely and require users to compose navigation separately (e.g., Card with Link inside)
  • Use overlay Link pattern: position the Link with overlay styling over the card without nesting content inside it, allowing other interactive elements
  • Link only primary content: link the card's title/header instead of the entire card, expanding its hitbox with CSS

Current codebase has no Card components using href, making this safe to refactor before establishing problematic usage patterns.

🤖 Prompt for AI Agents
In src/components/Card/index.js lines 23-30, the card currently wraps all
content in a Link when href is provided; stop wrapping the entire card in an
anchor. Instead render the card root as a non-link container regardless of href,
and when href is present render a separate Link element that uses the "overlay"
pattern (absolutely positioned, visually covers the card but does not wrap inner
content) or alternatively only wrap the title/header in a Link; keep className,
style and cardShadow on the root, ensure the overlay Link has an accessible
aria-label (from title) and does not contain other interactive children, and
update props/type docs to deprecate/warn about the old href behavior.


return (
<div className={clsx('card', className, cardShadow)} style={style}>
{Header}
{children}
</div>
);
};

export default Card;
Loading