Ben Hancock

Eliminating Redundant Repos in the Netlify CLI's sites:create-template command


tl;dr: The sites:create-template command had a backwards flow that created GitHub repositories before validating user-inputted site names, littering users’ accounts with empty repos whenever they picked an unavailable name. Dylan and I fixed this by implementing upfront validation and idempotent retry logic. The command now also auto-links the user’s CLI client to new sites.

Dylan Spyer and I recently collaborated on a series of open-source contributions to the Netlify CLI. We decided to implement a longstanding request to automatically link the CLI client to sites created with sites:create-template command so that users can begin running other commands for that site without first running the link command. But when we actually started using the command, we discovered it had some bugs and architectural issues we needed to sort out first.

The core issue was with the command’s API call flow. Users who wanted to create a site from a template would input a site name, and the command would create a GitHub repository for it. But only after creating the repo would it check whether that site name was actually available to use on Netlify. So whenever someone entered an already-taken name, they’d end up with an extra empty repo in their GitHub account.

User enters site name → Repository created → Site name unavailable → User tries again → Another repository created → Site name still unavailable…

This behavior existed because Netlify’s API requires repository metadata in order to create the site (and in the process, validate the site name), so the sites:create-template command needed to create the repo first to have that information ready to make the API call. The tradeoff was that site name validation happened after repository creation, which led to the redundant repos issue.

Because there is no existing API endpoint for simply testing if a site name is valid, we addressed this by adding new validation earlier in the flow with two upfront checks before any GitHub API calls: first a global availability check via a fetch to the Netlify URL with that site name, then a query to Netlify’s ListSites API to verify the name isn’t taken in the user’s account. This catches most unavailable names before any repos get created.

For the rare edge cases where both checks pass but the name is somehow still unavailable (like when a site exists/is taken by another user’s account but returns a 404), we implemented idempotent retry logic that persists the created repo’s information and reuses it on subsequent attempts instead of creating any redundant repositories.

One tradeoff: in those edge cases, users might end up with a repo name that doesn’t match their final site name. We considered adding a GitHub API call to rename the repo automatically, but given the added complexity, potential failure points, and how infrequently this would occur, we decided to keep the operation atomic and let users handle renames themselves if needed.

On top of these API call flow issues, we also addressed a collision issue where the “leave blank for random name” option only worked once per template — the command would use the template name (say, next-starter) as the repo name, so subsequent attempts with the same template would fail. Now we append random UUID suffixes to ensure uniqueness (next-starter-8e42)

Beyond the repo creation improvements, we enhanced error handling with actionable feedback (replacing non-specific “Warning: undefined.netlify.app already exists” messages), refactored utility functions into separate modules for better testability and code reuse, and replaced TypeScript error suppressions with proper type definitions.

And with all that sorted, we finally got to build the auto-linking feature we originally wanted. sites:create-template now links to the new site automatically and has significantly better fault tolerance overall. You can give these improvements a go as of version 17.38.0!