# Phase 13: Add Remaining RClone Remotes - Research
**Researched:** 2026-04-01
**Domain:** rclone backend registry expansion, React component architecture, UX search/categorization
**Confidence:** HIGH
---
## User Constraints (from CONTEXT.md)
### Locked Decisions
- Comprehensive coverage — all rclone backends that make sense for unattended Windows deployment
- OAuth-requiring backends included via token-paste approach (same as OneDrive: user runs `rclone authorize` locally, pastes resulting JSON token)
- All new backends shipped in a single phase (no sub-phases by auth type)
- Claude picks the specific backend list based on rclone documentation and deployment viability
- Reuse per-backend AuthToggle component pattern for backends with mutually-exclusive auth fields (e.g., FTP password vs key file) — same proven pattern as AzureAuthToggle/SftpAuthToggle
- Build a new reusable OAuthInstructions component for OAuth-token backends — collapsible step-by-step guide showing how to run `rclone authorize` for that specific backend
- OAuthInstructions takes backend-specific command and steps as props, keeps RemoteConfigStep clean
- Categorized sections with headings: Cloud Object Storage, Cloud Drives, Protocol-based — grouped by storage type
- Search/filter bar at the top that filters instantly as user types
- Search matches across all fields: displayName, description, category, and field labels
- Categories with no matching backends collapse when search is active
- Add `category` field to each BACKEND_REGISTRY entry — single source of truth stays single
- Add inline SVG icons per backend card — hand-picked SVGs bundled in the app, no external dependency
### Claude's Discretion
- BackendType implementation: keep explicit union type or derive dynamically from registry keys — pick whichever balances type safety and maintainability best at 20+ backends
- Specific backend list selection based on rclone docs and unattended deployment viability
- Field validation depth per backend (regex patterns vs simple required/optional)
- Icon design approach (monochrome vs brand colors, sizing)
### Deferred Ideas (OUT OF SCOPE)
None — discussion stayed within phase scope
---
## Summary
Phase 13 expands the BACKEND_REGISTRY from 7 to approximately 18-20 entries, grouping them into three categories (Cloud Object Storage, Cloud Drives, Protocol-based). Each new backend requires: a registry entry, a RCLONE_TYPE_MAP entry, a `buildZodSchema()` call, and a `backendLabel` entry. Backends with OAuth tokens get an `OAuthInstructions` collapsible component. Backends with mutually-exclusive auth get a new AuthToggle component. The BackendSelectionStep gets a complete UX overhaul with category headings, instant search, and inline SVG icons.
The critical architectural decision is whether `BackendType` stays as an explicit union literal or is derived from registry keys. At 20+ backends, explicit union becomes a maintenance burden (every new backend requires editing 6 files). Deriving from registry keys reduces that to 4 files and eliminates the "forgot to update BackendType" class of bug.
**Primary recommendation:** Derive `BackendType` from `keyof typeof BACKEND_REGISTRY` to reduce per-backend boilerplate from 6 touch-points to 4. Use `as const` assertion on the registry object for full TypeScript narrowing.
---
## Recommended Backend List
Based on rclone documentation and suitability for unattended Windows deployment via RMM/Intune, the following backends should be added. Each entry shows the rclone `type` string and auth approach.
### Category: Cloud Object Storage (S3-like)
These all use static API credentials — ideal for unattended deployment.
| Backend ID | displayName | rclone type | Auth approach | Notes |
|------------|-------------|-------------|---------------|-------|
| `azureblob` | Azure Blob Storage | `azureblob` | Key or SAS URL | Existing |
| `azure-files` | Azure Files Storage | `azurefiles` | Account + Key | New — uses `account` + `key` fields |
| `s3` | Amazon S3 | `s3` | Access Key + Secret | Existing |
| `s3-compatible` | S3-Compatible | `s3` (provider=Other) | Access Key + Secret + Endpoint | Existing |
| `gcs` | Google Cloud Storage | `google cloud storage` | Service Account JSON | Existing |
| `b2` | Backblaze B2 | `b2` | Application Key ID + Key | Existing |
| `swift` | OpenStack Swift | `swift` | User + Key + Auth URL + Tenant | New — API credential |
### Category: Cloud Drives (OAuth token-paste)
These require OAuth — user runs `rclone authorize` locally, pastes JSON token.
| Backend ID | displayName | rclone type | Auth approach | Notes |
|------------|-------------|-------------|---------------|-------|
| `onedrive` | OneDrive | `onedrive` | OAuth token + drive_id + drive_type | Existing |
| `gdrive` | Google Drive | `drive` | OAuth token + service account option | New — token or service_account_credentials |
| `dropbox` | Dropbox | `dropbox` | OAuth token (JSON blob) | New — token field only |
| `box` | Box | `box` | OAuth token (JSON blob) | New — token + box_sub_type |
| `pcloud` | pCloud | `pcloud` | OAuth token (JSON blob) | New — token + hostname |
### Category: Protocol-based
These use server credentials — IP/hostname, user, password.
| Backend ID | displayName | rclone type | Auth approach | Notes |
|------------|-------------|-------------|---------------|-------|
| `sftp` | SFTP | `sftp` | Password or Key PEM (AuthToggle) | Existing |
| `ftp` | FTP | `ftp` | Host + User + Password | New — also FTPS via `tls` select |
| `webdav` | WebDAV | `webdav` | URL + User + Password + Vendor select | New — includes NextCloud, SharePoint, OwnCloud, etc. |
| `smb` | SMB / Windows Share | `smb` | Host + User + Pass + Domain | New — ideal for Windows shops |
| `http` | HTTP (read-only) | `http` | URL only | New — simple, read-only |
| `seafile` | Seafile | `seafile` | URL + User + Password | New — self-hosted cloud |
**Total:** 7 existing + 10 new = 17 backends
**Excluded from scope (not suitable for unattended Windows deployment):**
- HDFS — Hadoop/enterprise Linux ecosystem, not Windows-native
- Google Photos — read-only, consumer
- iCloud Drive — macOS-only tooling
- Mega, Jottacloud, Yandex, Mail.ru — consumer-grade, poor enterprise adoption
- pCloud — included only if token-paste approach is feasible (MEDIUM confidence)
- Internet Archive, Pixeldrain, Uloz.to, Gofile — public/consumer file sharing
---
## Standard Stack
### Core (no new dependencies)
| Library | Version | Purpose | Why Standard |
|---------|---------|---------|--------------|
| react | ^18.3.1 | UI rendering | Existing |
| react-hook-form | ^7.72.0 | Form state + validation | Existing — all forms use it |
| zod | ^4.3.6 | Schema validation | Existing — `buildZodSchema()` auto-derives |
| @hookform/resolvers | ^5.2.2 | Zod <-> RHF bridge | Existing |
**No new npm dependencies.** Inline SVG icons are bundled as TSX components. No icon library needed.
### Installation
```bash
# Nothing new to install — all new code uses existing stack
```
---
## Architecture Patterns
### Recommended Project Structure (additions only)
```
src/
├── schemas/
│ └── registry.ts # Add ~10 new backend entries + category field
├── generators/
│ └── rclone-conf.ts # Add ~10 entries to RCLONE_TYPE_MAP
├── components/
│ ├── wizard/
│ │ ├── BackendSelectionStep.tsx # Full overhaul: categories, search, icons
│ │ ├── RemoteConfigStep.tsx # Add auth-toggle branches for FTP/WebDAV
│ │ ├── FtpAuthToggle.tsx # New: password vs no-auth (anonymous) toggle
│ │ ├── OAuthInstructions.tsx # New: reusable collapsible rclone authorize guide
│ │ └── [backend]AuthToggle.tsx # Only if backend needs mutually-exclusive auth
│ └── icons/
│ └── BackendIcons.tsx # New: inline SVG icon map, keyed by BackendType
```
### Pattern 1: Deriving BackendType from Registry (RECOMMENDED)
The current explicit union `'azureblob' | 's3' | ...` must be touched in `registry.ts` every time a backend is added. At 17+ backends, derive it instead:
```typescript
// src/schemas/registry.ts
export const BACKEND_REGISTRY = {
azureblob: { ... },
gdrive: { ... },
// ... all entries
} as const; // <-- CRITICAL: 'as const' needed for keyof narrowing
export type BackendType = keyof typeof BACKEND_REGISTRY;
// Result: 'azureblob' | 's3' | 'gdrive' | ... (auto-updated when registry grows)
```
**What changes:** `BackendType` no longer lives in `registry.ts` as a separate literal union — it is derived. The `src/store/types.ts` re-export (`export type { BackendType }`) continues to work unchanged. All consumers importing `BackendType` from `./registry` or `../store/types` require zero changes.
**What must be verified:** The `BACKEND_REGISTRY` cast at the bottom currently uses `as Record` which would become circular. Remove that cast — with `as const` the registry is already fully typed by inference.
**Confidence:** HIGH — standard TypeScript pattern, verified against codebase.
### Pattern 2: BACKEND_REGISTRY Entry with `category` Field
Add `category` to the registry entry — single source of truth for categorization:
```typescript
// src/schemas/registry.ts
export type BackendCategory = 'cloud-object-storage' | 'cloud-drives' | 'protocol-based';
export interface BackendMeta {
displayName: string;
description: string;
category: BackendCategory; // NEW field
fields: FieldDef[];
}
export const BACKEND_REGISTRY = {
azureblob: {
displayName: 'Azure Blob Storage',
description: 'Microsoft Azure cloud storage',
category: 'cloud-object-storage', // NEW
fields: [ ... ],
},
gdrive: {
displayName: 'Google Drive',
description: 'Google Drive (paste pre-obtained rclone token)',
category: 'cloud-drives',
fields: [ ... ],
},
} as const;
```
### Pattern 3: OAuthInstructions Component
Collapsible component, collapsed by default. Takes backend-specific props:
```typescript
// src/components/wizard/OAuthInstructions.tsx
interface OAuthInstructionsProps {
backendName: string; // e.g. "Google Drive"
authorizeCommand: string; // e.g. 'rclone authorize "drive"'
steps?: string[]; // optional custom step descriptions
}
export function OAuthInstructions({ backendName, authorizeCommand, steps }: OAuthInstructionsProps) {
const [expanded, setExpanded] = useState(false);
// Renders a collapsible details/summary or button-controlled div
// Shows numbered steps: install rclone → run command → browser opens → paste JSON
}
```
Used in RemoteConfigStep for `gdrive`, `dropbox`, `box`, `pcloud` alongside the `token` PasswordField:
```typescript
// In RemoteConfigStep, new OAuth branch:
} : backendType === 'gdrive' ? (
<>
f.key === 'token')!} ... />
f.key === 'root_folder_id')!} ... />
>
)
```
### Pattern 4: BackendSelectionStep Category + Search
The current flat grid becomes a category-grouped, searchable layout:
```typescript
// Category display order (stable, not alphabetical)
const CATEGORY_ORDER: BackendCategory[] = [
'cloud-object-storage',
'cloud-drives',
'protocol-based',
];
const CATEGORY_LABELS: Record = {
'cloud-object-storage': 'Cloud Object Storage',
'cloud-drives': 'Cloud Drives',
'protocol-based': 'Protocol-based',
};
// Search filter logic — matches displayName, description, category label, and field labels
function matchesSearch(entry: BackendMeta, query: string): boolean {
const q = query.toLowerCase();
if (entry.displayName.toLowerCase().includes(q)) return true;
if (entry.description.toLowerCase().includes(q)) return true;
if (CATEGORY_LABELS[entry.category].toLowerCase().includes(q)) return true;
if (entry.fields.some(f => f.label.toLowerCase().includes(q))) return true;
return false;
}
```
Search bar uses the existing `TextFieldMD3` component. The search query is stored in local `useState` — no global state needed.
### Pattern 5: Inline SVG Icon Component
Icons are TSX components returning `