Files
OpenFrontIO/src/client/index.html
T
evanpelle e0b486320a add SEO & Open Graph (#1692)
## Description:

The first Google result contains a join code. Using the canonical should
tell Google to use openfront.io instead. Also add metadata for Open
Graph links. Set favicon in the index.html instead of Main.ts so google
can pick it up.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I have read and accepted the CLA agreement (only required once).

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2025-08-03 04:54:03 +00:00

458 lines
15 KiB
HTML

<!doctype html>
<html lang="en" class="h-full">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>OpenFront (ALPHA)</title>
<link rel="manifest" href="../../resources/manifest.json" />
<link
rel="icon"
type="image/x-icon"
href="../../resources/images/Favicon.svg"
/>
<!-- SEO -->
<link rel="canonical" href="https://openfront.io/" />
<meta
name="description"
content="Conquer the world in this multiplayer battle royale! Expand your nation, eliminate opponents, and dominate the map in this fast-paced IO game."
/>
<!-- Open Graph -->
<meta property="og:url" content="https://openfront.io/" />
<meta property="og:title" content="OpenFront - Battle Royale" />
<meta
property="og:description"
content="Conquer the world in this multiplayer battle royale! Expand your nation, eliminate opponents, and dominate the map in this fast-paced IO game."
/>
<meta
property="og:image"
content="https://openfront.io/resources/images/GameplayScreenshot.png"
/>
<meta property="og:type" content="game" />
<!-- Critical CSS to prevent FOUC -->
<style>
.preload * {
-webkit-transition: none !important;
-moz-transition: none !important;
-ms-transition: none !important;
-o-transition: none !important;
transition: none !important;
}
html {
visibility: visible;
opacity: 1;
}
html.preload {
visibility: hidden;
opacity: 0;
}
.bg-image {
content: "";
background-image: url("/images/EuropeBackground.webp");
background-position: center;
background-attachment: fixed;
background-size: cover;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
filter: blur(4px);
z-index: -1;
}
.dark .bg-image {
filter: blur(4px) brightness(0.4) saturate(0.3) contrast(1.2);
}
/* display:none if child has class parent-hidden since we can't use shadow DOM in Lit due to Tailwind */
.component-hideable:has(> .parent-hidden) {
display: none;
}
</style>
<!-- Immediate execution to prevent FOUC -->
<script>
document.documentElement.className = "preload";
</script>
<!-- Playwire ads -->
<script>
window.ramp = window.ramp || {};
window.ramp.que = window.ramp.que || [];
window.ramp.passiveMode = true;
</script>
<!-- Analytics -->
<script
async
src="https://www.googletagmanager.com/gtag/js?id=AW-16702609763"
></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "AW-16702609763");
</script>
<!-- Google tag (gtag.js) -->
<script
async
src="https://www.googletagmanager.com/gtag/js?id=G-WQGQQ8RDN4"
></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "G-WQGQQ8RDN4");
</script>
</head>
<body
class="h-full select-none font-sans min-h-screen bg-opacity-0 bg-cover bg-center bg-fixed transition-opacity duration-300 ease-in-out flex flex-col"
>
<header class="l-header">
<div class="l-header__content">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1364 259"
width="100%"
height="100%"
fill="currentColor"
class="l-header__logo"
>
<defs>
<linearGradient
id="logo-gradient"
x1="0%"
y1="0%"
x2="100%"
y2="0%"
>
<stop offset="0%" style="stop-color: #2563eb" />
<stop offset="100%" style="stop-color: #3b82f6" />
</linearGradient>
</defs>
<g>
<path
d="M0,174V51h15.24v-17.14h16.81v-16.98h16.96V0h1266v17.23h17.13v16.81h16.98v16.96h14.88v123h-15.13v17.08h-17.08v17.08h-16.9v17.04H324.9v16.86h-16.9v16.95h-102v-17.12h-17.07v-17.05H48.73v-17.05h-16.89v-16.89H14.94v-16.89H0ZM1297.95,17.35H65.9v16.7h-17.08v17.08h-14.5v123.08h14.85v16.9h17.08v17.08h139.9v17.08h17.08v16.36h67.9v-16.72h17.08v-17.07h989.88v-17.07h17.08v-16.9h14.44V50.8h-14.75v-17.08h-16.9v-16.37Z"
/>
<path
d="M189.1,154.78v17.07h-16.9v16.75h-51.07v-16.42h-16.9v-17.07h-16.97v-84.88h16.63v-17.07h16.9v-16.84h51.07v16.5h17.07v17.07h16.7v84.89h-16.54ZM137.87,53.1v17.15h-16.6v84.86h16.97v16.61h16.89v-16.97h16.6v-84.86h-16.97v-16.79h-16.89Z"
/>
<path
d="M273.91,104.06v-16.73h50.92v16.45h16.85v68.05h-16.44v17.06h-50.96v16.88h16.4v16.96h-67.28v-16.61h16.33v-101.86h-16.38v-16.98h33.4v16.63c6.12,0,11.72,0,17.31,0,0,22.56,0,45.13,0,67.75h33.59v-67.61h-33.73Z"
/>
<path
d="M631.12,188.64v-16.36h16.53V53.2h-16.25v-16.86h118.33v33.29h-16.65v-16.36h-50.72v50.44h33.36v-16.35h16.99v50.25h-16.6v-16.33h-33.73v50.65h16.37v16.72h-67.63Z"
/>
<path
d="M596.78,103.8v84.94h-33.54v-84.39h-34.03v84.25h-33.85v-101.29h84.5v16.49h16.93Z"
/>
<path
d="M1107.12,188.71v-84.34h-34.03v84.37h-33.7v-101.41h84.42v16.41h16.86v84.96h-33.54Z"
/>
<path
d="M988.1,171.78v16.87h-67.88v-16.38h-16.87v-68.06h16.38v-16.87h68.06v16.38h16.87v68.06h-16.55ZM970.78,104.35h-33.39v67.38h33.39v-67.38Z"
/>
<path
d="M460.77,155.38v16.49h-16.58v16.83h-68.05v-16.5h-16.83v-68.05h16.49v-16.83h68.05v16.49h16.83v34.06h-67.31v33.82h33.47v-16.31h33.92ZM393.39,104.18v16.56h33.3v-16.56h-33.3Z"
/>
<path
d="M1209.13,172h-16.9v-67.9h-16.96v-16.9h16.68v-17.08h16.9v-16.82h16.9v33.58h50.98v16.91h-50.4v67.96h16.48v-16.43h50.95v16.54h-16.55v16.76h-68.08v-16.6Z"
/>
<path
d="M834.91,120.94v16.96h-16.65v33.88h16.41v16.96h-67.29v-16.63h16.34v-67.87h-16.4v-16.97h50.42v33.81h17.3l-.14-.14Z"
/>
<path
d="M835.05,121.08v-33.75h33.76v16.43h16.85v33.96h-33.43v-16.79c-6.13,0-11.73,0-17.32,0,0,0,.14.14.14.14Z"
/>
</g>
</svg>
<div id="game-version" class="l-header__highlightText text-center">
Loading version...
</div>
</div>
</header>
<div class="bg-image"></div>
<gutter-ad-modal></gutter-ad-modal>
<!-- Main container with responsive padding -->
<main class="flex justify-center flex-grow">
<div class="container pt-12">
<o-button
id="login-discord"
title="Initializing..."
disable="true"
block
></o-button>
<o-button
id="logout-discord"
title="Log out"
translationKey="main.log_out"
visible="false"
block
></o-button>
<div class="container__row">
<flag-input class="w-[20%] md:w-[15%]"></flag-input>
<territory-patterns-modal class="w-[20%] md:w-[15%]">
<button
id="territory-patterns-input-preview-button"
class="w-full border p-[4px] rounded-lg flex cursor-pointer border-black/30 dark:border-gray-300/60 bg-white/70 dark:bg-[rgba(55,65,81,0.7)] justify-center"
title="Pick a pattern!"
></button>
</territory-patterns-modal>
<username-input class="relative w-full"></username-input>
<news-button
class="w-[20%] md:w-[15%] component-hideable"
></news-button>
</div>
<div></div>
<div>
<public-lobby class="block"></public-lobby>
</div>
<div class="container__row container__row--equal">
<o-button
id="host-lobby-button"
title="Create Lobby"
translationKey="main.create_lobby"
block
secondary
></o-button>
<o-button
id="join-private-lobby-button"
title="Join Lobby"
translationKey="main.join_lobby"
block
secondary
></o-button>
<!-- <o-button
id="chat-button"
title="Chat Test"
block
secondary
></o-button> -->
</div>
<o-button
id="single-player"
title="Single Player"
translationKey="main.single_player"
block
></o-button>
<o-button
id="help-button"
title="Instructions"
translationKey="main.instructions"
block
secondary
></o-button>
<div class="container__row">
<lang-selector class="w-full"></lang-selector>
</div>
</div>
</main>
<!-- User Setting -->
<button
id="settings-button"
title="Settings"
class="fixed bottom-4 right-4 z-50 rounded-full p-2 shadow-lg transition-colors duration-300 flex items-center justify-center"
style="width: 80px; height: 80px; background-color: #0075ff"
>
<img
src="../../resources/images/SettingIconWhite.svg"
alt="Settings"
style="width: 72px; height: 72px"
/>
</button>
<!-- Game components -->
<div id="customMenu" class="mt-4 sm:mt-6 lg:mt-8">
<ul></ul>
</div>
<div id="app"></div>
<div id="radialMenu" class="radial-menu"></div>
<div class="flex gap-2 fixed right-[10px] top-[10px] z-50 flex-col">
<options-menu></options-menu>
<player-info-overlay></player-info-overlay>
</div>
<div
class="fixed bottom-[30px] sm:bottom-auto sm:top-[20px] z-50 mx-auto max-w-max inset-x-0 items-center"
>
<heads-up-message></heads-up-message>
</div>
<div
class="bottom-0 w-full flex-col-reverse sm:flex-row z-50 md:w-[320px]"
style="position: fixed; pointer-events: none"
>
<div
class="w-full md:w-2/3 md:fixed sm:right-0 md:bottom-0 md:flex flex-col items-end"
style="pointer-events: none"
>
<chat-display></chat-display>
<events-display></events-display>
</div>
<div style="pointer-events: auto">
<control-panel></control-panel>
</div>
</div>
<!-- Footer section -->
<footer class="l-footer">
<div class="l-footer__content">
<div class="l-footer__col">
<a
href="https://youtu.be/jvHEvbko3uw?si=znspkP84P76B1w5I"
data-i18n="main.how_to_play"
class="t-link"
target="_blank"
>
How to Play
</a>
<a
href="https://openfront.miraheze.org/wiki/Main_Page"
data-i18n="main.wiki"
class="t-link"
target="_blank"
>
Wiki
</a>
<a
target="_blank"
href="https://discord.gg/jRpxXvG42t"
class="t-link"
>
<span data-i18n="main.join_discord"> Join the Discord! </span>
</a>
</div>
<div class="l-footer__col t-text-white">
<a
href="https://github.com/openfrontio/OpenFrontIO"
class="t-link inline-flex items-center space-x-2"
target="_blank"
>
©2025 OpenFront™
<img
src="../../resources/icons/github-mark-white.svg"
alt="GitHub"
width="20"
height="20"
class="ml-2 mr-4"
/>
</a>
<a
href="/privacy-policy.html"
data-i18n="main.privacy_policy"
class="t-link"
target="_blank"
>
Privacy Policy
</a>
<a
href="/terms-of-service.html"
data-i18n="main.terms_of_service"
class="t-link"
target="_blank"
>
Terms of Service
</a>
<p style="text-align: center">
<a
href="https://www.playwire.com/contact-direct-sales"
data-i18n="main.advertise"
class="t-link"
target="_blank"
rel="noopener"
>Advertise</a
>
</p>
</div>
</div>
</footer>
<!-- Game modals and overlays -->
<single-player-modal></single-player-modal>
<host-lobby-modal></host-lobby-modal>
<join-private-lobby-modal></join-private-lobby-modal>
<emoji-table></emoji-table>
<build-menu></build-menu>
<win-modal></win-modal>
<game-starting-modal></game-starting-modal>
<game-top-bar></game-top-bar>
<unit-display></unit-display>
<div class="flex fixed top-[20px] right-[20px] z-[1000] items-start gap-2">
<replay-panel></replay-panel>
<game-right-sidebar></game-right-sidebar>
</div>
<settings-modal></settings-modal>
<player-panel></player-panel>
<help-modal></help-modal>
<dark-mode-button></dark-mode-button>
<alert-frame></alert-frame>
<chat-modal></chat-modal>
<user-setting></user-setting>
<multi-tab-modal></multi-tab-modal>
<news-modal></news-modal>
<game-left-sidebar></game-left-sidebar>
<spawn-ad></spawn-ad>
<fps-display></fps-display>
<div
id="language-modal"
class="fixed inset-0 bg-black bg-opacity-50 z-50 hidden flex justify-center items-center"
>
<div class="bg-white rounded-lg shadow-lg p-6 w-96 max-w-full">
<h2 class="text-xl font-semibold mb-4">Select Language</h2>
<div
id="language-list"
class="space-y-2 max-h-80 overflow-y-auto"
></div>
<button
class="mt-4 w-full bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 rounded"
onclick="document.getElementById('language-modal').classList.add('hidden')"
>
Close
</button>
</div>
</div>
<!-- Scripts -->
<script>
// Remove preload class after everything is loaded
window.addEventListener("load", function () {
requestAnimationFrame(() => {
document.documentElement.classList.remove("preload");
});
});
window.addEventListener("beforeunload", function (e) {
e.preventDefault();
e.returnValue = "Are you sure you want to leave?";
});
</script>
<!-- Playwire ads -->
<script async src="//cdn.intergient.com/1025558/75940/ramp.js"></script>
<!-- Analytics -->
<script
defer
src="https://static.cloudflareinsights.com/beacon.min.js"
data-cf-beacon='{"token": "03d93e6fefb349c28ee69b408fa25a13"}'
></script>
</body>
</html>