From e72c7d8f7fef8d98ce7c56faa1840683f2f1cd3b Mon Sep 17 00:00:00 2001
From: CanbiZ <47820557+MickLesk@users.noreply.github.com>
Date: Sun, 18 Jan 2026 18:18:52 +0100
Subject: [PATCH] Update contribution docs for improved workflow and clarity
Revised multiple documentation files to clarify the recommended development workflow: contributors must test scripts via curl from their GitHub fork (not local bash), use setup-fork.sh for URL rewriting, and submit only new files using cherry-pick. Expanded and modernized install and JSON metadata template guides, emphasizing use of helper functions, resource requirements, and the JSON generator tool. Added detailed step-by-step instructions, best practices, and updated examples throughout.
---
docs/contribution/AI.md | 12 +-
docs/contribution/CONTRIBUTING.md | 54 +++-
docs/contribution/FORK_SETUP.md | 11 +-
docs/contribution/GUIDE.md | 59 +++-
docs/contribution/README.md | 115 ++++---
docs/contribution/templates_ct/AppName.md | 306 +++++++++---------
.../templates_install/AppName-install.md | 221 ++++++++++---
docs/contribution/templates_json/AppName.md | 140 +++++++-
8 files changed, 642 insertions(+), 276 deletions(-)
diff --git a/docs/contribution/AI.md b/docs/contribution/AI.md
index 49a2dfe17..0f4c7627d 100644
--- a/docs/contribution/AI.md
+++ b/docs/contribution/AI.md
@@ -168,9 +168,9 @@ cleanup_lxc
### Release Management
-| Function | Description | Example |
-| ----------------------------- | ----------------------------------- | --------------------------------------------------------- |
-| `fetch_and_deploy_gh_release` | Fetches and installs GitHub Release | `fetch_and_deploy_gh_release "app" "owner/repo"` |
+| Function | Description | Example |
+| ----------------------------- | ----------------------------------- | ------------------------------------------------------------- |
+| `fetch_and_deploy_gh_release` | Fetches and installs GitHub Release | `fetch_and_deploy_gh_release "app" "owner/repo"` |
| `check_for_gh_release` | Checks for new version | `if check_for_gh_release "app" "YourUsername/YourRepo"; then` |
**Modes for `fetch_and_deploy_gh_release`:**
@@ -816,7 +816,11 @@ Or no credentials:
1. **ALWAYS search `tools.func` first** before implementing custom solutions
2. **Use recent scripts as reference** (Thingsboard, UniFi OS, Trip, Flatnotes, etc.)
3. **Ask when uncertain** instead of introducing wrong patterns
-4. **Test locally** - try running scripts in test containers
+4. **Test via GitHub** - push to your fork and test with curl (not local bash)
+ ```bash
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
+ # Wait 10-30 seconds after pushing - GitHub takes time to update files
+ ```
5. **Consistency > Creativity** - follow established patterns strictly
6. **Check the templates** - they show the correct structure
7. **Don't wrap tools.func functions** - they handle their own msg_info/msg_ok output
diff --git a/docs/contribution/CONTRIBUTING.md b/docs/contribution/CONTRIBUTING.md
index 02eb9d24b..96d4dd23b 100644
--- a/docs/contribution/CONTRIBUTING.md
+++ b/docs/contribution/CONTRIBUTING.md
@@ -81,11 +81,22 @@ git clone https://github.com/yourUserName/ForkName
git switch -c your-feature-branch
```
-### 4. Change paths in build.func install.func and AppName.sh
+### 4. Run setup-fork.sh to auto-configure your fork
-To be able to develop from your own branch you need to change `https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main` to `https://raw.githubusercontent.com/[USER]/[REPOSITORY]/refs/heads/[BRANCH]`. You need to make this change atleast in misc/build.func misc/install.func and in your ct/AppName.sh. This change is only for testing. Before opening a Pull Request you should change this line change all this back to point to `https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main`.
+```bash
+bash docs/contribution/setup-fork.sh
+```
-### 4. Commit changes (without build.func and install.func!)
+This script automatically:
+
+- Detects your GitHub username
+- Updates ALL curl URLs to point to your fork (for testing)
+- Creates `.git-setup-info` with your config
+- Backs up all modified files (\*.backup)
+
+**IMPORTANT**: This modifies 600+ files! Use cherry-pick when submitting your PR (see below).
+
+### 5. Commit ONLY your new application files
```bash
git commit -m "Your commit message"
@@ -97,9 +108,42 @@ git commit -m "Your commit message"
git push origin your-feature-branch
```
-### 6. Create a Pull Request
+### 6. Cherry-Pick: Submit Only Your Files for PR
-Open a Pull Request from your feature branch to the main repository branch. You must only include your **$AppName.sh**, **$AppName-install.sh** and **$AppName.json** files in the pull request.
+⚠️ **IMPORTANT**: setup-fork.sh modified 600+ files. You MUST only submit your 3 new files!
+
+See [README.md - Cherry-Pick Guide](README.md#-cherry-pick-submitting-only-your-changes) for step-by-step instructions.
+
+Quick version:
+
+```bash
+# Create clean branch from upstream
+git fetch upstream
+git checkout -b submit/myapp upstream/main
+
+# Copy only your files
+cp ../your-work-branch/ct/myapp.sh ct/myapp.sh
+cp ../your-work-branch/install_scripts/myapp-install.sh install_scripts/myapp-install.sh
+cp ../your-work-branch/config/myapp.json config/myapp.json
+
+# Commit and verify
+git add ct/myapp.sh install_scripts/myapp-install.sh config/myapp.json
+git commit -m "feat: add MyApp"
+git diff upstream/main --name-only # Should show ONLY your 3 files
+
+# Push and create PR
+git push origin submit/myapp
+```
+
+### 7. Create a Pull Request
+
+Open a Pull Request from `submit/myapp` → `community-scripts/ProxmoxVE/main`.
+
+Verify the PR shows ONLY these 3 files:
+
+- `ct/myapp.sh`
+- `install_scripts/myapp-install.sh`
+- `config/myapp.json`
---
diff --git a/docs/contribution/FORK_SETUP.md b/docs/contribution/FORK_SETUP.md
index e2512356e..5993fbb67 100644
--- a/docs/contribution/FORK_SETUP.md
+++ b/docs/contribution/FORK_SETUP.md
@@ -38,14 +38,17 @@ source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxV
```
**WITHOUT setup-fork.sh:**
+
- Script URLs still point to `community-scripts/ProxmoxVE/main`
-- When you test `bash ct/myapp.sh` locally, it downloads from the **upstream** repo, not your changes
-- Your modifications aren't actually being tested! ❌
+- If you test locally with `bash ct/myapp.sh`, you're testing local files, but the script's curl commands would download from **upstream** repo
+- Your modifications aren't actually being tested via the curl commands! ❌
**AFTER setup-fork.sh:**
+
- Script URLs are updated to `YourUsername/ProxmoxVE/main`
-- When you test `bash ct/myapp.sh` locally, it downloads from **your fork**
-- You're actually testing your changes! ✅
+- When you test via curl from GitHub: `bash -c "$(curl ... YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"`, it downloads from **your fork**
+- The script's curl commands also point to your fork, so you're actually testing your changes! ✅
+- ⏱️ **Important:** GitHub takes 10-30 seconds to recognize pushed files - wait before testing!
```bash
# Example: What setup-fork.sh changes
diff --git a/docs/contribution/GUIDE.md b/docs/contribution/GUIDE.md
index e5a078b00..52d3bcc60 100644
--- a/docs/contribution/GUIDE.md
+++ b/docs/contribution/GUIDE.md
@@ -51,28 +51,29 @@ cat .git-setup-info
# 1. Create feature branch
git checkout -b add/my-awesome-app
-# 2. Create application scripts
-cp ct/example.sh ct/myapp.sh
-cp install/example-install.sh install/myapp-install.sh
+# 2. Create application scripts from templates
+cp docs/contribution/templates_ct/AppName.sh ct/myapp.sh
+cp docs/contribution/templates_install/AppName-install.sh install_scripts/myapp-install.sh
+cp docs/contribution/templates_json/AppName.json config/myapp.json
# 3. Edit your scripts
nano ct/myapp.sh
-nano install/myapp-install.sh
+nano install_scripts/myapp-install.sh
+nano config/myapp.json
-# 4. Test locally
-bash ct/myapp.sh # Will prompt for container creation
-
-# 5. Commit and push
-git add ct/myapp.sh install/myapp-install.sh
-git commit -m "feat: add MyApp container"
+# 4. Commit and push to your fork
+git add ct/myapp.sh install_scripts/myapp-install.sh config/myapp.json
+git commit -m "feat: add MyApp container and install scripts"
git push origin add/my-awesome-app
-# 6. Open Pull Request on GitHub
-# Click: New Pull Request (GitHub will show this automatically)
+# 5. Test via curl from your fork (GitHub may take 10-30 seconds)
+bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
-# 7. Keep your fork updated
-git fetch upstream
-git rebase upstream/main
+# 6. Use cherry-pick to submit only your files (see Cherry-Pick section)
+# DO NOT submit the 600+ files modified by setup-fork.sh!
+
+# 7. Open Pull Request on GitHub
+# Create PR from: your-fork/add/my-awesome-app → community-scripts/ProxmoxVE/main
```
**💡 Tip**: See `../FORK_SETUP.md` for detailed fork setup and troubleshooting
@@ -137,6 +138,7 @@ Examples:
```
**Rules**:
+
- Container script name: **Title Case** (PiHole, Docker, NextCloud)
- Install script name: **lowercase** with **hyphens** (pihole-install, docker-install)
- Must match: `ct/AppName.sh` ↔ `install/appname-install.sh`
@@ -156,6 +158,7 @@ Examples:
- Ubuntu 20.04 / Debian 11+ on host
2. **Git** installed
+
```bash
apt-get install -y git
```
@@ -241,18 +244,21 @@ bash -n install/myapp-install.sh
### Step 1: Choose Your Template
**For Simple Web Apps** (Node.js, Python, PHP):
+
```bash
cp ct/example.sh ct/myapp.sh
cp install/example-install.sh install/myapp-install.sh
```
**For Database Apps** (PostgreSQL, MongoDB):
+
```bash
cp ct/docker.sh ct/myapp.sh # Use Docker container
# OR manual setup for more control
```
**For Alpine Linux Apps** (lightweight):
+
```bash
# Use ct/alpine.sh as reference
# Edit install script to use Alpine packages (apk not apt)
@@ -317,6 +323,7 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}:PORT${CL}"
```
**Checklist**:
+
- [ ] APP variable matches filename
- [ ] var_tags semicolon-separated (no spaces)
- [ ] Realistic CPU/RAM/disk values
@@ -370,6 +377,7 @@ cleanup_lxc
```
**Checklist**:
+
- [ ] Functions loaded from `$FUNCTIONS_FILE_PATH`
- [ ] All installation phases present (deps, tools, app, config, cleanup)
- [ ] Using `$STD` for output suppression
@@ -774,16 +782,19 @@ Use this template:
```markdown
## Description
+
Brief description of what this PR adds/fixes
## Type of Change
+
- [ ] New application (ct/AppName.sh + install/appname-install.sh)
- [ ] Update existing application
- [ ] Bug fix
- [ ] Documentation update
-- [ ] Other: _______
+- [ ] Other: **\_\_\_**
## Testing
+
- [ ] Tested on Proxmox VE 8.x
- [ ] Container creation successful
- [ ] Application installation successful
@@ -792,6 +803,7 @@ Brief description of what this PR adds/fixes
- [ ] No temporary files left after installation
## Application Details (for new apps only)
+
- **App Name**: MyApp
- **Source**: https://github.com/app/repo
- **Default OS**: Debian 12
@@ -800,6 +812,7 @@ Brief description of what this PR adds/fixes
- **Access URL**: http://IP:PORT/path
## Checklist
+
- [ ] My code follows the style guidelines
- [ ] I have performed a self-review
- [ ] I have tested the script locally
@@ -811,6 +824,7 @@ Brief description of what this PR adds/fixes
### Step 5: Respond to Review Comments
**Maintainers may request changes**:
+
- Fix syntax/style issues
- Add better error handling
- Optimize resource usage
@@ -922,6 +936,7 @@ pct exec CTID netstat -tlnp | grep LISTEN
### Q: Can I test without a Proxmox system?
**A**: Partially. You can verify syntax and ShellCheck compliance locally, but real container testing requires Proxmox. Consider using:
+
- Proxmox in a VM (VirtualBox/KVM)
- Test instances on Hetzner/DigitalOcean
- Ask maintainers to test for you
@@ -929,6 +944,7 @@ pct exec CTID netstat -tlnp | grep LISTEN
### Q: My update function is very complex - is that OK?
**A**: Yes! Update functions can be complex if needed. Just ensure:
+
- Backup user data before updating
- Restore user data after update
- Test thoroughly before submitting
@@ -937,6 +953,7 @@ pct exec CTID netstat -tlnp | grep LISTEN
### Q: Can I add new dependencies to build.func?
**A**: Generally no. build.func is the orchestrator and should remain stable. New functions should go in:
+
- `tools.func` - Tool installation
- `core.func` - Utility functions
- `install.func` - Container setup
@@ -948,11 +965,13 @@ Ask in an issue first if you're unsure.
**A**: You have options:
**Option 1**: Use Advanced mode (19-step wizard)
+
```bash
# Extend advanced_settings() if app needs special vars
```
**Option 2**: Create custom setup menu
+
```bash
function custom_config() {
OPTION=$(whiptail --inputbox "Enter database name:" 8 60)
@@ -961,6 +980,7 @@ function custom_config() {
```
**Option 3**: Leave as defaults + documentation
+
```bash
# In success message:
echo "Edit /opt/myapp/config.json to customize settings"
@@ -969,9 +989,10 @@ echo "Edit /opt/myapp/config.json to customize settings"
### Q: Can I contribute Windows/macOS/ARM support?
**A**:
+
- **Windows**: Not planned (ProxmoxVE is Linux/Proxmox focused)
- **macOS**: Can contribute Docker-based alternatives
-- **ARM**: Yes! Many apps work on ARM. Add to vm/pimox-*.sh scripts
+- **ARM**: Yes! Many apps work on ARM. Add to vm/pimox-\*.sh scripts
---
@@ -995,6 +1016,7 @@ echo "Edit /opt/myapp/config.json to customize settings"
### Report Bugs
When reporting bugs, include:
+
- Which application
- What happened (error message)
- What you expected
@@ -1002,6 +1024,7 @@ When reporting bugs, include:
- Container OS and version
Example:
+
```
Title: pihole-install.sh fails on Alpine 3.20
@@ -1025,6 +1048,7 @@ Error Output:
## Contribution Statistics
**ProxmoxVE by the Numbers**:
+
- 🎯 40+ applications supported
- 👥 100+ contributors
- 📊 10,000+ GitHub stars
@@ -1038,6 +1062,7 @@ Error Output:
## Code of Conduct
By contributing, you agree to:
+
- ✅ Be respectful and inclusive
- ✅ Follow the style guidelines
- ✅ Test your changes thoroughly
diff --git a/docs/contribution/README.md b/docs/contribution/README.md
index ec81db7a3..1e6c2c1fd 100644
--- a/docs/contribution/README.md
+++ b/docs/contribution/README.md
@@ -45,17 +45,18 @@ cp docs/contribution/templates_ct/AppName.sh ct/myapp.sh
cp docs/contribution/templates_install/AppName-install.sh install/myapp-install.sh
# ... edit files ...
-# 7. Test locally (in your fork before PR)
-bash ct/myapp.sh
-# ⚠️ Important: Always use `bash ct/myapp.sh`, NOT `./ct/myapp.sh`
+# 7. Push to your fork and test via GitHub
+git push origin feature/my-awesome-app
+bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
+# ⏱️ GitHub may take 10-30 seconds to update files - be patient!
# 8. Create your JSON metadata file
cp docs/contribution/templates_json/AppName.json frontend/public/json/myapp.json
# Edit metadata: name, slug, categories, description, resources, etc.
-# 9. Test locally (in your fork before PR)
-bash ct/myapp.sh
-# ⚠️ Important: Always use `bash ct/myapp.sh`, NOT `./ct/myapp.sh`
+# 9. Test the install script (if you created one)
+bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/install_scripts/myapp-install.sh)"
+# ⏱️ GitHub may take 10-30 seconds to update files - be patient!
# 10. Commit ONLY your new files (see Cherry-Pick section below!)
git add ct/myapp.sh install/myapp-install.sh frontend/public/json/myapp.json
@@ -84,15 +85,18 @@ bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/Proxmo
### Development vs. Production Execution
**During Development (you, in your fork):**
-```bash
-# You test locally with your cloned files
-bash ct/myapp.sh
-# The script's curl commands are updated by setup-fork.sh to pull from YOUR fork
+```bash
+# You MUST test via curl from your GitHub fork (not local files!)
+bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
+
+# The script's curl commands are updated by setup-fork.sh to point to YOUR fork
# This ensures you're testing your actual changes
+# ⏱️ Wait 10-30 seconds after pushing - GitHub updates slowly
```
**After Merge (users, from GitHub):**
+
```bash
# Users download the script from upstream via curl
bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/myapp.sh)"
@@ -102,8 +106,9 @@ bash -c "$(curl -fsSL https://raw.githubusercontent.com/community-scripts/Proxmo
```
**Summary:**
-- **Development**: `bash ct/myapp.sh` (local clone) → setup-fork.sh changes curl URLs to your fork
-- **Production**: `curl | bash` from upstream → curl URLs point to community-scripts repo
+
+- **Development**: Push to fork, test via curl → setup-fork.sh changes curl URLs to your fork
+- **Production**: curl | bash from upstream → curl URLs point to community-scripts repo
---
@@ -137,8 +142,10 @@ Without running this script, all links in your fork will still point to the upst
Your fork is fully configured and ready to develop. You can:
-- Test changes locally with `bash ct/myapp.sh`
+- Push changes to your fork
+- Test via curl: `bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"`
- All links will reference your fork for development
+- ⏱️ Wait 10-30 seconds after pushing - GitHub takes time to update
- Commit and push with confidence
- Create a PR to merge into upstream
@@ -185,7 +192,7 @@ All scripts and configurations must follow our coding standards to ensure consis
- ✅ Include proper shebang: `#!/usr/bin/env bash`
- ✅ Add copyright header with author
- ✅ Handle errors properly with `msg_error`, `msg_ok`, etc.
-- ✅ Test before submitting PR
+- ✅ Test before submitting PR (via curl from your fork, not local bash)
- ✅ Update documentation if needed
---
@@ -357,7 +364,11 @@ If you're using **Visual Studio Code** with an AI assistant, you can leverage ou
- **Templates Location**: `docs/contribution/templates_ct/AppName.sh`, `templates_install/`, `templates_json/`
- **Guidelines**: Must follow `docs/contribution/AI.md` exactly
- **Helper Functions**: Use only functions from `misc/tools.func` - never write custom ones
-- **Testing**: Always include `bash ct/myapp.sh` testing before submission
+- **Testing**: Always test before submission via curl from your fork
+ ```bash
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
+ # Wait 10-30 seconds after pushing changes
+ ```
- **No Docker**: Container scripts must be bare-metal, not Docker-based
### Benefits
@@ -455,11 +466,12 @@ git push origin feature/my-feature
git rebase upstream/main
```
-2. **Test your changes**
+2. **Test your changes** (via curl from your fork)
```bash
- bash ct/my-app.sh
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/my-app.sh)"
# Follow prompts and test the container
+ # ⏱️ Wait 10-30 seconds after pushing - GitHub takes time to update
```
3. **Check code standards**
@@ -493,44 +505,61 @@ Before opening a PR:
## ❓ FAQ
-### ⚠️ Why must I use `bash ct/myapp.sh` (during development)?
+### ❌ Why can't I test with `bash ct/myapp.sh` locally?
-During **local development and testing** in your fork, use bash explicitly:
+You might try:
```bash
-# ✅ CORRECT (during development in your fork)
+# ❌ WRONG - This won't test your actual changes!
bash ct/myapp.sh
-
-# ❌ WRONG - Will fail
./ct/myapp.sh
sh ct/myapp.sh
-/path/to/ct/myapp.sh
+```
+
+**Why this fails:**
+
+- `bash ct/myapp.sh` uses the LOCAL clone file
+- The LOCAL file doesn't execute the curl commands - it's already on disk
+- The curl URLs INSIDE the script are modified by setup-fork.sh, but they're not executed
+- So you can't verify if your curl URLs actually work
+- Users will get the curl URL version (which may be broken)
+
+**Solution:** Always test via curl from GitHub:
+
+```bash
+# ✅ CORRECT - Tests the actual GitHub URLs
+bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/myapp.sh)"
+```
+
+### ❓ How do I test my changes?
+
+You **cannot** test locally with `bash ct/myapp.sh` from your cloned directory!
+
+You **must** push to GitHub and test via curl from your fork:
+
+```bash
+# 1. Push your changes to your fork
+git push origin feature/my-awesome-app
+
+# 2. Test via curl (this loads the script from GitHub, not local files)
+bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/my-app.sh)"
+
+# 3. For verbose/debug output, pass environment variables
+VERBOSE=yes bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/my-app.sh)"
+DEV_MODE_LOGS=true bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/my-app.sh)"
```
**Why?**
-- Scripts use bash-specific features (arrays, process substitution, etc.)
-- Permissions might not be executable on Windows/WSL
-- Source files need proper `<(curl ...)` process substitution
-- Error handling requires specific bash settings
+- Local `bash ct/myapp.sh` uses local files from your clone
+- But the script's INTERNAL curl commands have been modified by setup-fork.sh to point to your fork
+- This discrepancy means you're not actually testing the curl URLs
+- Testing via curl ensures the script downloads from YOUR fork GitHub URLs
+- ⏱️ **Important:** GitHub takes 10-30 seconds to recognize newly pushed files. Wait before testing!
-**⚠️ But remember:** Once merged, users will run it via `curl | bash` from GitHub, not locally!
+**What if local bash worked?**
-### How do I test my changes locally?
-
-```bash
-# You're on Proxmox VE host with your fork cloned
-# Test your script before PR:
-
-bash ct/my-app.sh
-
-# The setup-fork.sh script ensures curl pulls from YOUR fork, not upstream
-# So this tests your actual changes!
-
-# For advanced debugging with verbose output
-VERBOSE=yes bash ct/my-app.sh
-DEV_MODE_LOGS=true bash ct/my-app.sh
-```
+You'd be testing local files only, not the actual GitHub URLs that users will download. This means broken curl links wouldn't be caught during testing.
### What if my PR has conflicts?
diff --git a/docs/contribution/templates_ct/AppName.md b/docs/contribution/templates_ct/AppName.md
index 7759f1dfb..0b0387a1f 100644
--- a/docs/contribution/templates_ct/AppName.md
+++ b/docs/contribution/templates_ct/AppName.md
@@ -1,197 +1,193 @@
-# **AppName.sh Scripts**
+# CT Container Scripts - Quick Reference
- `AppName.sh` scripts found in the `/ct` directory. These scripts are responsible for the installation of the desired application. For this guide we take `/ct/snipeit.sh` as example.
-
-## Table of Contents
-
-- [**AppName.sh Scripts**](#appnamesh-scripts)
- - [Table of Contents](#table-of-contents)
- - [1. **File Header**](#1-file-header)
- - [1.1 **Shebang**](#11-shebang)
- - [1.2 **Import Functions**](#12-import-functions)
- - [1.3 **Metadata**](#13-metadata)
- - [2 **Variables and function import**](#2-variables-and-function-import)
- - [2.1 **Default Values**](#21-default-values)
- - [2.2 **📋 App output \& base settings**](#22--app-output--base-settings)
- - [2.3 **🛠 Core functions**](#23--core-functions)
- - [3 **Update function**](#3-update-function)
- - [3.1 **Function Header**](#31-function-header)
- - [3.2 **Check APP**](#32-check-app)
- - [3.3 **Check version**](#33-check-version)
- - [3.4 **Verbosity**](#34-verbosity)
- - [3.5 **Backups**](#35-backups)
- - [3.6 **Cleanup**](#36-cleanup)
- - [3.7 **No update function**](#37-no-update-function)
- - [4 **End of the script**](#4-end-of-the-script)
- - [5. **Contribution checklist**](#5-contribution-checklist)
-
-## 1. **File Header**
-
-### 1.1 **Shebang**
-
-- Use `#!/usr/bin/env bash` as the shebang.
-
-```bash
-#!/usr/bin/env bash
-```
-
-### 1.2 **Import Functions**
-
-- Import the build.func file.
-- When developing your own script, change the URL to your own repository.
-
-> [!IMPORTANT]
-> You also need to change all apperances of this URL in `misc/build.func` and `misc/install.func`
-
-Example for development:
-
-```bash
-source <(curl -fsSL https://raw.githubusercontent.com/[USER]/[REPO]/refs/heads/[BRANCH]/misc/build.func)
-```
-
-Final script:
-
-```bash
-source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
-```
-
-> [!CAUTION]
-> Before opening a Pull Request, change the URLs to point to the community-scripts repo.
-
-### 1.3 **Metadata**
-
-- Add clear comments for script metadata, including author, copyright, and license information.
-
-Example:
-
-```bash
-# Copyright (c) 2021-2026 community-scripts ORG
-# Author: [YourUserName]
-# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
-# Source: [SOURCE_URL]
-```
-
-> [!NOTE]:
+> [!WARNING]
+> **This is legacy documentation.** Refer to the **modern template** at [templates_ct/AppName.sh](AppName.sh) for best practices.
>
-> - Add your username and source URL
-> - For existing scripts, add "| Co-Author [YourUserName]" after the current author
+> Current templates use:
+>
+> - `tools.func` helpers instead of manual patterns
+> - `check_for_gh_release` and `fetch_and_deploy_gh_release` from build.func
+> - Automatic setup-fork.sh configuration
---
-## 2 **Variables and function import**
->
-> [!NOTE]
-> You need to have all this set in your script, otherwise it will not work!
+## Before Creating a Script
-### 2.1 **Default Values**
+1. **Fork & Clone:**
-- This section sets the default values for the container.
-- `APP` needs to be set to the application name and must be equal to the filenames of your scripts.
-- `var_tags`: You can set Tags for the CT wich show up in the Proxmox UI. Don´t overdo it!
+ ```bash
+ git clone https://github.com/YOUR_USERNAME/ProxmoxVE.git
+ cd ProxmoxVE
+ ```
->[!NOTE]
->Description for all Default Values
->
->| Variable | Description | Notes |
->|----------|-------------|-------|
->| `APP` | Application name | Must match ct\AppName.sh |
->| `var_tags` | Proxmox display tags without Spaces, only ; | Limit the number |
->| `var_cpu` | CPU cores | Number of cores |
->| `var_ram` | RAM | In MB |
->| `var_disk` | Disk capacity | In GB |
->| `var_os` | Operating system | alpine, debian, ubuntu |
->| `var_version` | OS version | e.g., 3.20, 11, 12, 20.04 |
->| `var_unprivileged` | Container type | 1 = Unprivileged, 0 = Privileged |
+2. **Run setup-fork.sh** (updates all curl URLs to your fork):
-Example:
+ ```bash
+ bash docs/contribution/setup-fork.sh
+ ```
+
+3. **Copy the Modern Template:**
+
+ ```bash
+ cp templates_ct/AppName.sh ct/MyApp.sh
+ # Edit ct/MyApp.sh with your app details
+ ```
+
+4. **Test Your Script (via GitHub):**
+
+ ⚠️ **Important:** You must push to GitHub and test via curl, not `bash ct/MyApp.sh`!
+
+ ```bash
+ # Push your changes to your fork first
+ git push origin feature/my-awesome-app
+
+ # Then test via curl (this loads from YOUR fork, not local files)
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/MyApp.sh)"
+ ```
+
+ > 💡 **Why?** The script's curl commands are modified by setup-fork.sh, but local execution uses local files, not the updated GitHub URLs. Testing via curl ensures your script actually works.
+ >
+ > ⏱️ **Note:** GitHub sometimes takes 10-30 seconds to update files. If you don't see your changes, wait and try again.
+
+5. **Cherry-Pick for PR** (submit ONLY your 3-4 files):
+ - See [Cherry-Pick Guide](../README.md) for step-by-step git commands
+
+---
+
+## Template Structure
+
+The modern template includes:
+
+### Header
```bash
-APP="SnipeIT"
-var_tags="asset-management;foss"
+#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func)
+# (Note: setup-fork.sh changes this URL to point to YOUR fork during development)
+```
+
+### Metadata
+
+```bash
+# Copyright (c) 2021-2026 community-scripts ORG
+# Author: YourUsername
+# License: MIT
+APP="MyApp"
+var_tags="app-category;foss"
var_cpu="2"
var_ram="2048"
var_disk="4"
-var_os="debian"
-var_version="12"
+var_os="alpine"
+var_version="3.20"
var_unprivileged="1"
```
-## 2.2 **📋 App output & base settings**
+### Core Setup
```bash
header_info "$APP"
-```
-- `header_info`: Generates ASCII header for APP
-
-## 2.3 **🛠 Core functions**
-
-```bash
variables
color
catch_errors
```
-- `variables`: Processes input and prepares variables
-- `color`: Sets icons, colors, and formatting
-- `catch_errors`: Enables error handling
+### Update Function
----
-
-## 3 **Update function**
-
-### 3.1 **Function Header**
-
-- If applicable write a function that updates the application and the OS in the container.
-- Each update function starts with the same code:
+The modern template provides a standard update pattern:
```bash
function update_script() {
header_info
check_container_storage
check_container_resources
-```
-### 3.2 **Check APP**
-
-- Before doing anything update-wise, check if the app is installed in the container.
-
-Example:
-
-```bash
-if [[ ! -d /opt/snipe-it ]]; then
- msg_error "No ${APP} Installation Found!"
- exit
- fi
-```
-
-### 3.3 **Check version**
-
-- Before updating, check if a new version exists.
- - We use the `${APPLICATION}_version.txt` file created in `/opt` during the install to compare new versions against the currently installed version.
-
-Example with a Github Release:
-
-```bash
- RELEASE=$(curl -fsSL https://api.github.com/repos/snipe/snipe-it/releases/latest | grep "tag_name" | awk '{print substr($2, 3, length($2)-4) }')
- if [[ ! -f /opt/${APP}_version.txt ]] || [[ "${RELEASE}" != "$(cat /opt/${APP}_version.txt)" ]]; then
- msg_info "Updating ${APP} to v${RELEASE}"
- #DO UPDATE
- else
- msg_ok "No update required. ${APP} is already at v${RELEASE}."
- fi
- exit
+ # Use tools.func helpers:
+ check_for_gh_release "myapp" "YourUsername/ProxmoxVE"
+ fetch_and_deploy_gh_release "myapp" "app/owner" "appname.tar.gz" "latest" "/opt/myapp"
}
```
+---
+
+## Key Patterns
+
+### Check for Updates (ProxmoxVE Fork)
+
+Use `check_for_gh_release` with **YOUR fork**:
+
+```bash
+check_for_gh_release "myapp" "YourUsername/ProxmoxVE"
+```
+
+### Deploy External App
+
+Use `fetch_and_deploy_gh_release` with **target app repo**:
+
+```bash
+fetch_and_deploy_gh_release "myapp" "myapp/repo" "appname.tar.gz" "latest" "/opt/myapp"
+```
+
+### Avoid Manual Version Checking
+
+❌ OLD (manual):
+
+```bash
+RELEASE=$(curl -fsSL https://api.github.com/repos/myapp/myapp/releases/latest | grep tag_name)
+```
+
+✅ NEW (use tools.func):
+
+```bash
+fetch_and_deploy_gh_release "myapp" "myapp/repo" "appname.tar.gz" "latest" "/opt/myapp"
+```
+
+---
+
+## Best Practices
+
+1. **Use tools.func helpers** - Don't manually curl for versions
+2. **Only add app-specific dependencies** - Don't add ca-certificates, curl, gnupg (handled by build.func)
+3. **Test via curl from your fork** - Push first, then: `bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/MyApp.sh)"`
+4. **Wait for GitHub to update** - Takes 10-30 seconds after git push
+5. **Cherry-pick only YOUR files** - Submit only ct/MyApp.sh, install_scripts/MyApp-install.sh, config/myapp.json (3 files)
+6. **Verify before PR** - Run `git diff upstream/main --name-only` to confirm only your files changed
+
+---
+
+## Common Update Patterns
+
+See the [modern template](AppName.sh) and [AI.md](../AI.md) for complete working examples.
+
+Recent reference scripts with good update functions:
+
+- [Trip](https://github.com/community-scripts/ProxmoxVE/blob/main/ct/trip.sh)
+- [Thingsboard](https://github.com/community-scripts/ProxmoxVE/blob/main/ct/thingsboard.sh)
+- [UniFi](https://github.com/community-scripts/ProxmoxVE/blob/main/ct/unifi.sh)
+
+---
+
+## Need Help?
+
+- **[README.md](../README.md)** - Full contribution workflow
+- **[AI.md](../AI.md)** - AI-generated script guidelines
+- **[FORK_SETUP.md](../FORK_SETUP.md)** - Why setup-fork.sh is important
+- **[Slack Community](https://discord.gg/your-link)** - Ask questions
+ msg_ok "No update required. ${APP} is already at v${RELEASE}."
+ fi
+ exit
+ }
+
+````
+
### 3.4 **Verbosity**
- Use the appropriate flag (**-q** in the examples) for a command to suppress its output.
-Example:
+ Example:
```bash
curl -fsSL
unzip -q
-```
+````
- If a command does not come with this functionality use `$STD` to suppress it's output.
@@ -207,8 +203,8 @@ $STD php artisan config:clear
- Backup user data if necessary.
- Move all user data back in the directory when the update is finished.
->[!NOTE]
->This is not meant to be a permanent backup
+> [!NOTE]
+> This is not meant to be a permanent backup
Example backup:
@@ -227,7 +223,7 @@ Example config restore:
### 3.6 **Cleanup**
- Do not forget to remove any temporary files/folders such as zip-files or temporary backups.
-Example:
+ Example:
```bash
rm -rf /opt/v${RELEASE}.zip
@@ -277,7 +273,7 @@ echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}"
## 5. **Contribution checklist**
- [ ] Shebang is correctly set (`#!/usr/bin/env bash`).
-- [ ] Correct link to *build.func*
+- [ ] Correct link to _build.func_
- [ ] Metadata (author, license) is included at the top.
- [ ] Variables follow naming conventions.
- [ ] Update function exists.
diff --git a/docs/contribution/templates_install/AppName-install.md b/docs/contribution/templates_install/AppName-install.md
index a5b21634e..dffdc3855 100644
--- a/docs/contribution/templates_install/AppName-install.md
+++ b/docs/contribution/templates_install/AppName-install.md
@@ -1,54 +1,195 @@
+# Install Scripts - Quick Reference
-# **AppName-install.sh Scripts**
+> [!WARNING]
+> **This is legacy documentation.** Refer to the **modern template** at [templates_install/AppName-install.sh](AppName-install.sh) for best practices.
+>
+> Current templates use:
+>
+> - `tools.func` helpers (setup_nodejs, setup_python, setup_postgresql_db, etc.)
+> - Automatic dependency installation via build.func
+> - Standardized environment variable patterns
- `AppName-install.sh` scripts found in the `/install` directory. These scripts are responsible for the installation of the application. For this guide we take `/install/snipeit-install.sh` as example.
+---
-## Table of Contents
+## Before Creating a Script
-- [**AppName-install.sh Scripts**](#appname-installsh-scripts)
- - [Table of Contents](#table-of-contents)
- - [1. **File header**](#1-file-header)
- - [1.1 **Shebang**](#11-shebang)
- - [1.2 **Comments**](#12-comments)
- - [1.3 **Variables and function import**](#13-variables-and-function-import)
- - [2. **Variable naming and management**](#2-variable-naming-and-management)
- - [2.1 **Naming conventions**](#21-naming-conventions)
- - [3. **Dependencies**](#3-dependencies)
- - [3.1 **Install all at once**](#31-install-all-at-once)
- - [3.2 **Collapse dependencies**](#32-collapse-dependencies)
- - [4. **Paths to application files**](#4-paths-to-application-files)
- - [5. **Version management**](#5-version-management)
- - [5.1 **Install the latest release**](#51-install-the-latest-release)
- - [5.2 **Save the version for update checks**](#52-save-the-version-for-update-checks)
- - [6. **Input and output management**](#6-input-and-output-management)
- - [6.1 **User feedback**](#61-user-feedback)
- - [6.2 **Verbosity**](#62-verbosity)
- - [7. **String/File Manipulation**](#7-stringfile-manipulation)
- - [7.1 **File Manipulation**](#71-file-manipulation)
- - [8. **Security practices**](#8-security-practices)
- - [8.1 **Password generation**](#81-password-generation)
- - [8.2 **File permissions**](#82-file-permissions)
- - [9. **Service Configuration**](#9-service-configuration)
- - [9.1 **Configuration files**](#91-configuration-files)
- - [9.2 **Credential management**](#92-credential-management)
- - [9.3 **Enviroment files**](#93-enviroment-files)
- - [9.4 **Services**](#94-services)
- - [10. **Cleanup**](#10-cleanup)
- - [10.1 **Remove temporary files**](#101-remove-temporary-files)
- - [10.2 **Autoremove and autoclean**](#102-autoremove-and-autoclean)
- - [11. **Best Practices Checklist**](#11-best-practices-checklist)
- - [Example: High-Level Script Flow](#example-high-level-script-flow)
+1. **Copy the Modern Template:**
-## 1. **File header**
+ ```bash
+ cp templates_install/AppName-install.sh install_scripts/MyApp-install.sh
+ # Edit install_scripts/MyApp-install.sh
+ ```
-### 1.1 **Shebang**
+2. **Key Pattern:**
+ - CT scripts source build.func and call the install script
+ - Install scripts use sourced FUNCTIONS_FILE_PATH (via build.func)
+ - Both scripts work together in the container
-- Use `#!/usr/bin/env bash` as the shebang.
+3. **Test via GitHub:**
+
+ ```bash
+ # Push your changes to your fork first
+ git push origin feature/my-awesome-app
+
+ # Test the CT script via curl (it will call the install script)
+ bash -c "$(curl -fsSL https://raw.githubusercontent.com/YOUR_USERNAME/ProxmoxVE/main/ct/MyApp.sh)"
+ # ⏱️ Wait 10-30 seconds after pushing - GitHub takes time to update
+ ```
+
+---
+
+## Template Structure
+
+### Header
```bash
#!/usr/bin/env bash
+source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/install.func)
+# (setup-fork.sh modifies this URL to point to YOUR fork during development)
```
+### Dependencies (App-Specific Only)
+
+```bash
+# Don't add: ca-certificates, curl, gnupg, wget, git, jq
+# These are handled by build.func
+msg_info "Installing dependencies"
+$STD apt-get install -y app-specific-deps
+msg_ok "Installed dependencies"
+```
+
+### Runtime Setup
+
+Use tools.func helpers instead of manual installation:
+
+```bash
+# ✅ NEW (use tools.func):
+NODE_VERSION="20"
+setup_nodejs
+# OR
+PYTHON_VERSION="3.12"
+setup_uv
+# OR
+PG_DB_NAME="myapp_db"
+PG_DB_USER="myapp"
+setup_postgresql_db
+```
+
+### Service Configuration
+
+```bash
+# Create .env file
+msg_info "Configuring MyApp"
+cat << EOF > /opt/myapp/.env
+DEBUG=false
+PORT=8080
+DATABASE_URL=postgresql://...
+EOF
+msg_ok "Configuration complete"
+
+# Create systemd service
+msg_info "Creating systemd service"
+cat << EOF > /etc/systemd/system/myapp.service
+[Unit]
+Description=MyApp
+[Service]
+ExecStart=/usr/bin/node /opt/myapp/app.js
+[Install]
+WantedBy=multi-user.target
+EOF
+msg_ok "Service created"
+```
+
+### Finalization
+
+```bash
+msg_info "Finalizing MyApp installation"
+systemctl enable --now myapp
+motd_ssh
+customize
+msg_ok "MyApp installation complete"
+cleanup_lxc
+```
+
+---
+
+## Key Patterns
+
+### Avoid Manual Version Checking
+
+❌ OLD (manual):
+
+```bash
+RELEASE=$(curl -fsSL https://api.github.com/repos/app/repo/releases/latest | grep tag_name)
+wget https://github.com/app/repo/releases/download/$RELEASE/app.tar.gz
+```
+
+✅ NEW (use tools.func via CT script's fetch_and_deploy_gh_release):
+
+```bash
+# In CT script, not install script:
+fetch_and_deploy_gh_release "myapp" "app/repo" "app.tar.gz" "latest" "/opt/myapp"
+```
+
+### Database Setup
+
+```bash
+# Use setup_postgresql_db, setup_mysql_db, etc.
+PG_DB_NAME="myapp"
+PG_DB_USER="myapp"
+setup_postgresql_db
+```
+
+### Node.js Setup
+
+```bash
+NODE_VERSION="20"
+setup_nodejs
+npm install --no-save
+```
+
+---
+
+## Best Practices
+
+1. **Only add app-specific dependencies**
+ - Don't add: ca-certificates, curl, gnupg, wget, git, jq
+ - These are handled by build.func
+
+2. **Use tools.func helpers**
+ - setup_nodejs, setup_python, setup_uv, setup_postgresql_db, setup_mysql_db, etc.
+
+3. **Don't do version checks in install script**
+ - Version checking happens in CT script's update_script()
+ - Install script just installs the latest
+
+4. **Structure:**
+ - Dependencies
+ - Runtime setup (tools.func)
+ - Deployment (fetch from CT script)
+ - Configuration files
+ - Systemd service
+ - Finalization
+
+---
+
+## Reference Scripts
+
+See working examples:
+
+- [Trip](https://github.com/community-scripts/ProxmoxVE/blob/main/install_scripts/trip-install.sh)
+- [Thingsboard](https://github.com/community-scripts/ProxmoxVE/blob/main/install_scripts/thingsboard-install.sh)
+- [UniFi](https://github.com/community-scripts/ProxmoxVE/blob/main/install_scripts/unifi-install.sh)
+
+---
+
+## Need Help?
+
+- **[Modern Template](AppName-install.sh)** - Start here
+- **[CT Template](../templates_ct/AppName.sh)** - How CT scripts work
+- **[README.md](../README.md)** - Full contribution workflow
+- **[AI.md](../AI.md)** - AI-generated script guidelines
+
### 1.2 **Comments**
- Add clear comments for script metadata, including author, copyright, and license information.
@@ -189,7 +330,7 @@ msg_ok "Installed Dependencies"
### 6.2 **Verbosity**
- Use the appropiate flag (**-q** in the examples) for a command to suppres its output
-Example:
+ Example:
```bash
curl -fsSL
diff --git a/docs/contribution/templates_json/AppName.md b/docs/contribution/templates_json/AppName.md
index 5b61f5e91..92f870bfa 100644
--- a/docs/contribution/templates_json/AppName.md
+++ b/docs/contribution/templates_json/AppName.md
@@ -1,13 +1,137 @@
-# **AppName.json Files**
+# JSON Metadata Files - Quick Reference
- `AppName.json` files found in the `/json` directory. These files are used to provide informations for the website. For this guide we take `/json/snipeit.json` as example.
+The metadata file (`config/myapp.json`) tells the web interface how to display your application.
-## Table of Contents
+---
-- [**AppName.json Files**](#appnamejson-files)
- - [Table of Contents](#table-of-contents)
- - [1. JSON Generator](#1-json-generator)
+## Quick Start
-## 1. JSON Generator
+**Use the JSON Generator Tool:**
+[https://community-scripts.github.io/ProxmoxVE/json-editor](https://community-scripts.github.io/ProxmoxVE/json-editor)
-Use the [JSON Generator](https://community-scripts.github.io/ProxmoxVE/json-editor) to create this file for your application.
+1. Enter application details
+2. Generator creates `config/myapp.json`
+3. Copy the output to your contribution
+
+---
+
+## File Structure
+
+```json
+{
+ "name": "MyApp",
+ "slug": "myapp",
+ "categories": ["utilities", "monitoring"],
+ "date_created": "2025-01-15",
+ "type": "ct",
+ "interface_port": "3000",
+ "logo": "https://example.com/logo.png",
+ "config_path": "/etc/myapp/config.json",
+ "description": "Brief description of what MyApp does",
+ "install_methods": {
+ "1": {
+ "type": "ct",
+ "resources": {
+ "cpu": "2",
+ "ram": "2048",
+ "disk": "10"
+ },
+ "pre_install_msg": "Optional message shown before installation"
+ }
+ },
+ "default_credentials": {
+ "username": "admin",
+ "password": "Generated during install"
+ },
+ "notes": "Optional setup notes",
+ "notes_type": "markdown"
+}
+```
+
+---
+
+## Field Reference
+
+| Field | Required | Example | Notes |
+| --------------------- | -------- | ------------------------ | ---------------------------------------------- |
+| `name` | Yes | "MyApp" | Display name |
+| `slug` | Yes | "myapp" | URL-friendly identifier (lowercase, no spaces) |
+| `categories` | Yes | ["utilities"] | One or more from available list |
+| `date_created` | Yes | "2025-01-15" | Format: YYYY-MM-DD |
+| `type` | Yes | "ct" | Container type: "ct" or "vm" |
+| `interface_port` | Yes | "3000" | Default web interface port |
+| `logo` | No | "https://..." | Logo URL (64px x 64px PNG) |
+| `config_path` | Yes | "/etc/myapp/config.json" | Main config file location |
+| `description` | Yes | "App description" | Brief description (100 chars) |
+| `install_methods` | Yes | See below | Installation resources |
+| `default_credentials` | No | See below | Optional default login |
+| `notes` | No | "Setup info" | Additional notes |
+| `notes_type` | No | "markdown" | Format of notes field |
+
+---
+
+## Install Methods
+
+Each installation method specifies resource requirements:
+
+```json
+"install_methods": {
+ "1": {
+ "type": "ct",
+ "resources": {
+ "cpu": "2",
+ "ram": "2048",
+ "disk": "10"
+ },
+ "pre_install_msg": "Optional message"
+ }
+}
+```
+
+**Resource Defaults:**
+
+- CPU: Cores (1-8)
+- RAM: Megabytes (256-4096)
+- Disk: Gigabytes (4-50)
+
+---
+
+## Common Categories
+
+- `utilities` - Tools and utilities
+- `monitoring` - Monitoring/logging
+- `media` - Media servers
+- `databases` - Database systems
+- `communication` - Chat/messaging
+- `smart-home` - Home automation
+- `development` - Dev tools
+- `security` - Security tools
+- `storage` - File storage
+
+---
+
+## Best Practices
+
+1. **Use the JSON Generator** - It validates structure
+2. **Keep descriptions short** - 100 characters max
+3. **Use real resource requirements** - Based on your testing
+4. **Include sensible defaults** - Pre-filled in install_methods
+5. **Slug must be lowercase** - No spaces, use hyphens
+
+---
+
+## Reference Examples
+
+See actual examples in the repo:
+
+- [config/trip.json](https://github.com/community-scripts/ProxmoxVE/blob/main/config/trip.json)
+- [config/thingsboard.json](https://github.com/community-scripts/ProxmoxVE/blob/main/config/thingsboard.json)
+- [config/unifi.json](https://github.com/community-scripts/ProxmoxVE/blob/main/config/unifi.json)
+
+---
+
+## Need Help?
+
+- **[JSON Generator](https://community-scripts.github.io/ProxmoxVE/json-editor)** - Interactive tool
+- **[README.md](../README.md)** - Full contribution workflow
+- **[Quick Start](../README.md)** - Step-by-step guide