diff --git a/templates/repo/clone_buttons.tmpl b/templates/repo/clone_buttons.tmpl
index fb54b27c82..67a509835f 100644
--- a/templates/repo/clone_buttons.tmpl
+++ b/templates/repo/clone_buttons.tmpl
@@ -9,16 +9,7 @@
 		SSH
 	</button>
 {{end}}
-<!-- the value will be updated by initRepoCloneLink, the code below is used to avoid UI flicking  -->
-<input id="repo-clone-url" value="" size="1" readonly>
-<script>
-	(() => {
-		const proto = localStorage.getItem('repo-clone-protocol') || 'https';
-		const btn = document.getElementById(`repo-clone-${proto}`);
-		// it's ok if we don't find the btn here, initRepoCloneLink will take care of it
-		document.getElementById('repo-clone-url').value = btn ? btn.getAttribute('data-link') : '';
-	})();
-</script>
+<input id="repo-clone-url" class="js-clone-url" value="" size="1" readonly>
 <button class="ui basic icon button tooltip" id="clipboard-btn" data-content="{{.locale.Tr "copy_url"}}" data-clipboard-target="#repo-clone-url" aria-label="{{.locale.Tr "copy_url"}}">
 	{{svg "octicon-paste"}}
 </button>
diff --git a/templates/repo/clone_script.tmpl b/templates/repo/clone_script.tmpl
new file mode 100644
index 0000000000..48b7ad3299
--- /dev/null
+++ b/templates/repo/clone_script.tmpl
@@ -0,0 +1,23 @@
+<script>
+	// synchronously set clone button states and urls here to avoid flickering
+	// on page load. initRepoCloneLink calls this when proto changes.
+	// TODO: This localStorage setting should be moved to backend user config
+	// so it's available during rendering, then this inline script can be removed.
+	(window.updateCloneStates = function() {
+		const httpsBtn = document.getElementById('repo-clone-https');
+		const sshBtn = document.getElementById('repo-clone-ssh');
+		const value = localStorage.getItem('repo-clone-protocol') || 'https';
+		const isSSH = value === 'ssh' && sshBtn || value !== 'ssh' && !httpsBtn;
+
+		if (httpsBtn) httpsBtn.classList[!isSSH ? 'add' : 'remove']('primary');
+		if (sshBtn) sshBtn.classList[isSSH ? 'add' : 'remove']('primary');
+
+		const btn = isSSH ? sshBtn : httpsBtn;
+		if (!btn) return;
+
+		const link = btn.getAttribute('data-link');
+		for (const el of document.getElementsByClassName('js-clone-url')) {
+			el[el.nodeName === 'INPUT' ? 'value' : 'textContent'] = link;
+		}
+	})();
+</script>
diff --git a/templates/repo/empty.tmpl b/templates/repo/empty.tmpl
index 730284da20..99f662cd0b 100644
--- a/templates/repo/empty.tmpl
+++ b/templates/repo/empty.tmpl
@@ -37,7 +37,7 @@ git init
 {{if ne .Repository.DefaultBranch "master"}}git checkout -b {{.Repository.DefaultBranch}}{{end}}
 git add README.md
 git commit -m "first commit"
-git remote add origin <span class="clone-url"></span>
+git remote add origin <span class="js-clone-url"></span>
 git push -u origin {{.Repository.DefaultBranch}}</code></pre>
 								</div>
 							</div>
@@ -46,24 +46,11 @@ git push -u origin {{.Repository.DefaultBranch}}</code></pre>
 							<div class="item">
 								<h3>{{.locale.Tr "repo.push_exist_repo"}}</h3>
 								<div class="markup">
-									<pre><code>git remote add origin <span class="clone-url"></span>
+									<pre><code>git remote add origin <span class="js-clone-url"></span>
 git push -u origin {{.Repository.DefaultBranch}}</code></pre>
 								</div>
 							</div>
-							<!-- the clone-url content will be updated by initRepoCloneLink, the code below is used to avoid UI flicking  -->
-							<script>
-								(() => {
-									const proto = localStorage.getItem('repo-clone-protocol') || 'https';
-									const btn = document.getElementById(`repo-clone-${proto}`);
-									const cloneUrls = document.getElementsByClassName('clone-url');
-									// it's ok if we didn't find the btn here, initRepoCloneLink will take all the work
-									if (btn) {
-										for (let i = 0; i < cloneUrls.length; i++) {
-											cloneUrls[i].textContent = btn.getAttribute('data-link');
-										}
-									}
-								})();
-							</script>
+							{{template "repo/clone_script" .}}
 						{{end}}
 					{{else}}
 						<div class="ui segment center">
diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl
index 825eaed111..0734076eff 100644
--- a/templates/repo/home.tmpl
+++ b/templates/repo/home.tmpl
@@ -124,6 +124,7 @@
 				{{if eq $n 0}}
 					<div class="ui action tiny input" id="clone-panel">
 						{{template "repo/clone_buttons" .}}
+						{{template "repo/clone_script" .}}
 						{{if not .DisableDownloadSourceArchives}}
 						<button id="download-btn" class="ui basic jump dropdown icon button tooltip" data-content="{{.locale.Tr "repo.download_archive"}}" data-position="top right">
 							{{svg "octicon-download"}}
diff --git a/templates/repo/wiki/revision.tmpl b/templates/repo/wiki/revision.tmpl
index 577eb6e6c0..71b69220c6 100644
--- a/templates/repo/wiki/revision.tmpl
+++ b/templates/repo/wiki/revision.tmpl
@@ -7,6 +7,7 @@
 			<div class="ui eight wide column text right df ac je">
 				<div class="ui action small input" id="clone-panel">
 					{{template "repo/clone_buttons" .}}
+					{{template "repo/clone_script" .}}
 				</div>
 			</div>
 			<div class="ui header eight wide column">
diff --git a/templates/repo/wiki/view.tmpl b/templates/repo/wiki/view.tmpl
index 91a15f19e2..21affddc62 100644
--- a/templates/repo/wiki/view.tmpl
+++ b/templates/repo/wiki/view.tmpl
@@ -31,6 +31,7 @@
 			<div class="right fitted item">
 				<div class="ui action small input" id="clone-panel">
 					{{template "repo/clone_buttons" .}}
+					{{template "repo/clone_script" .}}
 				</div>
 			</div>
 		</div>
diff --git a/web_src/js/features/repo-common.js b/web_src/js/features/repo-common.js
index b0ecc5a651..1cf67401be 100644
--- a/web_src/js/features/repo-common.js
+++ b/web_src/js/features/repo-common.js
@@ -44,8 +44,6 @@ export function initRepoArchiveLinks() {
 }
 
 export function initRepoCloneLink() {
-  const defaultGitProtocol = 'https'; // ssh or https
-
   const $repoCloneSsh = $('#repo-clone-ssh');
   const $repoCloneHttps = $('#repo-clone-https');
   const $inputLink = $('#repo-clone-url');
@@ -54,41 +52,19 @@ export function initRepoCloneLink() {
     return;
   }
 
-  const updateUi = () => {
-    let isSSH = (localStorage.getItem('repo-clone-protocol') || defaultGitProtocol) === 'ssh';
-    // there must be at least one clone button (by context/repo.go). if no ssh, then there must be https.
-    if (isSSH && $repoCloneSsh.length === 0) {
-      isSSH = false;
-    } else if (!isSSH && $repoCloneHttps.length === 0) {
-      isSSH = true;
-    }
-    const cloneLink = (isSSH ? $repoCloneSsh : $repoCloneHttps).attr('data-link');
-    $inputLink.val(cloneLink);
-    if (isSSH) {
-      $repoCloneSsh.addClass('primary');
-      $repoCloneHttps.removeClass('primary');
-    } else {
-      $repoCloneSsh.removeClass('primary');
-      $repoCloneHttps.addClass('primary');
-    }
-    // the empty repo guide
-    $('.quickstart .empty-repo-guide .clone-url').text(cloneLink);
-  };
-  updateUi();
-
+  // restore animation after first init
   setTimeout(() => {
-    // restore animation after first init
     $repoCloneSsh.removeClass('no-transition');
     $repoCloneHttps.removeClass('no-transition');
   }, 100);
 
   $repoCloneSsh.on('click', () => {
     localStorage.setItem('repo-clone-protocol', 'ssh');
-    updateUi();
+    window.updateCloneStates();
   });
   $repoCloneHttps.on('click', () => {
     localStorage.setItem('repo-clone-protocol', 'https');
-    updateUi();
+    window.updateCloneStates();
   });
 
   $inputLink.on('click', () => {