diff --git a/site/src/pages/TemplateBuilder/ModuleSelectStep.tsx b/site/src/pages/TemplateBuilder/ModuleSelectStep.tsx index 993cdf3b8c..ce7954020e 100644 --- a/site/src/pages/TemplateBuilder/ModuleSelectStep.tsx +++ b/site/src/pages/TemplateBuilder/ModuleSelectStep.tsx @@ -70,6 +70,40 @@ const ConflictWarning: FC = ({ moduleA, moduleB }) => { ); }; +// Preferred display order for modules. Modules in this list appear first, +// in this order. Unlisted modules appear after, in their original order. +const MODULE_PRIORITY: readonly string[] = [ + "claude-code", + // "codex", + "cursor", + "vscode-desktop", + "code-server", + "jetbrains", + "vscode-web", + "zed", + // "antigravity", + "windsurf", + "git-clone", + "dotfiles", + "git-config", + "personalize", + "filebrowser", + // "kasmvnc", +]; + +function sortByPriority( + items: readonly T[], + priority: readonly string[], +): T[] { + const indexMap = new Map(priority.map((id, i) => [id, i])); + const fallback = priority.length; + return [...items].sort((a, b) => { + const ai = indexMap.get(a.id) ?? fallback; + const bi = indexMap.get(b.id) ?? fallback; + return ai - bi; + }); +} + export const ModuleSelectStep: FC = ({ baseId, selectedModuleIds, @@ -78,14 +112,15 @@ export const ModuleSelectStep: FC = ({ const { data, error, isLoading } = useQuery(templateBuilderModules(baseId)); const [moduleSearchText, setModuleSearchText] = useState(""); const modules = data?.modules ?? []; + const sortedModules = sortByPriority(modules, MODULE_PRIORITY); const categories = [ - ...new Set(modules.map((module) => module.category)), + ...new Set(sortedModules.map((module) => module.category)), ].sort((a, b) => a.localeCompare(b)); const [selectedFilterTab, setSelectedFilterTab] = useState("All"); const searchedModules = useFuzzySearch({ - allItems: modules, + allItems: sortedModules, searchText: moduleSearchText, searchProperties: ["display_name", "description"], });