diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..5e1922f1 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +**/node_modules +**/.next +/node_modules +/.next +node_modules +.next diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4122c1c3..25f2e1c4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,10 +42,22 @@ jobs: - name: Install dependencies run: pnpm install + - name: Build packages/common + run: | + cd ./packages/common + npm run build + cd ../.. + + - name: Install dependencies + run: pnpm install + + - name: Build packages + run: pnpm -r build + - name: Run global tests run: pnpm test - - name: Run tests + - name: Run linter run: pnpm -r lint - name: Run tests diff --git a/.github/workflows/release-candidate.yml b/.github/workflows/release-candidate.yml index 5a743b6d..9efada00 100644 --- a/.github/workflows/release-candidate.yml +++ b/.github/workflows/release-candidate.yml @@ -61,22 +61,13 @@ jobs: - name: Build and push dashboard uses: docker/build-push-action@v3 with: - context: ./packages/dashboard + context: . platforms: linux/amd64,linux/arm64,linux/arm/v7 push: true - tags: meienberger/tipi-dashboard:rc-${{ steps.meta.outputs.TAG }} - cache-from: type=registry,ref=meienberger/tipi-dashboard:buildcache - cache-to: type=registry,ref=meienberger/tipi-dashboard:buildcache,mode=max - - - name: Build and push api - uses: docker/build-push-action@v3 - with: - context: ./packages/system-api - platforms: linux/amd64,linux/arm64,linux/arm/v7 - push: true - tags: meienberger/tipi-api:rc-${{ steps.meta.outputs.TAG }} - cache-from: type=registry,ref=meienberger/tipi-api:buildcache - cache-to: type=registry,ref=meienberger/tipi-api:buildcache,mode=max + tags: meienberger/runtipi:rc-${{ steps.meta.outputs.TAG }} + cache-from: type=registry,ref=meienberger/runtipi:buildcache + cache-to: type=registry,ref=meienberger/runtipi:buildcache,mode=max + # Test installation script # test-install: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a922c2de..2b6ea110 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,16 +62,6 @@ jobs: context: ./packages/dashboard platforms: linux/amd64,linux/arm64,linux/arm/v7 push: true - tags: meienberger/tipi-dashboard:latest,meienberger/tipi-dashboard:${{ steps.meta.outputs.TAG }} - cache-from: type=registry,ref=meienberger/tipi-dashboard:buildcache - cache-to: type=registry,ref=meienberger/tipi-dashboard:buildcache,mode=max - - - name: Build and push api - uses: docker/build-push-action@v3 - with: - context: ./packages/system-api - platforms: linux/amd64,linux/arm64,linux/arm/v7 - push: true - tags: meienberger/tipi-api:latest,meienberger/tipi-api:${{ steps.meta.outputs.TAG }} - cache-from: type=registry,ref=meienberger/tipi-api:buildcache - cache-to: type=registry,ref=meienberger/tipi-api:buildcache,mode=max + tags: meienberger/runtipi:latest,meienberger/runtipi:${{ steps.meta.outputs.TAG }} + cache-from: type=registry,ref=meienberger/runtipi:buildcache + cache-to: type=registry,ref=meienberger/runtipi:buildcache,mode=max diff --git a/.gitignore b/.gitignore index 7950e42b..c1099946 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,4 @@ media/torrents/incomplete/* !media/torrents/incomplete/.gitkeep media/torrents/watch/* !media/torrents/watch/.gitkeep +packages/dashboard/package-lock.json diff --git a/packages/system-api/Dockerfile.dev b/Dockerfile similarity index 57% rename from packages/system-api/Dockerfile.dev rename to Dockerfile index 1af6d316..b4e80934 100644 --- a/packages/system-api/Dockerfile.dev +++ b/Dockerfile @@ -1,7 +1,24 @@ +FROM node:18-buster-slim AS build + +COPY ./packages/common /common + +WORKDIR /api +COPY ./packages/system-api/package.json /api/package.json +RUN npm i +COPY ./packages/system-api /api +RUN npm run build + +WORKDIR /dashboard +COPY ./packages/dashboard/package.json /dashboard/package.json +RUN npm i +COPY ./packages/dashboard /dashboard +RUN npm run build + + FROM ubuntu:20.04 ARG DEBIAN_FRONTEND=noninteractive -WORKDIR /app +WORKDIR / # Install docker RUN apt-get update && apt-get install -y \ @@ -22,15 +39,23 @@ RUN apt-get install -y docker-ce docker-ce-cli containerd.io # Install node RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - RUN apt-get install -y nodejs +RUN npm install --quiet node-gyp -g # Install docker-compose RUN curl -L "https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose RUN chmod +x /usr/local/bin/docker-compose -COPY ./package.json ./ +COPY ./packages/common /common -RUN npm install +WORKDIR /api +COPY ./packages/system-api/package.json /api/package.json +RUN npm install --omit=dev -COPY ./ ./ +WORKDIR /dashboard +COPY ./packages/dashboard/package.json /dashboard/package.json +RUN npm install --omit=dev -CMD ["npm", "run", "dev"] \ No newline at end of file +COPY --from=build /api /api +COPY --from=build /dashboard /dashboard + +WORKDIR / diff --git a/packages/system-api/Dockerfile b/Dockerfile.dev similarity index 76% rename from packages/system-api/Dockerfile rename to Dockerfile.dev index 639472c5..e5c4b8bb 100644 --- a/packages/system-api/Dockerfile +++ b/Dockerfile.dev @@ -1,7 +1,7 @@ FROM ubuntu:20.04 ARG DEBIAN_FRONTEND=noninteractive -WORKDIR /app +WORKDIR / # Install docker RUN apt-get update && apt-get install -y \ @@ -10,9 +10,6 @@ RUN apt-get update && apt-get install -y \ gnupg \ lsb-release -RUN apt-get install -y \ - g++ gcc make python - RUN curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg RUN echo \ @@ -25,18 +22,22 @@ RUN apt-get install -y docker-ce docker-ce-cli containerd.io # Install node RUN curl -sL https://deb.nodesource.com/setup_18.x | bash - RUN apt-get install -y nodejs -RUN npm install --quiet node-gyp -g # Install docker-compose RUN curl -L "https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose RUN chmod +x /usr/local/bin/docker-compose -COPY ./package.json ./ +COPY ./packages/common /common +WORKDIR /api +COPY ./packages/system-api/package.json /api/package.json RUN npm install -COPY ./ ./ +WORKDIR /dashboard +COPY ./packages/dashboard/package.json /dashboard/package.json +RUN npm install -RUN npm run build +COPY ./packages/system-api /api +COPY ./packages/dashboard /dashboard -CMD ["npm", "run", "start"] \ No newline at end of file +WORKDIR / diff --git a/README.md b/README.md index 720c4ecd..72e6596d 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,14 @@ [![License](https://img.shields.io/github/license/meienberger/runtipi)](https://github.com/meienberger/runtipi/blob/master/LICENSE) [![Version](https://img.shields.io/github/v/release/meienberger/runtipi?color=%235351FB&label=version)](https://github.com/meienberger/runtipi/releases) ![Issues](https://img.shields.io/github/issues/meienberger/runtipi) -[![Docker Pulls](https://badgen.net/docker/pulls/meienberger/tipi-dashboard?icon=docker&label=pulls)](https://hub.docker.com/r/meienberger/tipi-dashboard/) -[![Docker Image Size](https://badgen.net/docker/size/meienberger/tipi-dashboard?icon=docker&label=image%20size)](https://hub.docker.com/r/meienberger/tipi-dashboard/) +[![Docker Pulls](https://badgen.net/docker/pulls/meienberger/runtipi?icon=docker&label=pulls)](https://hub.docker.com/r/meienberger/tipi-dashboard/) +[![Docker Image Size](https://badgen.net/docker/size/meienberger/runtipi?icon=docker&label=image%20size)](https://hub.docker.com/r/meienberger/tipi-dashboard/) ![Build](https://github.com/meienberger/runtipi/workflows/Tipi%20CI/badge.svg) #### Join the discussion [![Discord](https://img.shields.io/discord/976934649643294750?label=discord&logo=discord)](https://discord.gg/Bu9qEPnHsc) [![Matrix](https://img.shields.io/matrix/runtipi:matrix.org?label=matrix&logo=matrix)](https://matrix.to/#/#runtipi:matrix.org) -![Preview](https://raw.githubusercontent.com/meienberger/runtipi/develop/screenshots/1.png) +![Preview](https://raw.githubusercontent.com/meienberger/runtipi/develop/screenshots/appstore.png) > ⚠️ Tipi is still at an early stage of development and issues are to be expected. Feel free to open an issue or pull request if you find a bug. Tipi is a personal homeserver orchestrator. It is running docker containers under the hood and provides a simple web interface to manage them. Every service comes with an opinionated configuration in order to remove the need for manual configuration and network setup. @@ -95,6 +95,7 @@ Tipi is licensed under the GNU General Public License v3.0. TL;DR — You may co - [Matrix](https://matrix.to/#/#runtipi:matrix.org)
- [Twitter](https://twitter.com/runtipi) - [Telegram](https://t.me/+72-y10MnLBw2ZGI0) +- [Discord](https://discord.gg/Bu9qEPnHsc) ## Contributors ✨ @@ -114,4 +115,4 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d -This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! \ No newline at end of file +This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg deleted file mode 100644 index 999d56da..00000000 --- a/ansible/ansible.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[defaults] -INVENTORY = hosts \ No newline at end of file diff --git a/ansible/host_vars/tipi.yml b/ansible/host_vars/tipi.yml deleted file mode 100644 index 041c2b8d..00000000 --- a/ansible/host_vars/tipi.yml +++ /dev/null @@ -1,4 +0,0 @@ -packages: - - jq - - coreutils - - docker diff --git a/ansible/hosts b/ansible/hosts deleted file mode 100644 index ec888a3c..00000000 --- a/ansible/hosts +++ /dev/null @@ -1,2 +0,0 @@ -[localhost] -tipi ansible_connection=local diff --git a/ansible/setup.yml b/ansible/setup.yml deleted file mode 100644 index 8b598ad0..00000000 --- a/ansible/setup.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -- hosts: tipi - become: yes - - tasks: - - import_tasks: ./tasks/common/essential.yml - - import_tasks: ./tasks/common/docker.yml - # - name: Reboot machine - # reboot: diff --git a/ansible/stop.yml b/ansible/stop.yml deleted file mode 100644 index 0227d34e..00000000 --- a/ansible/stop.yml +++ /dev/null @@ -1,6 +0,0 @@ ---- -- hosts: tipi - become: yes - - tasks: - - import_tasks: ./tasks/common/teardown.yml diff --git a/ansible/tasks/common/docker.yml b/ansible/tasks/common/docker.yml deleted file mode 100644 index d2fd2d6a..00000000 --- a/ansible/tasks/common/docker.yml +++ /dev/null @@ -1,67 +0,0 @@ -- name: Install docker - package: - name: - - docker - - ca-certificates - - curl - - gnupg - - lsb-release - state: latest - -- name: Check lsb_release -cs - shell: lsb_release -is - register: lsb_release - -- name: Add docker gpg key (Ubuntu) - shell: curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg - when: lsb_release.stdout == 'Ubuntu' - -- name: Add docker gpg key (Debian) - shell: curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg - when: lsb_release.stdout == 'Debian' - -- name: Add deb repo for docker (Ubuntu) - shell: echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null - when: lsb_release.stdout == 'Ubuntu' - -- name: Add deb repo for docker (Debian) - shell: echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null - when: lsb_release.stdout == 'Debian' - -- name: Update packages - apt: - update_cache: yes - upgrade: yes - -- name: Install essential packages - package: - name: - - docker-ce - - docker-ce-cli - - containerd.io - state: latest - -- name: Check if docker-compose is installed - stat: - path: /usr/local/bin/docker-compose - register: docker_compose_status - -- name: Install docker-compose - shell: 'curl -L "https://github.com/docker/compose/releases/download/v2.3.4/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose' - when: not docker_compose_status.stat.exists - -- name: Make docker-compose executable - shell: chmod +x /usr/local/bin/docker-compose - -- name: Create group docker - group: - name: docker - -- name: Put user in docker group - shell: usermod -aG docker {{ username }} - -- name: Start docker service - service: - enabled: yes - name: docker - state: started diff --git a/ansible/tasks/common/essential.yml b/ansible/tasks/common/essential.yml deleted file mode 100644 index cc0f8361..00000000 --- a/ansible/tasks/common/essential.yml +++ /dev/null @@ -1,33 +0,0 @@ -- name: Update packages - apt: - update_cache: yes - upgrade: yes - -- name: Install essential packages - package: - name: "{{ packages }}" - state: latest - -- name: Upgrade packages - apt: - upgrade: yes - -- name: Add user to root group - user: - name: "{{ username }}" - group: root - -- name: "Enable passwordless sudo for {{ username }}" - lineinfile: - dest: /etc/sudoers - regexp: "^%wheel" - line: "{{ username }} ALL=(ALL) NOPASSWD: ALL" - validate: "/usr/sbin/visudo -cf %s" - -- name: Create cron every minute running system-info.sh - cron: - name: "system-info" - user: "{{ username }}" - minute: "*/1" - job: "{{ playbook_dir }}/../scripts/system-info.sh" - ignore_errors: yes \ No newline at end of file diff --git a/ansible/tasks/common/teardown.yml b/ansible/tasks/common/teardown.yml deleted file mode 100644 index fb0c7850..00000000 --- a/ansible/tasks/common/teardown.yml +++ /dev/null @@ -1,18 +0,0 @@ -- name: Check if pm2 is installed - become_user: "{{ username }}" - stat: - path: /usr/local/bin/pm2 - register: pm2_status - -- name: Check if app is already running - become_user: "{{ username }}" - shell: pm2 list - register: pm2_result - when: pm2_status.stat.exists - -- name: Stop app - become_user: "{{ username }}" - shell: pm2 stop "system-api" - when: - - pm2_status.stat.exists - - pm2_result.stdout.find("system-api") != -1 diff --git a/ansible/tasks/network/avahi.yml b/ansible/tasks/network/avahi.yml deleted file mode 100644 index 1faa4ebb..00000000 --- a/ansible/tasks/network/avahi.yml +++ /dev/null @@ -1,44 +0,0 @@ -# Network -- name: Install avahi - package: - name: avahi - state: latest - when: ansible_os_family == "Arch" - -- name: Install avahi - package: - name: avahi-daemon - state: latest - when: ansible_os_family == "Debian" - -- name: Disable and stop sytemd-resolved - service: - name: systemd-resolved - state: stopped - enabled: no - -- name: Replace line in /etc/nsswitch.conf - lineinfile: - path: /etc/nsswitch.conf - regexp: '^hosts:.*' - line: 'hosts: mymachines mdns_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] files myhostname dns' - -- name: Allow port 5353 in UFW - community.general.ufw: - rule: allow - port: 5353 - proto: udp - -- name: Copy avahi template to /etc/avahi/services/tipi.service - copy: - src: "{{ playbook_dir }}/templates/avahi/tipi.service" - dest: /etc/avahi/services/tipi.service - group: avahi - owner: avahi - -- name: Start and enable avahi-daemon - service: - name: avahi-daemon - state: restarted - enabled: yes -### \ No newline at end of file diff --git a/ansible/templates/avahi/tipi.service b/ansible/templates/avahi/tipi.service deleted file mode 100644 index b6ae14be..00000000 --- a/ansible/templates/avahi/tipi.service +++ /dev/null @@ -1,16 +0,0 @@ - - - - %h - - _http._tcp - 80 - - - \ No newline at end of file diff --git a/apps/__tests__/apps.test.ts b/apps/__tests__/apps.test.ts index a2719e2d..19983292 100644 --- a/apps/__tests__/apps.test.ts +++ b/apps/__tests__/apps.test.ts @@ -58,6 +58,22 @@ describe("App configs", () => { }); }); + it("Each app should have a md description", () => { + const apps = getAppConfigs(); + + apps.forEach((app) => { + const path = `./apps/${app.id}/metadata/description.md`; + + if (fs.existsSync(path)) { + const description = fs.readFileSync(path).toString(); + expect(description).toBeDefined(); + } else { + console.error(`Missing description for app ${app.id}`); + expect(true).toBe(false); + } + }); + }); + it("Each app should have a name", () => { const apps = getAppConfigs(); diff --git a/apps/adguard/config.json b/apps/adguard/config.json index d251ea57..c3d1a059 100644 --- a/apps/adguard/config.json +++ b/apps/adguard/config.json @@ -3,12 +3,12 @@ "available": true, "port": 8104, "id": "adguard", + "categories": ["network", "security"], "description": "Adguard is the best way to get rid of annoying ads and online tracking and protect your computer from malware. Make your web surfing fast, safe and ad-free.", "short_desc": "World's most advanced adblocker!", - "author": "ArneNaessens", + "author": "AdguardTeam", "source": "https://github.com/AdguardTeam", - "image": "https://avatars.githubusercontent.com/u/8361145?s=200&v=4", - "cagegories": ["network", "security"], + "image": "/logos/apps/adguard.jpg", "requirements": { "ports": [53] }, diff --git a/apps/adguard/docker-compose.yml b/apps/adguard/docker-compose.yml index 9be29925..f5aeb613 100644 --- a/apps/adguard/docker-compose.yml +++ b/apps/adguard/docker-compose.yml @@ -2,7 +2,7 @@ version: "3.7" services: adguard: - image: adguard/adguardhome:v0.107.6 + image: adguard/adguardhome:v0.107.7 container_name: adguard volumes: - "${APP_DATA_DIR}/data/work:/opt/adguardhome/work" diff --git a/apps/adguard/metadata/description.md b/apps/adguard/metadata/description.md index b88c68d3..3efa30f5 100644 --- a/apps/adguard/metadata/description.md +++ b/apps/adguard/metadata/description.md @@ -1,3 +1,6 @@ -Network-wide ads & trackers blocking DNS server +## AdGuard Home is a network-wide software for blocking ads & tracking. -AdGuard Home is a network-wide software for blocking ads and tracking. After you set it up, it'll cover all your home devices, and you won't need any client-side software for that. Learn more on our official Github repository. +After you set it up, it'll cover ALL your home devices, and you don't need any client-side software for that. +It operates as a DNS server that re-routes tracking domains to a "black hole", thus preventing your devices from connecting to those servers. It's based on software we use for our public AdGuard DNS servers -- both share a lot of common code. + +![Screenshot](https://cdn.adguard.com/public/Adguard/Common/adguard_home.gif) diff --git a/apps/anonaddy/metadata/description.md b/apps/anonaddy/metadata/description.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/calibre-web/config.json b/apps/calibre-web/config.json index 6e19d314..6f03cc7c 100644 --- a/apps/calibre-web/config.json +++ b/apps/calibre-web/config.json @@ -3,10 +3,11 @@ "available": true, "port": 8100, "id": "calibre-web", + "categories": ["books"], "description": "On the initial setup screen, enter /books as your calibre library location. \n Default admin login: Username: admin Password: admin123", "short_desc": "Calibre-web is a web app providing a clean interface for browsing, reading and downloading eBooks using an existing Calibre database.", "author": "https://github.com/janeczku/", "source": "https://github.com/janeczku/calibre-web", - "image": "https://raw.githubusercontent.com/linuxserver/docker-templates/master/linuxserver.io/img/calibre-web-icon.png", + "image": "/logos/apps/calibre-web.jpg", "form_fields": {} } diff --git a/apps/calibre-web/metadata/description.md b/apps/calibre-web/metadata/description.md new file mode 100644 index 00000000..795e2a5b --- /dev/null +++ b/apps/calibre-web/metadata/description.md @@ -0,0 +1,7 @@ +Calibre-Web is a web app providing a clean interface for browsing, reading and downloading eBooks using a valid Calibre database. + +On the initial setup screen, enter /books as your calibre library location. + +- **username**: admin +- **password**: admin123 +
\ No newline at end of file diff --git a/apps/code-server/config.json b/apps/code-server/config.json index 1f106328..20039c48 100644 --- a/apps/code-server/config.json +++ b/apps/code-server/config.json @@ -3,6 +3,7 @@ "available": true, "port": 8101, "id": "code-server", + "categories": ["development"], "description": "", "short_desc": "Code-server is VS Code running on a remote server, accessible through the browser.", "author": "https://github.com/coder", diff --git a/apps/code-server/metadata/description.md b/apps/code-server/metadata/description.md new file mode 100644 index 00000000..abe472d8 --- /dev/null +++ b/apps/code-server/metadata/description.md @@ -0,0 +1,7 @@ +## Run VS Code on any machine anywhere and access it in the browser. + +- Code on any device with a consistent development environment +- Use cloud servers to speed up tests, compilations, downloads, and more +- Preserve battery life when you're on the go; all intensive tasks run on your server + +![screenshot](https://raw.githubusercontent.com/coder/code-server/main/docs/assets/screenshot.png) \ No newline at end of file diff --git a/apps/filebrowser/config.json b/apps/filebrowser/config.json index 243ce3e8..b05a3783 100644 --- a/apps/filebrowser/config.json +++ b/apps/filebrowser/config.json @@ -3,11 +3,12 @@ "available": true, "port": 8096, "id": "filebrowser", + "categories": ["utilities"], "description": "Reliable and Performant File Management Desktop Sync and File Sharing\n Default credentials: admin / admin", "short_desc": "Access your homeserver files from your browser", - "author": "", + "author": "filebrowser.org", "website": "https://filebrowser.org/", "source": "https://github.com/filebrowser/filebrowser", - "image": "https://avatars.githubusercontent.com/u/35781395?s=200&v=4", + "image": "/logos/apps/filebrowser.jpg", "form_fields": {} } diff --git a/apps/filebrowser/metadata/description.md b/apps/filebrowser/metadata/description.md new file mode 100644 index 00000000..3c7355e1 --- /dev/null +++ b/apps/filebrowser/metadata/description.md @@ -0,0 +1,12 @@ +## Access your homeserver files from your browser + +filebrowser provides a file managing interface within a specified directory and it can be used to upload, delete, preview, rename and edit your files. It allows the creation of multiple users and each user can have its own directory. It can be used as a standalone app. + +- **username**: admin +- **password**: admin +
+## Features + +Please refer to our docs at [https://filebrowser.org/features](https://filebrowser.org/features) + +![Preview](https://user-images.githubusercontent.com/5447088/50716739-ebd26700-107a-11e9-9817-14230c53efd2.gif) \ No newline at end of file diff --git a/apps/filerun/metadata/description.md b/apps/filerun/metadata/description.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/freshrss/config.json b/apps/freshrss/config.json index fefb6780..44c0f5da 100644 --- a/apps/freshrss/config.json +++ b/apps/freshrss/config.json @@ -3,10 +3,11 @@ "available": true, "port": 8086, "id": "freshrss", + "categories": ["utilities"], "description": "FreshRSS is a self-hosted RSS feed aggregator like Leed or Kriss Feed.\nIt is lightweight, easy to work with, powerful, and customizable.\n\nIt is a multi-user application with an anonymous reading mode. It supports custom tags. There is an API for (mobile) clients, and a Command-Line Interface.\n\nThanks to the WebSub standard (formerly PubSubHubbub), FreshRSS is able to receive instant push notifications from compatible sources, such as Mastodon, Friendica, WordPress, Blogger, FeedBurner, etc.\n\nFreshRSS natively supports basic Web scraping, based on XPath, for Web sites not providing any RSS / Atom feed.\n\nFinally, it supports extensions for further tuning.", "short_desc": "A free, self-hostable aggregator… ", "author": "https://freshrss.org/", "source": "https://github.com/FreshRSS/FreshRSS", - "image": "https://avatars.githubusercontent.com/u/9414285?s=200&v=4", + "image": "/logos/apps/freshrss.jpg", "form_fields": {} } diff --git a/apps/freshrss/metadata/description.md b/apps/freshrss/metadata/description.md new file mode 100644 index 00000000..bc58cde2 --- /dev/null +++ b/apps/freshrss/metadata/description.md @@ -0,0 +1,27 @@ + + +## A free, self-hostable aggregator… + +FreshRSS is a self-hosted RSS feed aggregator like [Leed](https://github.com/LeedRSS/Leed) or [Kriss Feed](https://tontof.net/kriss/feed/). + +It is lightweight, easy to work with, powerful, and customizable. + +It is a multi-user application with an anonymous reading mode. It supports custom tags. +There is an API for (mobile) clients, and a [Command-Line Interface](cli/README.md). + +Thanks to the [WebSub](https://www.w3.org/TR/websub/) standard (formerly [PubSubHubbub](https://github.com/pubsubhubbub/PubSubHubbub)), +FreshRSS is able to receive instant push notifications from compatible sources, such as [Mastodon](https://joinmastodon.org), [Friendica](https://friendi.ca), [WordPress](https://wordpress.org/plugins/pubsubhubbub/), Blogger, FeedBurner, etc. + +FreshRSS natively supports basic Web scraping, based on [XPath](https://www.w3.org/TR/xpath-10/), for Web sites not providing any RSS / Atom feed. + +Finally, it supports [extensions](#extensions) for further tuning. + +Feature requests, bug reports, and other contributions are welcome. The best way to contribute is to [open an issue on GitHub](https://github.com/FreshRSS/FreshRSS/issues). +We are a friendly community. + +* Official website: [website](https://freshrss.org) +* Demo: [Demo](https://demo.freshrss.org/) +* License: [GNU AGPL 3](https://www.gnu.org/licenses/agpl-3.0.html) + +![Screenshot](https://raw.githubusercontent.com/FreshRSS/FreshRSS/edge/docs/img/FreshRSS-screenshot.png) + diff --git a/apps/gitea/config.json b/apps/gitea/config.json index 7abec2a6..8c8b9843 100644 --- a/apps/gitea/config.json +++ b/apps/gitea/config.json @@ -3,10 +3,11 @@ "port": 8108, "available": true, "id": "gitea", + "categories": ["development"], "description": "Gitea is a painless self-hosted Git service. It is similar to GitHub, Bitbucket, and GitLab. Gitea is a fork of Gogs. See the Gitea Announcement blog post to read about the justification for a fork.", "short_desc": "Gitea - Git with a cup of tea · A painless self-hosted Git service. · Cross-platform · Easy to install · Lightweight · Open Source.", "author": "go-gitea", "source": "https://github.com/go-gitea/gitea", - "image": "https://avatars.githubusercontent.com/u/12724356?s=200&v=4", + "image": "/logos/apps/gitea.jpg", "form_fields": {} } diff --git a/apps/gitea/metadata/description.md b/apps/gitea/metadata/description.md new file mode 100644 index 00000000..9a52a06f --- /dev/null +++ b/apps/gitea/metadata/description.md @@ -0,0 +1,5 @@ +# A painless self-hosted Git service + +The goal of this project is to make the easiest, fastest, and most painless way of setting up a self-hosted Git service. Using Go, this can be done with an independent binary distribution across all platforms which Go supports, including Linux, macOS, and Windows on x86, amd64, ARM and PowerPC architectures. Want to try it before doing anything else? Do it with the online demo! This project has been forked from Gogs since 2016.11 but changed a lot. + +![Screenshot](https://camo.githubusercontent.com/134f49a62801ab393c211125515d108439c67b59befb2ec3e42e7235af4f5d6c/68747470733a2f2f646c2e67697465612e696f2f73637265656e73686f74732f686f6d655f74696d656c696e652e706e67) \ No newline at end of file diff --git a/apps/homarr/config.json b/apps/homarr/config.json index d859784e..888c7a5b 100644 --- a/apps/homarr/config.json +++ b/apps/homarr/config.json @@ -3,11 +3,12 @@ "available": true, "port": 8102, "id": "homarr", + "categories": ["utilities"], "description": "A homepage for your server.", "short_desc": "Homarr is a simple and lightweight homepage for your server, that helps you easily access all of your services in one place.", "author": "ajnart", "source": "https://github.com/ajnart/homarr", "website": "https://discord.gg/C2WTXkzkwK", - "image": "https://raw.githubusercontent.com/ajnart/homarr/master/public/imgs/logo.png", + "image": "/logos/apps/homarr.jpg", "form_fields": {} } diff --git a/apps/homarr/metadata/description.md b/apps/homarr/metadata/description.md new file mode 100644 index 00000000..88ddc31a --- /dev/null +++ b/apps/homarr/metadata/description.md @@ -0,0 +1,10 @@ +# Lightweight homepage for your server +Homarr is a simple and lightweight homepage for your server, that helps you easily access all of your services in one place. +It integrates with the services you use to display information on the homepage (E.g. Show upcoming Sonarr/Radarr releases). + +If you have any questions about Homarr or want to share information with us, please go to one of the following places: + +- [Github Discussions](https://github.com/ajnart/homarr/discussions) +- [Discord Server](https://discord.gg/aCsmEV5RgA) + +![Screenshot](https://user-images.githubusercontent.com/71191962/169860380-856634fb-4f41-47cb-ba54-6a9e7b3b9c81.gif) \ No newline at end of file diff --git a/apps/homeassistant/config.json b/apps/homeassistant/config.json index ef526f63..cbcaeb92 100644 --- a/apps/homeassistant/config.json +++ b/apps/homeassistant/config.json @@ -3,10 +3,11 @@ "available": true, "port": 8123, "id": "homeassistant", + "categories": ["automation"], "description": "Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server.", "short_desc": "Open source home automation that puts local control and privacy first", "author": "ArneNaessens", "source": "https://github.com/home-assistant/core", - "image": "https://avatars.githubusercontent.com/u/13844975?s=200&v=4", + "image": "/logos/apps/homeassistant.jpg", "form_fields": {} } diff --git a/apps/homeassistant/metadata/description.md b/apps/homeassistant/metadata/description.md new file mode 100644 index 00000000..b7b2a420 --- /dev/null +++ b/apps/homeassistant/metadata/description.md @@ -0,0 +1,7 @@ + +## Open source home automation that puts local control and privacy first + +Open source home automation that puts local control and privacy first. Powered by a worldwide community of tinkerers and DIY enthusiasts. Perfect to run on a Raspberry Pi or a local server. +Check out [home-assistant.io](https://home-assistant.io) for a [demo](https://home-assistant.io/demo/), installation [instructions](https://home-assistant.io/getting-started/), [tutorials](https://home-assistant.io/getting-started/automation/) and [documentation](https://home-assistant.io/docs/) + +![Screenshot](https://raw.githubusercontent.com/home-assistant/core/master/docs/screenshots.png) \ No newline at end of file diff --git a/apps/invidious/config.json b/apps/invidious/config.json index e0bcb97d..8ecc863a 100644 --- a/apps/invidious/config.json +++ b/apps/invidious/config.json @@ -3,6 +3,7 @@ "available": true, "port": 8095, "id": "invidious", + "categories": ["media", "social"], "description": "Invidious is an open source alternative front-end to YouTube.", "short_desc": "An alternative front-end to YouTube", "author": "iv-org", diff --git a/apps/invidious/docker-compose.arm.yml b/apps/invidious/docker-compose.arm.yml index e47850c9..50975e6b 100644 --- a/apps/invidious/docker-compose.arm.yml +++ b/apps/invidious/docker-compose.arm.yml @@ -43,3 +43,5 @@ services: POSTGRES_PASSWORD: tipi healthcheck: test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] + networks: + - tipi_main_network diff --git a/apps/invidious/docker-compose.yml b/apps/invidious/docker-compose.yml index 38ec9953..58380b6b 100644 --- a/apps/invidious/docker-compose.yml +++ b/apps/invidious/docker-compose.yml @@ -44,3 +44,5 @@ services: POSTGRES_PASSWORD: tipi healthcheck: test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"] + networks: + - tipi_main_network diff --git a/apps/invidious/metadata/description.md b/apps/invidious/metadata/description.md new file mode 100644 index 00000000..fae659e1 --- /dev/null +++ b/apps/invidious/metadata/description.md @@ -0,0 +1,27 @@ + +## An open source alternative front-end to YouTube + +**User features** +- Lightweight +- No ads +- No tracking +- No JavaScript required +- Light/Dark themes +- Customizable homepage +- Subscriptions independent from Google +- Notifications for all subscribed channels +- Audio-only mode (with background play on mobile) +- Support for Reddit comments +- Available in many languages, thanks to our translators +
+**Data import/export** +- Import subscriptions from YouTube, NewPipe and Freetube +- Import watch history from NewPipe +- Export subscriptions to NewPipe and Freetube +- Import/Export Invidious user data +
+**Technical features** +- Embedded video support +- [Developer API](https://docs.invidious.io/api/) +- Does not use official YouTube APIs +- No Contributor License Agreement (CLA) \ No newline at end of file diff --git a/apps/jackett/config.json b/apps/jackett/config.json index b88a1d17..805e5d7d 100644 --- a/apps/jackett/config.json +++ b/apps/jackett/config.json @@ -5,8 +5,9 @@ "id": "jackett", "description": "Jackett works as a proxy server: it translates queries from apps (Sonarr, Radarr, SickRage, CouchPotato, Mylar3, Lidarr, DuckieTV, qBittorrent, Nefarious etc.) into tracker-site-specific http queries, parses the html or json response, and then sends results back to the requesting software. This allows for getting recent uploads (like RSS) and performing searches.", "short_desc": "API Support for your favorite torrent trackers ", + "categories": ["media", "utilities"], "author": "", "source": "https://github.com/Jackett/Jackett", - "image": "https://avatars.githubusercontent.com/u/15383019?s=200&v=4", + "image": "/logos/apps/jackett.jpg", "form_fields": {} } diff --git a/apps/jackett/metadata/description.md b/apps/jackett/metadata/description.md new file mode 100644 index 00000000..7d2fce91 --- /dev/null +++ b/apps/jackett/metadata/description.md @@ -0,0 +1,5 @@ +## API Support for your favorite torrent trackers + +Jackett works as a proxy server: it translates queries from apps ([Sonarr](https://github.com/Sonarr/Sonarr), [Radarr](https://github.com/Radarr/Radarr), [SickRage](https://sickrage.github.io/), [CouchPotato](https://couchpota.to/), [Mylar3](https://github.com/mylar3/mylar3), [Lidarr](https://github.com/lidarr/lidarr), [DuckieTV](https://github.com/SchizoDuckie/DuckieTV), [qBittorrent](https://www.qbittorrent.org/), [Nefarious](https://github.com/lardbit/nefarious) etc.) into tracker-site-specific http queries, parses the html or json response, and then sends results back to the requesting software. This allows for getting recent uploads (like RSS) and performing searches. Jackett is a single repository of maintained indexer scraping & translation logic - removing the burden from other apps. + +![Screenshot](https://raw.githubusercontent.com/Jackett/Jackett/master/.github/jackett-screenshot1.png) \ No newline at end of file diff --git a/apps/jellyfin/config.json b/apps/jellyfin/config.json index 748bfc58..fc8592cd 100644 --- a/apps/jellyfin/config.json +++ b/apps/jellyfin/config.json @@ -3,6 +3,7 @@ "available": true, "port": 8091, "id": "jellyfin", + "categories": ["media"], "description": "Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. It is an alternative to the proprietary Emby and Plex, to provide media from a dedicated server to end-user devices via multiple apps. Jellyfin is descended from Emby's 3.5.2 release and ported to the .NET Core framework to enable full cross-platform support. There are no strings attached, no premium licenses or features, and no hidden agendas: just a team who want to build something better and work together to achieve it. We welcome anyone who is interested in joining us in our quest!", "short_desc": "A media server for your home collection", "author": "jellyfin.org", diff --git a/apps/jellyfin/metadata/description.md b/apps/jellyfin/metadata/description.md new file mode 100644 index 00000000..b280e86b --- /dev/null +++ b/apps/jellyfin/metadata/description.md @@ -0,0 +1,5 @@ +## A media server for your home collection + +Jellyfin is a Free Software Media System that puts you in control of managing and streaming your media. It is an alternative to the proprietary Emby and Plex, to provide media from a dedicated server to end-user devices via multiple apps. Jellyfin is descended from Emby's 3.5.2 release and ported to the .NET Core framework to enable full cross-platform support. There are no strings attached, no premium licenses or features, and no hidden agendas: just a team who want to build something better and work together to achieve it. We welcome anyone who is interested in joining us in our quest! + +For further details, please see [our documentation page](https://docs.jellyfin.org/). To receive the latest updates, get help with Jellyfin, and join the community, please visit [one of our communication channels](https://docs.jellyfin.org/general/getting-help.html). For more information about the project, please see our [about page](https://docs.jellyfin.org/general/about.html). \ No newline at end of file diff --git a/apps/joplin/config.json b/apps/joplin/config.json index ac66e4fb..c099eee1 100644 --- a/apps/joplin/config.json +++ b/apps/joplin/config.json @@ -3,11 +3,12 @@ "available": true, "port": 8099, "id": "joplin", + "categories": ["utilities"], "description": "Default credentials: admin@localhost / admin", "short_desc": "Note taking and to-do application with synchronisation", "author": "https://github.com/laurent22", "source": "https://github.com/laurent22/joplin", "website": "https://joplinapp.org", - "image": "https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/LinuxIcons/256x256.png", + "image": "/logos/apps/joplin.jpg", "form_fields": {} } diff --git a/apps/joplin/metadata/description.md b/apps/joplin/metadata/description.md new file mode 100644 index 00000000..c21b2807 --- /dev/null +++ b/apps/joplin/metadata/description.md @@ -0,0 +1,17 @@ +## Note taking and to-do application with synchronisation + +- **username**: admin@localhost +- **password**: admin +
+ +Joplin is a free, open source note taking and to-do application, which can handle a large number of notes organised into notebooks. The notes are searchable, can be copied, tagged and modified either from the applications directly or from your own text editor. The notes are in Markdown format. + +Notes exported from Evernote can be imported into Joplin, including the formatted content (which is converted to Markdown), resources (images, attachments, etc.) and complete metadata (geolocation, updated time, created time, etc.). Plain Markdown files can also be imported. + +The notes can be securely synchronised using end-to-end encryption with various cloud services including Nextcloud, Dropbox, OneDrive and Joplin Cloud. + +Full text search is available on all platforms to quickly find the information you need. The app can be customised using plugins and themes, and you can also easily create your own. + +The application is available for Windows, Linux, macOS, Android and iOS. A Web Clipper, to save web pages and screenshots from your browser, is also available for Firefox and Chrome. + +![Screenshot](https://raw.githubusercontent.com/laurent22/joplin/dev/Assets/WebsiteAssets/images/home-top-img.png) \ No newline at end of file diff --git a/apps/libreddit/config.json b/apps/libreddit/config.json index aa0a53f4..f2e6aad1 100644 --- a/apps/libreddit/config.json +++ b/apps/libreddit/config.json @@ -3,10 +3,11 @@ "available": true, "port": 8105, "id": "libreddit", + "categories": ["social"], "description": "LibReddit is a bloat free reddit frontend written in Rust, no ads, no tracking and strong Content Security Policy prevents any request from going to reddit, everything is proxied.", "short_desc": "Browse reddit without problems!", "author": "spikecodes", "source": "https://github.com/spikecodes/libreddit", - "image": "https://raw.githubusercontent.com/spikecodes/libreddit/master/static/logo.png", + "image": "/logos/apps/libreddit.jpg", "form_fields": {} } diff --git a/apps/libreddit/metadata/description.md b/apps/libreddit/metadata/description.md new file mode 100644 index 00000000..5925ab9a --- /dev/null +++ b/apps/libreddit/metadata/description.md @@ -0,0 +1,12 @@ +## An alternative private front-end to Reddit + + +**10 second pitch:** Libreddit is a portmanteau of "libre" (meaning freedom) and "Reddit". It is a private front-end like [Invidious](https://github.com/iv-org/invidious) but for Reddit. Browse the coldest takes of [r/unpopularopinion](https://libreddit.spike.codes/r/unpopularopinion) without being [tracked](#reddit). + +- 🚀 Fast: written in Rust for blazing-fast speeds and memory safety +- ☁️ Light: no JavaScript, no ads, no tracking, no bloat +- 🕵 Private: all requests are proxied through the server, including media +- 🔒 Secure: strong [Content Security Policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP) prevents browser requests to Reddit +
+ +![Screenshot](https://camo.githubusercontent.com/0753860e104fd86d32e13d47b31c8db88ec86bbdc66911480d92d20a96332c51/68747470733a2f2f692e6962622e636f2f515962715451742f6c69627265646469742d727573742e706e67) \ No newline at end of file diff --git a/apps/n8n/config.json b/apps/n8n/config.json index 6fedc838..180247ea 100644 --- a/apps/n8n/config.json +++ b/apps/n8n/config.json @@ -3,11 +3,12 @@ "available": true, "port": 8094, "id": "n8n", + "categories": ["automation"], "description": "n8n is an extendable workflow automation tool. With a fair-code distribution model, n8n will always have visible source code, be available to self-host, and allow you to add your own custom functions, logic and apps. n8n's node-based approach makes it highly versatile, enabling you to connect anything to everything.", "short_desc": "Workflow Automation Tool. Alternative to Zapier", "author": "n8n.io", "source": "https://github.com/n8n-io/n8n", "website": "https://n8n.io/", - "image": "https://avatars.githubusercontent.com/u/45487711?s=200&v=4", + "image": "/logos/apps/n8n.jpg", "form_fields": {} } diff --git a/apps/n8n/metadata/description.md b/apps/n8n/metadata/description.md new file mode 100644 index 00000000..810892f6 --- /dev/null +++ b/apps/n8n/metadata/description.md @@ -0,0 +1,6 @@ +## Easily automate tasks across different services. + +n8n is an extendable workflow automation tool. With a fair-code distribution model, n8n will always have visible source code, be available to self-host, and allow you to add your own custom functions, logic and apps. n8n's node-based approach makes it highly +versatile, enabling you to connect anything to everything. + +![Screenshot](https://raw.githubusercontent.com/n8n-io/n8n/master/assets/n8n-screenshot.png) \ No newline at end of file diff --git a/apps/nextcloud/config.json b/apps/nextcloud/config.json index 22fb6880..1d3c430a 100644 --- a/apps/nextcloud/config.json +++ b/apps/nextcloud/config.json @@ -3,6 +3,7 @@ "available": true, "port": 8083, "id": "nextcloud", + "categories": ["data"], "description": "Nextcloud is a self-hosted, open source, and fully-featured cloud storage solution for your personal files, office documents, and photos.", "short_desc": "Productivity platform that keeps you in control", "author": "Nextcloud GmbH", diff --git a/apps/nextcloud/metadata/description.md b/apps/nextcloud/metadata/description.md new file mode 100644 index 00000000..c8da741a --- /dev/null +++ b/apps/nextcloud/metadata/description.md @@ -0,0 +1,29 @@ +## A safe home for all your data. + +* 📁 **Access your Data** You can store your files, contacts, calendars and more on a server of your choosing. +* 🔄 **Sync your Data** You keep your files, contacts, calendars and more synchronized amongst your devices. +* 🙌 **Share your Data** …by giving others access to the stuff you want them to see or to collaborate with. +* 🚀 **Expandable with hundreds of Apps** ...like [Calendar](https://github.com/nextcloud/calendar), [Contacts](https://github.com/nextcloud/contacts), [Mail](https://github.com/nextcloud/mail), [Video Chat](https://github.com/nextcloud/spreed) and all those you can discover in our [App Store](https://apps.nextcloud.com) +* 🔒 **Security** with our encryption mechanisms, [HackerOne bounty program](https://hackerone.com/nextcloud) and two-factor authentication. + +You want to learn more about how you can use Nextcloud to access, share and protect your files, calendars, contacts, communication & more at home and at your organization? [**Learn about all our Features**](https://nextcloud.com/athome/). + +## Get your Nextcloud 🚚 + +- ☑️ [**Simply sign up**](https://nextcloud.com/signup/) at one of our providers either through our website or through the apps directly. +- 🖥 [**Install** a server by yourself](https://nextcloud.com/install/#instructions-server) on your own hardware or by using one of our ready to use **appliances** +- 📦 Buy one of the [awesome **devices** coming with a preinstalled Nextcloud](https://nextcloud.com/devices/) +- 🏢 Find a [service **provider**](https://nextcloud.com/providers/) who hosts Nextcloud for you or your company + +Enterprise? Public Sector or Education user? You may want to have a look into [**Nextcloud Enterprise**](https://nextcloud.com/enterprise/) provided by Nextcloud GmbH. + +## Get in touch 💬 + +* [📋 Forum](https://help.nextcloud.com) +* [👥 Facebook](https://www.facebook.com/nextclouders) +* [🐣 Twitter](https://twitter.com/Nextclouders) +* [🐘 Mastodon](https://mastodon.xyz/@nextcloud) + +You can also [get support for Nextcloud](https://nextcloud.com/support)! + +![](https://raw.githubusercontent.com/nextcloud/screenshots/master/files/Files%20Sharing.png) \ No newline at end of file diff --git a/apps/nitter/config.json b/apps/nitter/config.json index bcbd768a..1bacd383 100644 --- a/apps/nitter/config.json +++ b/apps/nitter/config.json @@ -3,10 +3,11 @@ "available": true, "port": 8106, "id": "nitter", + "categories": ["social"], "description": "A free and open source alternative Twitter front-end focused on privacy and performance.", "short_desc": "Twitter without annoyances!", "author": "zedeus", "source": "https://github.com/zedeus/nitter", - "image": "https://raw.githubusercontent.com/zedeus/nitter/master/public/favicon.ico", + "image": "/logos/apps/nitter.jpg", "form_fields": {} } diff --git a/apps/nitter/metadata/description.md b/apps/nitter/metadata/description.md new file mode 100644 index 00000000..091ddf59 --- /dev/null +++ b/apps/nitter/metadata/description.md @@ -0,0 +1,16 @@ +## Alternative Twitter front-end + +A free and open source alternative Twitter front-end focused on privacy and performance. Inspired by the [Invidious](https://github.com/iv-org/invidious) project. + +- No JavaScript or ads +- All requests go through the backend, client never talks to Twitter +- Prevents Twitter from tracking your IP or JavaScript fingerprint +- Uses Twitter's unofficial API (no rate limits or developer account required) +- Lightweight (for [@nim_lang](https://nitter.net/nim_lang), 60KB vs 784KB from twitter.com) +- RSS feeds +- Themes +- Mobile support (responsive design) +- AGPLv3 licensed, no proprietary instances permitted +
+ +![Screenshot](https://raw.githubusercontent.com/zedeus/nitter/master/screenshot.png) \ No newline at end of file diff --git a/apps/nodered/config.json b/apps/nodered/config.json index aefdfe89..a80606c4 100644 --- a/apps/nodered/config.json +++ b/apps/nodered/config.json @@ -3,6 +3,7 @@ "port": 8111, "available": true, "id": "nodered", + "categories": ["automation"], "description": "Node-RED is a programming tool for wiring together hardware devices, APIs and online services in new and interesting ways. It provides a browser-based editor that makes it easy to wire together flows using the wide range of nodes in the palette that can be deployed to its runtime in a single-click.", "short_desc": "Low-code programming for event-driven applications", "author": "node-red", diff --git a/apps/nodered/metadata/description.md b/apps/nodered/metadata/description.md new file mode 100644 index 00000000..af9ca0d7 --- /dev/null +++ b/apps/nodered/metadata/description.md @@ -0,0 +1,6 @@ +## Low-code programming for event-driven applications. + +Node-RED is a programming tool for wiring together hardware devices, APIs and online services in new and interesting ways. +It provides a browser-based editor that makes it easy to wire together flows using the wide range of nodes in the palette that can be deployed to its runtime in a single-click. + +![Screenshot](https://camo.githubusercontent.com/c7b6e0b937295c4d2c852130814050eb0caffac5b700ead6de21df6dbf83aa82/687474703a2f2f6e6f64657265642e6f72672f696d616765732f6e6f64652d7265642d73637265656e73686f742e706e67) \ No newline at end of file diff --git a/apps/photoprism/config.json b/apps/photoprism/config.json index b3aeb645..5b953c75 100644 --- a/apps/photoprism/config.json +++ b/apps/photoprism/config.json @@ -3,11 +3,12 @@ "port": 8110, "available": true, "id": "photoprism", + "categories": ["photography"], "description": "PhotoPrism® is an AI-Powered Photos App for the Decentralized Web. It makes use of the latest technologies to tag and find pictures automatically without getting in your way. You can run it at home, on a private server, or in the cloud. Default username: admin", "short_desc": "AI-Powered Photos App for the Decentralized Web. We are on a mission to protect your freedom and privacy.", "author": "PhotoPrism", "source": "https://github.com/photoprism/photoprism", - "image": "https://avatars.githubusercontent.com/u/32436079?s=200&v=4", + "image": "/logos/apps/photoprism.jpg", "form_fields": { "password": { "type": "password", diff --git a/apps/photoprism/metadata/description.md b/apps/photoprism/metadata/description.md new file mode 100644 index 00000000..f2fb525b --- /dev/null +++ b/apps/photoprism/metadata/description.md @@ -0,0 +1,9 @@ +## AI-Powered Photos App for the Decentralized Web 🌈💎✨ + +- **username**: admin +
+ +PhotoPrism® is an AI-Powered Photos App for the Decentralized Web. It makes use of the latest technologies to tag and find pictures automatically without getting in your way. You can run it at home, on a private server, or in the cloud. +To get a first impression, you are welcome to play with our [public demo](https://try.photoprism.app/). Be careful not to upload any private pictures. + +![Screenshot](https://camo.githubusercontent.com/5e03a87e47aad26ad7248b8b43eac6471fe96f7b655ac2e532697692753c3ff8/68747470733a2f2f646c2e70686f746f707269736d2e6170702f696d672f75692f6465736b746f702d3130303070782e6a7067) \ No newline at end of file diff --git a/apps/pihole/config.json b/apps/pihole/config.json index 29c8b903..35c19fdd 100644 --- a/apps/pihole/config.json +++ b/apps/pihole/config.json @@ -6,11 +6,12 @@ "ports": [53] }, "id": "pihole", + "categories": ["network", "security"], "description": "The Pi-hole® is a DNS sinkhole that protects your devices from unwanted content without installing any client-side software.", "short_desc": "A black hole for Internet advertisements", "author": "pi-hole.net", "source": "https://github.com/pi-hole/pi-hole", - "image": "https://avatars.githubusercontent.com/u/16827203?s=200&v=4", + "image": "/logos/apps/pihole.jpg", "form_fields": { "password": { "type": "password", diff --git a/apps/pihole/metadata/description.md b/apps/pihole/metadata/description.md new file mode 100644 index 00000000..5062451e --- /dev/null +++ b/apps/pihole/metadata/description.md @@ -0,0 +1,14 @@ +## A black hole for Internet advertisements + +The Pi-hole® is a [DNS sinkhole](https://en.wikipedia.org/wiki/DNS_Sinkhole) that protects your devices from unwanted content without installing any client-side software. + +- **Easy-to-install**: our versatile installer walks you through the process and takes less than ten minutes +- **Resolute**: content is blocked in _non-browser locations_, such as ad-laden mobile apps and smart TVs +- **Responsive**: seamlessly speeds up the feel of everyday browsing by caching DNS queries +- **Lightweight**: runs smoothly with [minimal hardware and software requirements](https://docs.pi-hole.net/main/prerequisites/) +- **Robust**: a command line interface that is quality assured for interoperability +- **Insightful**: a beautiful responsive Web Interface dashboard to view and control your Pi-hole +- **Versatile**: can optionally function as a [DHCP server](https://discourse.pi-hole.net/t/how-do-i-use-pi-holes-built-in-dhcp-server-and-why-would-i-want-to/3026), ensuring *all* your devices are protected automatically +- **Scalable**: [capable of handling hundreds of millions of queries](https://pi-hole.net/2017/05/24/how-much-traffic-can-pi-hole-handle/) when installed on server-grade hardware +- **Modern**: blocks ads over both IPv4 and IPv6 +- **Free**: open source software that helps ensure _you_ are the sole person in control of your privacy \ No newline at end of file diff --git a/apps/prowlarr/config.json b/apps/prowlarr/config.json index fd5cdef0..a98dcc2d 100644 --- a/apps/prowlarr/config.json +++ b/apps/prowlarr/config.json @@ -3,10 +3,11 @@ "available": true, "port": 8109, "id": "prowlarr", + "categories": ["media", "utilities"], "description": "Prowlarr is an indexer manager/proxy built on the popular *arr .net/reactjs base stack to integrate with your various PVR apps. Prowlarr supports management of both Torrent Trackers and Usenet Indexers. It integrates seamlessly with Lidarr, Mylar3, Radarr, Readarr, and Sonarr offering complete management of your indexers with no per app Indexer setup required (we do it all).", "short_desc": "A torrent/usenet indexer manager/proxy", "author": "Prowlarr", "source": "https://github.com/Prowlarr/Prowlarr/", - "image": "https://prowlarr.com/logo/256.png", + "image": "/logos/apps/prowlarr.jpg", "form_fields": {} } diff --git a/apps/prowlarr/metadata/description.md b/apps/prowlarr/metadata/description.md new file mode 100644 index 00000000..7a1fe674 --- /dev/null +++ b/apps/prowlarr/metadata/description.md @@ -0,0 +1,18 @@ +## A torrent/usenet indexer manager/proxy + +Prowlarr is an indexer manager/proxy built on the popular *arr .net/reactjs base stack to integrate with your various PVR apps. Prowlarr supports management of both Torrent Trackers and Usenet Indexers. It integrates seamlessly with Lidarr, Mylar3, Radarr, Readarr, and Sonarr offering complete management of your indexers with no per app Indexer setup required (we do it all). + +### Major Features Include + +- Usenet support for 24 indexers natively, including Headphones VIP +- Usenet support for any Newznab compatible indexer via "Generic Newznab" +- Torrent support for over 500 trackers with more added all the time +- Torrent support for any Torznab compatible tracker via "Generic Torznab" +- Support for custom YML definitions via Cardigann that includes JSON and XML parsing +- Indexer Sync to Lidarr/Mylar3/Radarr/Readarr/Sonarr, so no manual configuration of the other applications are required +- Indexer history and statistics +- Manual searching of Trackers & Indexers at a category level +- Parameter based manual searching +- Support for pushing multiple releases at once directly to your download clients from Prowlarr +- Indexer health and status notifications +- Per Indexer proxy support (SOCKS4, SOCKS5, HTTP, Flaresolverr) \ No newline at end of file diff --git a/apps/radarr/config.json b/apps/radarr/config.json index ae40742f..225ff5a1 100644 --- a/apps/radarr/config.json +++ b/apps/radarr/config.json @@ -3,10 +3,11 @@ "available": true, "port": 8088, "id": "radarr", + "categories": ["media", "utilities"], "description": "Radarr is a movie collection manager for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new movies and will interface with clients and indexers to grab, sort, and rename them. It can also be configured to automatically upgrade the quality of existing files in the library when a better quality format becomes available. Note that only one type of a given movie is supported. If you want both an 4k version and 1080p version of a given movie you will need multiple instances.", "short_desc": "Movie collection manager for Usenet and BitTorrent users.", "author": "radarr.video", "source": "https://github.com/Radarr/Radarr", - "image": "https://avatars.githubusercontent.com/u/25025331?s=200&v=4", + "image": "/logos/apps/radarr.jpg", "form_fields": {} } diff --git a/apps/radarr/metadata/description.md b/apps/radarr/metadata/description.md new file mode 100644 index 00000000..d68512b0 --- /dev/null +++ b/apps/radarr/metadata/description.md @@ -0,0 +1,23 @@ +## A fork of Sonarr to work with movies à la Couchpotato. + +Radarr is a movie collection manager for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new movies and will interface with clients and indexers to grab, sort, and rename them. It can also be configured to automatically upgrade the quality of existing files in the library when a better quality format becomes available. Note that only one type of a given movie is supported. If you want both an 4k version and 1080p version of a given movie you will need multiple instances. + +### Major Features Include + +* Adding new movies with lots of information, such as trailers, ratings, etc. +* Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc. +* Can watch for better quality of the movies you have and do an automatic upgrade. *e.g. from DVD to Blu-Ray* +* Automatic failed download handling will try another release if one fails +* Manual search so you can pick any release or to see why a release was not downloaded automatically +* Full integration with SABnzbd and NZBGet +* Automatically searching for releases as well as RSS Sync +* Automatically importing downloaded movies +* Recognizing Special Editions, Director's Cut, etc. +* Identifying releases with hardcoded subs +* Identifying releases with AKA movie names +* SABnzbd, NZBGet, QBittorrent, Deluge, rTorrent, Transmission, uTorrent, and other download clients are supported and integrated +* Full integration with Kodi and Plex (notifications, library updates) +* Importing Metadata such as trailers or subtitles +* Adding metadata such as posters and information for Kodi and others to use +* Advanced customization for profiles, such that Radarr will always download the copy you want +* A beautiful UI \ No newline at end of file diff --git a/apps/simple-torrent/metadata/description.md b/apps/simple-torrent/metadata/description.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/sonarr/config.json b/apps/sonarr/config.json index aa6dabd7..d6a0e113 100644 --- a/apps/sonarr/config.json +++ b/apps/sonarr/config.json @@ -3,10 +3,11 @@ "available": true, "port": 8098, "id": "sonarr", + "categories": ["media", "utilities"], "description": "Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available.", "short_desc": "TV show manager for Usenet and BitTorrent", "author": "sonarr.tv", "source": "https://github.com/Sonarr/Sonarr", - "image": "https://avatars.githubusercontent.com/u/1082903?s=200&v=4", + "image": "/logos/apps/sonarr.jpg", "form_fields": {} } diff --git a/apps/sonarr/metadata/description.md b/apps/sonarr/metadata/description.md new file mode 100644 index 00000000..bc10934e --- /dev/null +++ b/apps/sonarr/metadata/description.md @@ -0,0 +1,17 @@ +## Smart PVR for newsgroup and bittorrent users. + +Sonarr is a PVR for Usenet and BitTorrent users. It can monitor multiple RSS feeds for new episodes of your favorite shows and will grab, sort and rename them. It can also be configured to automatically upgrade the quality of files already downloaded when a better quality format becomes available. + +### Current Features + +- Support for major platforms: Windows, Linux, macOS, Raspberry Pi, etc. +- Automatically detects new episodes +- Can scan your existing library and download any missing episodes +- Can watch for better quality of the episodes you already have and do an automatic upgrade. *eg. from DVD to Blu-Ray* +- Automatic failed download handling will try another release if one fails +- Manual search so you can pick any release or to see why a release was not downloaded automatically +- Fully configurable episode renaming +- Full integration with SABnzbd and NZBGet +- Full integration with Kodi, Plex (notification, library update, metadata) +- Full support for specials and multi-episode releases +- And a beautiful UI \ No newline at end of file diff --git a/apps/syncthing/config.json b/apps/syncthing/config.json index a494435d..f7ce39b6 100644 --- a/apps/syncthing/config.json +++ b/apps/syncthing/config.json @@ -3,11 +3,12 @@ "available": true, "port": 8090, "id": "syncthing", + "categories": ["data", "utilities"], "description": "Syncthing is a peer-to-peer continuous file synchronization program. It synchronizes files between two or more computers in real time, safely protected from prying eyes. Your data is your data alone and you deserve to choose where it is stored, whether it is shared with some third party, and how it's transmitted over the internet.\n\nInstall the Syncthing app on your Umbrel and pair it with the Syncthing app on your phone or computer for a self hosted peer-to-peer backup solution.", "short_desc": "Peer-to-peer file synchronization between your devices", "author": "The Syncthing Foundation", "source": "https://github.com/syncthing", "website": "https://syncthing.net", - "image": "https://avatars.githubusercontent.com/u/7628018?s=200&v=4", + "image": "/logos/apps/syncthing.jpg", "form_fields": {} } diff --git a/apps/syncthing/metadata/description.md b/apps/syncthing/metadata/description.md new file mode 100644 index 00000000..39d27440 --- /dev/null +++ b/apps/syncthing/metadata/description.md @@ -0,0 +1,38 @@ +## Peer-to-peer file synchronization between your devices + +Syncthing is a continuous file synchronization program. It synchronizes files between two or more computers. We strive to fulfill the goals below. The goals are listed in order of importance, the most important one being the first. This is the summary version of the goal list - for more commentary, see the full Goals document. + +1. **Safe From Data Loss** + + Protecting the user's data is paramount. We take every reasonable + precaution to avoid corrupting the user's files. + +2. **Secure Against Attackers** + + Again, protecting the user's data is paramount. Regardless of our other + goals we must never allow the user's data to be susceptible to + eavesdropping or modification by unauthorized parties. + +3. **Easy to Use** + + Syncthing should be approachable, understandable and inclusive. + +4. **Automatic** + + User interaction should be required only when absolutely necessary. + +5. **Universally Available** + + Syncthing should run on every common computer. We are mindful that the + latest technology is not always available to any given individual. + +6. **For Individuals** + + Syncthing is primarily about empowering the individual user with safe, + secure and easy to use file synchronization. + +7. **Everything Else** + + There are many things we care about that don't make it on to the list. It + is fine to optimize for these values, as long as they are not in conflict + with the stated goals above. \ No newline at end of file diff --git a/apps/tailscale/config.json b/apps/tailscale/config.json index 6cddfdac..09861ddd 100644 --- a/apps/tailscale/config.json +++ b/apps/tailscale/config.json @@ -3,6 +3,7 @@ "available": true, "port": 8093, "id": "tailscale", + "categories": ["network", "security"], "description": "Zero config VPN. Installs on any device in minutes, manages firewall rules for you, and works from anywhere.", "short_desc": "The easiest, most secure way to use WireGuard and 2FA.", "author": "© Tailscale Inc.", diff --git a/apps/tailscale/metadata/description.md b/apps/tailscale/metadata/description.md new file mode 100644 index 00000000..1b4f17a3 --- /dev/null +++ b/apps/tailscale/metadata/description.md @@ -0,0 +1,7 @@ +## The easiest, most secure way to use WireGuard and 2FA. + +Zero config VPN. Installs on any device in minutes, manages firewall rules for you, and works from anywhere. +Create a secure network between your servers, computers, and cloud instances. Even when separated by firewalls or subnets, Tailscale just works. +Devices only connect after signing in through your existing identity provider. Easily enforce multi-factor authentication, deauthorize employees who’ve moved on, and more. + +![Screenshot](https://tailscale.com/static/images/marketing/home-illustration-2080w.webp) \ No newline at end of file diff --git a/apps/tautulli/config.json b/apps/tautulli/config.json index e502b183..0f703b02 100644 --- a/apps/tautulli/config.json +++ b/apps/tautulli/config.json @@ -3,10 +3,11 @@ "available": true, "port": 8181, "id": "tautulli", + "categories": ["media", "utilities"], "description": "Tautulli is a 3rd party application that you can run alongside your Plex Media Server to monitor activity and track various statistics. Most importantly, these statistics include what has been watched, who watched it, when and where they watched it, and how it was watched. The only thing missing is \"why they watched it\", but who am I to question your 42 plays of Frozen. All statistics are presented in a nice and clean interface with many tables and graphs, which makes it easy to brag about your server to everyone else.", - "short_desc": "A Python based monitoring and tracking tool for Plex Media Server.", + "short_desc": "Monitoring and tracking tool for Plex Media Server.", "author": "JonnyWong16", "source": "https://github.com/Tautulli/Tautulli", - "image": "https://tautulli.com/images/logo-circle.png", + "image": "/logos/apps/tautulli.jpg", "form_fields": {} } diff --git a/apps/tautulli/metadata/description.md b/apps/tautulli/metadata/description.md new file mode 100644 index 00000000..281a0661 --- /dev/null +++ b/apps/tautulli/metadata/description.md @@ -0,0 +1,19 @@ +## A Python based monitoring and tracking tool for Plex Media Server. + +- Responsive web design viewable on desktop, tablet and mobile web browsers. +- Themed to complement Plex/Web. +- Easy configuration setup (no separate web server required). +- Monitor current Plex Media Server activity. +- Fully customizable notifications for stream activity and recently added media. +- Top statistics on home page with configurable duration and measurement metric. +- Global watching history with search/filtering & dynamic column sorting. +- Full user list with general information and comparison stats. +- Individual user information including devices IP addresses. +- Complete library statistics and media file information. +- Rich analytics presented using Highcharts graphing. +- Beautiful content information pages. +- Full sync list data on all users syncing items from your library. +- And many more!! +
+ +![Screenshot](https://camo.githubusercontent.com/8e79a14ca41c16c2b1390fd3b3d686e90d5f1aaf2b466327f20d03fd123156cc/68747470733a2f2f74617574756c6c692e636f6d2f696d616765732f73637265656e73686f74732f61637469766974792d636f6d707265737365642e6a70673f763d32) \ No newline at end of file diff --git a/apps/transmission/config.json b/apps/transmission/config.json index e252a5c5..58d0f885 100644 --- a/apps/transmission/config.json +++ b/apps/transmission/config.json @@ -6,6 +6,7 @@ "ports": [51413] }, "id": "transmission", + "categories": ["utilities"], "description": "Transmission is a fast, easy, and free BitTorrent client.", "short_desc": "Fast, easy, and free BitTorrent client", "author": "Transmission Project", diff --git a/apps/transmission/metadata/description.md b/apps/transmission/metadata/description.md new file mode 100644 index 00000000..85bf1f8d --- /dev/null +++ b/apps/transmission/metadata/description.md @@ -0,0 +1,9 @@ +## Fast, easy, and free BitTorrent client + +Transmission is a fast, easy, and free BitTorrent client. It comes in several flavors: + * A native macOS GUI application + * GTK+ and Qt GUI applications for Linux, BSD, etc. + * A headless daemon for servers and routers + * A web UI for remote controlling any of the above + +Visit [https://transmissionbt.com/](https://transmissionbt.com/) for more information. \ No newline at end of file diff --git a/apps/ttyd/metadata/description.md b/apps/ttyd/metadata/description.md new file mode 100644 index 00000000..e69de29b diff --git a/apps/vaultwarden/config.json b/apps/vaultwarden/config.json index c4eecdbc..ef8443d0 100644 --- a/apps/vaultwarden/config.json +++ b/apps/vaultwarden/config.json @@ -3,11 +3,12 @@ "available": true, "port": 8107, "id": "vaultwarden", + "categories": ["utilities"], "description": "Alternative implementation of the Bitwarden server API written in Rust and compatible with upstream Bitwarden clients, perfect for self-hosted deployment where running the official resource-heavy service might not be ideal.", "short_desc": "All your passwords in your control!", "author": "Daniel García", "source": "https://github.com/dani-garcia/vaultwarden", - "image": "https://raw.githubusercontent.com/dani-garcia/vaultwarden/b636d20c6475bfb1b36561cb95812faee26ea7db/resources/vaultwarden-icon.svg", + "image": "/logos/apps/vaultwarden.jpg", "form_fields": { "admin_password": { "type": "password", diff --git a/apps/vaultwarden/metadata/description.md b/apps/vaultwarden/metadata/description.md new file mode 100644 index 00000000..30d146af --- /dev/null +++ b/apps/vaultwarden/metadata/description.md @@ -0,0 +1,13 @@ +## All your passwords in your control! + +Alternative implementation of the Bitwarden server API written in Rust and compatible with [upstream Bitwarden clients](https://bitwarden.com/download/), perfect for self-hosted deployment where running the official resource-heavy service might not be ideal. + +Basically full implementation of Bitwarden API is provided including: + + * Organizations support + * Attachments + * Vault API support + * Serving the static files for Vault interface + * Website icons API + * Authenticator and U2F support + * YubiKey and Duo support \ No newline at end of file diff --git a/apps/wg-easy/config.json b/apps/wg-easy/config.json index 4b90f8ab..bbacf634 100644 --- a/apps/wg-easy/config.json +++ b/apps/wg-easy/config.json @@ -6,11 +6,12 @@ "ports": [51820] }, "id": "wg-easy", + "categories": ["network"], "description": "Access your homeserver from anywhere even on your mobile device. Wireguard-easy is a simple tool to configure and manage Wireguard VPN servers. It is written in Go and uses the official Wireguard client. You have to open and redirect port 51820 to your homeserver in order to connect.", "short_desc": "VPN server for your homeserver", "author": "WeeJeWel", "source": "https://github.com/WeeJeWel/wg-easy/", - "image": "https://avatars.githubusercontent.com/u/13991055?s=200&v=4", + "image": "/logos/apps/wireguard.jpg", "form_fields": { "host": { "type": "fqdnip", diff --git a/apps/wg-easy/metadata/description.md b/apps/wg-easy/metadata/description.md new file mode 100644 index 00000000..b5378eaa --- /dev/null +++ b/apps/wg-easy/metadata/description.md @@ -0,0 +1,14 @@ +## The easiest way to run WireGuard VPN + Web-based Admin UI. + +You have found the easiest way to install & manage WireGuard on any Linux host! + +* All-in-one: WireGuard + Web UI. +* Easy installation, simple to use. +* List, create, edit, delete, enable & disable clients. +* Show a client's QR code. +* Download a client's configuration file. +* Statistics for which clients are connected. +* Tx/Rx charts for each connected client. +* Gravatar support. + +![Screenshot](https://raw.githubusercontent.com/WeeJeWel/wg-easy/master/assets/screenshot.png) \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 3f54b785..26e86f9b 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -3,8 +3,9 @@ version: "3.7" services: api: build: - context: ./packages/system-api + context: . dockerfile: Dockerfile.dev + command: bash -c "cd /api && npm run dev" container_name: api ports: - 3001:3001 @@ -12,8 +13,8 @@ services: ## Docker sock - /var/run/docker.sock:/var/run/docker.sock:ro - ${PWD}:/tipi - - ${PWD}/packages/system-api:/app - - /app/node_modules + - ${PWD}/packages/system-api:/api + - /api/node_modules environment: - INTERNAL_IP=${INTERNAL_IP} - TIPI_VERSION=${TIPI_VERSION} @@ -25,8 +26,9 @@ services: dashboard: build: - context: ./packages/dashboard + context: . dockerfile: Dockerfile.dev + command: bash -c "cd /dashboard && npm run dev" container_name: dashboard ports: - 3000:3000 @@ -35,8 +37,9 @@ services: environment: - INTERNAL_IP=${INTERNAL_IP} volumes: - - ${PWD}/packages/dashboard:/app - - /app/node_modules + - ${PWD}/packages/dashboard:/dashboard + - /dashboard/node_modules + - /dashboard/.next labels: traefik.enable: true traefik.http.routers.dashboard.rule: PathPrefix("/") # Host(`tipi.local`) && diff --git a/docker-compose.yml b/docker-compose.yml index 5868ef42..36becef0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -16,7 +16,8 @@ services: - tipi_main_network api: - image: meienberger/tipi-api:${TIPI_VERSION} + image: meienberger/runtipi:${TIPI_VERSION} + command: bash -c "cd /api && npm run start" restart: unless-stopped container_name: api ports: @@ -35,7 +36,8 @@ services: - tipi_main_network dashboard: - image: meienberger/tipi-dashboard:${TIPI_VERSION} + image: meienberger/runtipi:${TIPI_VERSION} + command: bash -c "cd /dasboard && npm run start" restart: unless-stopped container_name: dashboard ports: diff --git a/package.json b/package.json index 2df5a3e3..066829c2 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "act:docker": "act --container-architecture linux/amd64 --secret-file github.secrets -j build-images", "start:dev": "docker-compose -f docker-compose.dev.yml --env-file .env.dev up --build", "start:rc": "docker-compose -f docker-compose.rc.yml --env-file .env up --build", - "start:prod": "docker-compose --env-file .env up --build" + "start:prod": "docker-compose --env-file .env up --build", + "build:common": "cd packages/common && npm run build" }, "devDependencies": { "@types/jest": "^27.5.0", @@ -30,5 +31,6 @@ "bugs": { "url": "https://github.com/meienberger/runtipi/issues" }, - "homepage": "https://github.com/meienberger/runtipi#readme" + "homepage": "https://github.com/meienberger/runtipi#readme", + "dependencies": {} } diff --git a/packages/common/.eslintignore b/packages/common/.eslintignore new file mode 100644 index 00000000..c2f476d2 --- /dev/null +++ b/packages/common/.eslintignore @@ -0,0 +1,4 @@ +node_modules/ +dist/ +*.cjs +dist/ diff --git a/packages/common/.eslintrc.js b/packages/common/.eslintrc.js new file mode 100644 index 00000000..4c84277e --- /dev/null +++ b/packages/common/.eslintrc.js @@ -0,0 +1,18 @@ +module.exports = { + env: { node: true, jest: true }, + extends: ['airbnb-typescript', 'eslint:recommended', 'plugin:import/typescript'], + parser: '@typescript-eslint/parser', + parserOptions: { + project: './tsconfig.json', + tsconfigRootDir: __dirname, + ecmaVersion: 'latest', + sourceType: 'module', + }, + plugins: ['@typescript-eslint', 'import', 'react'], + rules: { + 'arrow-body-style': 0, + 'no-restricted-exports': 0, + 'max-len': [1, { code: 200 }], + 'import/extensions': ['error', 'ignorePackages', { js: 'never', jsx: 'never', ts: 'never', tsx: 'never' }], + }, +}; diff --git a/packages/common/.gitignore b/packages/common/.gitignore new file mode 100644 index 00000000..9ebfc2d9 --- /dev/null +++ b/packages/common/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +dist/ +coverage/ diff --git a/packages/common/.npmignore b/packages/common/.npmignore new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/packages/common/.npmignore @@ -0,0 +1 @@ + diff --git a/packages/common/.prettierrc.cjs b/packages/common/.prettierrc.cjs new file mode 100644 index 00000000..18502e8f --- /dev/null +++ b/packages/common/.prettierrc.cjs @@ -0,0 +1,6 @@ +module.exports = { + singleQuote: true, + semi: true, + trailingComma: 'all', + printWidth: 200, +}; diff --git a/packages/common/package.json b/packages/common/package.json new file mode 100644 index 00000000..3af329cb --- /dev/null +++ b/packages/common/package.json @@ -0,0 +1,23 @@ +{ + "name": "@runtipi/common", + "version": "0.2.8", + "main": "./dist/index.js", + "files": [ + "dist" + ], + "scripts": { + "test": "jest --coverage --passWithNoTests", + "build": "tsc -b tsconfig.build.json" + }, + "author": "", + "license": "ISC", + "devDependencies": { + "esbuild": "^0.14.38", + "typescript": "4.6.4" + }, + "dependencies": {}, + "description": "", + "publishConfig": { + "access": "public" + } +} diff --git a/packages/common/src/constants/app.constants.ts b/packages/common/src/constants/app.constants.ts new file mode 100644 index 00000000..0efc0b26 --- /dev/null +++ b/packages/common/src/constants/app.constants.ts @@ -0,0 +1,16 @@ +import { AppCategoriesEnum } from '../types'; + +// Icons should come from FontAwesome https://react-icons.github.io/react-icons/icons?name=fa +export const APP_CATEGORIES = [ + { name: 'Network', id: AppCategoriesEnum.NETWORK, icon: 'FaNetworkWired' }, + { name: 'Media', id: AppCategoriesEnum.MEDIA, icon: 'FaVideo' }, + { name: 'Development', id: AppCategoriesEnum.DEVELOPMENT, icon: 'FaCode' }, + { name: 'Automation', id: AppCategoriesEnum.AUTOMATION, icon: 'FaRobot' }, + { name: 'Social', id: AppCategoriesEnum.SOCIAL, icon: 'FaUserFriends' }, + { name: 'Utilities', id: AppCategoriesEnum.UTILITIES, icon: 'FaWrench' }, + { name: 'Photography', id: AppCategoriesEnum.PHOTOGRAPHY, icon: 'FaCamera' }, + { name: 'Security', id: AppCategoriesEnum.SECURITY, icon: 'FaShieldAlt' }, + { name: 'Featured', id: AppCategoriesEnum.FEATURED, icon: 'FaStar' }, + { name: 'Books', id: AppCategoriesEnum.BOOKS, icon: 'FaBook' }, + { name: 'Data', id: AppCategoriesEnum.DATA, icon: 'FaDatabase' }, +]; diff --git a/packages/common/src/constants/index.ts b/packages/common/src/constants/index.ts new file mode 100644 index 00000000..cd95e50a --- /dev/null +++ b/packages/common/src/constants/index.ts @@ -0,0 +1 @@ +export * from './app.constants'; diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts new file mode 100644 index 00000000..33c8572a --- /dev/null +++ b/packages/common/src/index.ts @@ -0,0 +1,2 @@ +export * from './types'; +export * from './constants'; diff --git a/packages/common/src/types/app.types.ts b/packages/common/src/types/app.types.ts new file mode 100644 index 00000000..2f110aa2 --- /dev/null +++ b/packages/common/src/types/app.types.ts @@ -0,0 +1,63 @@ +export enum AppCategoriesEnum { + NETWORK = 'network', + MEDIA = 'media', + DEVELOPMENT = 'development', + AUTOMATION = 'automation', + SOCIAL = 'social', + UTILITIES = 'utilities', + PHOTOGRAPHY = 'photography', + SECURITY = 'security', + FEATURED = 'featured', + BOOKS = 'books', + DATA = 'data', +} + +export enum FieldTypes { + text = 'text', + password = 'password', + email = 'email', + number = 'number', + fqdn = 'fqdn', + ip = 'ip', + fqdnip = 'fqdnip', + url = 'url', +} + +interface FormField { + type: FieldTypes; + label: string; + max?: number; + min?: number; + hint?: string; + required?: boolean; + env_variable: string; +} + +export enum AppStatusEnum { + RUNNING = 'running', + STOPPED = 'stopped', + INSTALLING = 'installing', + UNINSTALLING = 'uninstalling', + STOPPING = 'stopping', + STARTING = 'starting', +} + +export interface AppConfig { + id: string; + available: boolean; + port: number; + name: string; + requirements?: { + ports?: number[]; + }; + description: string; + version: string; + image: string; + form_fields: Record; + short_desc: string; + author: string; + source: string; + installed: boolean; + categories: AppCategoriesEnum[]; + status: AppStatusEnum; +} diff --git a/packages/common/src/types/index.ts b/packages/common/src/types/index.ts new file mode 100644 index 00000000..3758b427 --- /dev/null +++ b/packages/common/src/types/index.ts @@ -0,0 +1 @@ +export * from './app.types'; diff --git a/packages/common/tsconfig.build.json b/packages/common/tsconfig.build.json new file mode 100644 index 00000000..8ee9ef1e --- /dev/null +++ b/packages/common/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src", + "outDir": "./dist" + }, + "include": ["**/*.ts", "**/*.tsx"] +} diff --git a/packages/common/tsconfig.json b/packages/common/tsconfig.json new file mode 100644 index 00000000..904627e4 --- /dev/null +++ b/packages/common/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "es6", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": false, + "esModuleInterop": true, + "module": "commonjs", + "moduleResolution": "node", + "resolveJsonModule": true, + "isolatedModules": false, + "jsx": "preserve", + "incremental": false, + "declaration": true, + "outDir": "./dist" + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", "**/*.cjs", "jest.config.cjs"], + "exclude": ["node_modules", "dist"] +} diff --git a/packages/dashboard/.dockerignore b/packages/dashboard/.dockerignore index 22052075..57ff9714 100644 --- a/packages/dashboard/.dockerignore +++ b/packages/dashboard/.dockerignore @@ -1,2 +1,2 @@ node_modules/ -.next/ \ No newline at end of file +.next/ diff --git a/packages/dashboard/.eslintignore b/packages/dashboard/.eslintignore index 549416b1..fcca9768 100644 --- a/packages/dashboard/.eslintignore +++ b/packages/dashboard/.eslintignore @@ -1,3 +1,4 @@ *.config.js .eslintrc.js -next.config.js \ No newline at end of file +next.config.js +jest.config.js diff --git a/packages/dashboard/Dockerfile b/packages/dashboard/Dockerfile deleted file mode 100644 index 0eccf026..00000000 --- a/packages/dashboard/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM node:18-buster-slim - -WORKDIR /app - -COPY ./package.json ./ - -RUN npm install - -COPY ./ ./ - -RUN npm run build - -CMD ["npm", "run", "start"] \ No newline at end of file diff --git a/packages/dashboard/Dockerfile.dev b/packages/dashboard/Dockerfile.dev deleted file mode 100644 index 839143cd..00000000 --- a/packages/dashboard/Dockerfile.dev +++ /dev/null @@ -1,11 +0,0 @@ -FROM node:18-buster-slim - -WORKDIR /app - -COPY ./package.json ./ - -RUN yarn - -COPY ./ ./ - -CMD ["yarn", "dev"] \ No newline at end of file diff --git a/packages/dashboard/jest.config.js b/packages/dashboard/jest.config.js new file mode 100644 index 00000000..c14a6c36 --- /dev/null +++ b/packages/dashboard/jest.config.js @@ -0,0 +1,12 @@ +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ +module.exports = { + preset: 'ts-jest', + verbose: true, + // testEnvironment: 'node', + testMatch: ['**/__tests__/**/*.test.ts'], + // setupFiles: ['/tests/dotenv-config.ts'], + collectCoverage: true, + collectCoverageFrom: ['src/**/*.{ts,tsx}'], + coverageProvider: 'v8', + passWithNoTests: true, +}; diff --git a/packages/dashboard/next.config.js b/packages/dashboard/next.config.js index d2842ada..efdb715c 100644 --- a/packages/dashboard/next.config.js +++ b/packages/dashboard/next.config.js @@ -2,6 +2,13 @@ const { NODE_ENV, INTERNAL_IP } = process.env; const nextConfig = { + webpackDevMiddleware: (config) => { + config.watchOptions = { + poll: 1000, + aggregateTimeout: 300, + }; + return config; + }, reactStrictMode: true, env: { INTERNAL_IP: INTERNAL_IP, diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json index e4c45372..36bd956a 100644 --- a/packages/dashboard/package.json +++ b/packages/dashboard/package.json @@ -3,16 +3,18 @@ "version": "0.2.1", "private": true, "scripts": { + "test": "jest --colors", "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { - "@chakra-ui/react": "^2.0.2", + "@chakra-ui/react": "^2.1.2", "@emotion/react": "^11", "@emotion/styled": "^11", "@fontsource/open-sans": "^4.5.8", + "@runtipi/common": "file:../common", "axios": "^0.26.1", "clsx": "^1.1.1", "final-form": "^4.20.6", @@ -20,10 +22,17 @@ "immer": "^9.0.12", "js-cookie": "^3.0.1", "next": "12.1.6", + "npm": "^8.12.1", "react": "18.1.0", "react-dom": "18.1.0", "react-final-form": "^6.5.9", "react-icons": "^4.3.1", + "react-markdown": "^8.0.3", + "react-select": "^5.3.2", + "react-syntax-highlighter": "^15.5.0", + "remark-breaks": "^3.0.2", + "remark-gfm": "^3.0.1", + "remark-mdx": "^2.1.1", "swr": "^1.3.0", "systeminformation": "^5.11.9", "validator": "^13.7.0", @@ -35,14 +44,15 @@ "@types/node": "17.0.31", "@types/react": "18.0.8", "@types/react-dom": "18.0.3", + "@types/react-slick": "^0.23.8", "@types/validator": "^13.7.2", "@typescript-eslint/eslint-plugin": "^5.18.0", "@typescript-eslint/parser": "^5.0.0", - "eslint-plugin-import": "^2.25.3", "autoprefixer": "^10.4.4", "eslint": "8.12.0", "eslint-config-airbnb-typescript": "^17.0.0", "eslint-config-next": "12.1.4", + "eslint-plugin-import": "^2.25.3", "postcss": "^8.4.12", "tailwindcss": "^3.0.23", "typescript": "4.6.4" diff --git a/packages/dashboard/public/logos/apps/adguard.jpg b/packages/dashboard/public/logos/apps/adguard.jpg new file mode 100644 index 00000000..133d8f8d Binary files /dev/null and b/packages/dashboard/public/logos/apps/adguard.jpg differ diff --git a/apps/adguard/metadata/logo.png b/packages/dashboard/public/logos/apps/adguard.png similarity index 100% rename from apps/adguard/metadata/logo.png rename to packages/dashboard/public/logos/apps/adguard.png diff --git a/packages/dashboard/public/logos/apps/calibre-web.jpg b/packages/dashboard/public/logos/apps/calibre-web.jpg new file mode 100644 index 00000000..452d06c0 Binary files /dev/null and b/packages/dashboard/public/logos/apps/calibre-web.jpg differ diff --git a/packages/dashboard/public/logos/apps/filebrowser.jpg b/packages/dashboard/public/logos/apps/filebrowser.jpg new file mode 100644 index 00000000..36781399 Binary files /dev/null and b/packages/dashboard/public/logos/apps/filebrowser.jpg differ diff --git a/packages/dashboard/public/logos/apps/freshrss.jpg b/packages/dashboard/public/logos/apps/freshrss.jpg new file mode 100644 index 00000000..9f0c23a6 Binary files /dev/null and b/packages/dashboard/public/logos/apps/freshrss.jpg differ diff --git a/packages/dashboard/public/logos/apps/gitea.jpg b/packages/dashboard/public/logos/apps/gitea.jpg new file mode 100644 index 00000000..640652f5 Binary files /dev/null and b/packages/dashboard/public/logos/apps/gitea.jpg differ diff --git a/packages/dashboard/public/logos/apps/homarr.jpg b/packages/dashboard/public/logos/apps/homarr.jpg new file mode 100644 index 00000000..9f5cebd8 Binary files /dev/null and b/packages/dashboard/public/logos/apps/homarr.jpg differ diff --git a/packages/dashboard/public/logos/apps/homeassistant.jpg b/packages/dashboard/public/logos/apps/homeassistant.jpg new file mode 100644 index 00000000..e4466851 Binary files /dev/null and b/packages/dashboard/public/logos/apps/homeassistant.jpg differ diff --git a/packages/dashboard/public/logos/apps/jackett.jpg b/packages/dashboard/public/logos/apps/jackett.jpg new file mode 100644 index 00000000..eceab7e4 Binary files /dev/null and b/packages/dashboard/public/logos/apps/jackett.jpg differ diff --git a/packages/dashboard/public/logos/apps/joplin.jpg b/packages/dashboard/public/logos/apps/joplin.jpg new file mode 100644 index 00000000..d926c868 Binary files /dev/null and b/packages/dashboard/public/logos/apps/joplin.jpg differ diff --git a/packages/dashboard/public/logos/apps/libreddit.jpg b/packages/dashboard/public/logos/apps/libreddit.jpg new file mode 100644 index 00000000..14281a98 Binary files /dev/null and b/packages/dashboard/public/logos/apps/libreddit.jpg differ diff --git a/packages/dashboard/public/logos/apps/n8n.jpg b/packages/dashboard/public/logos/apps/n8n.jpg new file mode 100644 index 00000000..5e53b783 Binary files /dev/null and b/packages/dashboard/public/logos/apps/n8n.jpg differ diff --git a/packages/dashboard/public/logos/apps/nitter.jpg b/packages/dashboard/public/logos/apps/nitter.jpg new file mode 100644 index 00000000..ba58d3b0 Binary files /dev/null and b/packages/dashboard/public/logos/apps/nitter.jpg differ diff --git a/packages/dashboard/public/logos/apps/photoprism.jpg b/packages/dashboard/public/logos/apps/photoprism.jpg new file mode 100644 index 00000000..1310f32b Binary files /dev/null and b/packages/dashboard/public/logos/apps/photoprism.jpg differ diff --git a/packages/dashboard/public/logos/apps/pihole.jpg b/packages/dashboard/public/logos/apps/pihole.jpg new file mode 100644 index 00000000..6ec453b5 Binary files /dev/null and b/packages/dashboard/public/logos/apps/pihole.jpg differ diff --git a/packages/dashboard/public/logos/apps/prowlarr.jpg b/packages/dashboard/public/logos/apps/prowlarr.jpg new file mode 100644 index 00000000..2b4e9841 Binary files /dev/null and b/packages/dashboard/public/logos/apps/prowlarr.jpg differ diff --git a/packages/dashboard/public/logos/apps/radarr.jpg b/packages/dashboard/public/logos/apps/radarr.jpg new file mode 100644 index 00000000..e8b9a46b Binary files /dev/null and b/packages/dashboard/public/logos/apps/radarr.jpg differ diff --git a/packages/dashboard/public/logos/apps/sonarr.jpg b/packages/dashboard/public/logos/apps/sonarr.jpg new file mode 100644 index 00000000..fc3f7aac Binary files /dev/null and b/packages/dashboard/public/logos/apps/sonarr.jpg differ diff --git a/packages/dashboard/public/logos/apps/syncthing.jpg b/packages/dashboard/public/logos/apps/syncthing.jpg new file mode 100644 index 00000000..7564f5c1 Binary files /dev/null and b/packages/dashboard/public/logos/apps/syncthing.jpg differ diff --git a/packages/dashboard/public/logos/apps/tautulli.jpg b/packages/dashboard/public/logos/apps/tautulli.jpg new file mode 100644 index 00000000..b842dd23 Binary files /dev/null and b/packages/dashboard/public/logos/apps/tautulli.jpg differ diff --git a/packages/dashboard/public/logos/apps/vaultwarden.jpg b/packages/dashboard/public/logos/apps/vaultwarden.jpg new file mode 100644 index 00000000..5d4d32cd Binary files /dev/null and b/packages/dashboard/public/logos/apps/vaultwarden.jpg differ diff --git a/packages/dashboard/public/logos/apps/wireguard.jpg b/packages/dashboard/public/logos/apps/wireguard.jpg new file mode 100644 index 00000000..a7ea7aa1 Binary files /dev/null and b/packages/dashboard/public/logos/apps/wireguard.jpg differ diff --git a/packages/dashboard/src/components/AppLogo/AppLogo.tsx b/packages/dashboard/src/components/AppLogo/AppLogo.tsx new file mode 100644 index 00000000..68038585 --- /dev/null +++ b/packages/dashboard/src/components/AppLogo/AppLogo.tsx @@ -0,0 +1,16 @@ +import React from 'react'; + +const AppLogo: React.FC<{ src: string; size?: number; className?: string; alt?: string }> = ({ src, size = 80, className = '', alt = '' }) => { + return ( +
+ + + + + + +
+ ); +}; + +export default AppLogo; diff --git a/packages/dashboard/src/components/AppLogo/index.tsx b/packages/dashboard/src/components/AppLogo/index.tsx new file mode 100644 index 00000000..8c910ad9 --- /dev/null +++ b/packages/dashboard/src/components/AppLogo/index.tsx @@ -0,0 +1 @@ +export * from './AppLogo'; diff --git a/packages/dashboard/src/components/AppTile/AppStatus.tsx b/packages/dashboard/src/components/AppTile/AppStatus.tsx index e6266b73..0341562b 100644 --- a/packages/dashboard/src/components/AppTile/AppStatus.tsx +++ b/packages/dashboard/src/components/AppTile/AppStatus.tsx @@ -1,9 +1,9 @@ import React from 'react'; import { FiPauseCircle, FiPlayCircle } from 'react-icons/fi'; -import { AppStatus as TAppStatus } from '../../core/types'; +import { AppStatusEnum } from '@runtipi/common'; -const AppStatus: React.FC<{ status: TAppStatus }> = ({ status }) => { - if (status === 'running') { +const AppStatus: React.FC<{ status: AppStatusEnum }> = ({ status }) => { + if (status === AppStatusEnum.RUNNING) { return ( <> diff --git a/packages/dashboard/src/components/AppTile/index.tsx b/packages/dashboard/src/components/AppTile/index.tsx index b0b93de2..66aee9ae 100644 --- a/packages/dashboard/src/components/AppTile/index.tsx +++ b/packages/dashboard/src/components/AppTile/index.tsx @@ -1,9 +1,11 @@ -import { Box, SlideFade, Image, useColorModeValue } from '@chakra-ui/react'; +import { Box, SlideFade, useColorModeValue } from '@chakra-ui/react'; import Link from 'next/link'; import React from 'react'; import { FiChevronRight } from 'react-icons/fi'; -import { AppConfig } from '../../core/types'; +import { AppConfig } from '@runtipi/common'; import AppStatus from './AppStatus'; +import AppLogo from '../AppLogo/AppLogo'; +import { limitText } from '../../modules/AppStore/helpers/table.helpers'; const AppTile: React.FC<{ app: AppConfig }> = ({ app }) => { const bg = useColorModeValue('white', '#1a202c'); @@ -11,11 +13,11 @@ const AppTile: React.FC<{ app: AppConfig }> = ({ app }) => { return ( - - {`${app.name} + +

{app.name}

- {app.short_desc} + {limitText(app.short_desc, 50)} {app.installed && (
diff --git a/packages/dashboard/src/components/Form/validators.ts b/packages/dashboard/src/components/Form/validators.ts index cdba3603..09189155 100644 --- a/packages/dashboard/src/components/Form/validators.ts +++ b/packages/dashboard/src/components/Form/validators.ts @@ -1,5 +1,5 @@ import validator from 'validator'; -import { AppConfig, FieldTypes } from '../../core/types'; +import { AppConfig, FieldTypes } from '@runtipi/common'; const validateField = (field: AppConfig['form_fields'][0], value: string): string | undefined => { if (field.required && !value) { diff --git a/packages/dashboard/src/components/Layout/Menu.tsx b/packages/dashboard/src/components/Layout/Menu.tsx index bf177b7c..6f294ae6 100644 --- a/packages/dashboard/src/components/Layout/Menu.tsx +++ b/packages/dashboard/src/components/Layout/Menu.tsx @@ -1,5 +1,5 @@ import { AiOutlineDashboard, AiOutlineSetting, AiOutlineAppstore } from 'react-icons/ai'; -import { FaRegMoon } from 'react-icons/fa'; +import { FaAppStore, FaRegMoon } from 'react-icons/fa'; import { FiLogOut } from 'react-icons/fi'; import Package from '../../../package.json'; import { Box, Divider, Flex, List, ListItem, Switch, useColorMode } from '@chakra-ui/react'; @@ -45,7 +45,8 @@ const SideMenu: React.FC = () => { {renderMenuItem('Dashboard', '', AiOutlineDashboard)} - {renderMenuItem('Apps', 'apps', AiOutlineAppstore)} + {renderMenuItem('My Apps', 'apps', AiOutlineAppstore)} + {renderMenuItem('App Store', 'app-store', FaAppStore)} {renderMenuItem('Settings', 'settings', AiOutlineSetting)} diff --git a/packages/dashboard/src/components/Markdown/Markdown.tsx b/packages/dashboard/src/components/Markdown/Markdown.tsx new file mode 100644 index 00000000..1bb97474 --- /dev/null +++ b/packages/dashboard/src/components/Markdown/Markdown.tsx @@ -0,0 +1,32 @@ +import React from 'react'; +import ReactMarkdown from 'react-markdown'; +import remarkBreaks from 'remark-breaks'; +import remarkGfm from 'remark-gfm'; +import remarkMdx from 'remark-mdx'; + +const Markdown: React.FC<{ children: string; className: string }> = ({ children, className }) => { + return ( +

, + h2: (props) =>

, + h3: (props) =>

, + ul: (props) =>