This site is password protected
', 'Enter the password to continue.
', "', "", 'import { PASSWORD_PAGE_ROUTE, SIGN_IN_ROUTE, WALL_PAGE_HELPER_NAME } from './constants'
/** The TeleportHQ wordmark, inline so the page needs no asset behind the wall. */
const TELEPORT_LOGO_SVG =
''
const escapeForJsString = (value: string): string =>
value.replace(/\\/g, '\\\\').replace(/'/g, "\\'").replace(/\n/g, ' ')
/**
* `utils/site-wall-page.js`: the password page as HTML, rendered by the
* sign-in route — a route can answer with any status, which a Next.js page
* cannot promise, and the wall needs its 401 so nothing behind it is indexed.
* Rendered on every request, never cached. The branding is TeleportHQ's; a
* workspace that pays for hosting may show its own logo instead (Project
* Settings).
*/
export const buildPasswordPageModule = (
options: { logoUrl?: string; siteTitle?: string } = {}
): string => {
const customLogo = options.logoUrl && /^https?:\/\//.test(options.logoUrl) ? options.logoUrl : ''
const title = escapeForJsString(options.siteTitle || '')
return `// GENERATED by TeleportHQ — the password page of the site's wall (see utils/site-wall.js, ${WALL_PAGE_HELPER_NAME}).
export var SITE_TITLE = '${title}';
export var CUSTOM_LOGO = '${customLogo}';
var SIGN_IN_ROUTE = '${SIGN_IN_ROUTE}';
var PASSWORD_PAGE = '${PASSWORD_PAGE_ROUTE}';
var TELEPORT_LOGO = ${JSON.stringify(TELEPORT_LOGO_SVG)};
function escapeHtml(value) {
return String(value)
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
var STYLES = [
"html, body { margin: 0; min-height: 100%; background: #f4f4f6; }",
"body { display: flex; align-items: center; justify-content: center; min-height: 100vh; padding: 24px; box-sizing: border-box; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; color: #121212; }",
".card { width: 100%; max-width: 420px; background: #fff; border-radius: 16px; box-shadow: 0 12px 40px rgba(18, 18, 18, 0.08); padding: 40px 32px 32px; box-sizing: border-box; text-align: center; }",
".logo { width: 100%; max-width: 260px; margin: 0 auto 28px; }",
".logo svg { width: 100%; height: auto; display: block; }",
".logo-custom { max-width: 220px; max-height: 120px; margin: 0 auto 28px; display: block; object-fit: contain; }",
"h1 { font-size: 20px; font-weight: 600; margin: 0 0 8px; }",
"p { font-size: 15px; line-height: 1.5; color: #55555f; margin: 0 0 24px; }",
"input { width: 100%; box-sizing: border-box; font-size: 16px; padding: 12px 14px; border: 1px solid #d6d6de; border-radius: 10px; outline: none; margin-bottom: 12px; }",
"input:focus { border-color: #121212; }",
"button { width: 100%; font-size: 16px; font-weight: 600; padding: 12px 14px; border: none; border-radius: 10px; background: #121212; color: #fff; cursor: pointer; }",
"button[disabled] { opacity: 0.7; cursor: default; }",
".error { font-size: 14px; color: #c62828; margin: 12px 0 0; min-height: 20px; }",
].join('\\n');
var SCRIPT = [
"(function () {",
" var form = document.getElementById('tq-wall-form');",
" var input = document.getElementById('tq-wall-password');",
" var button = document.getElementById('tq-wall-submit');",
" var error = document.getElementById('tq-wall-error');",
" form.addEventListener('submit', function (event) {",
" event.preventDefault();",
" var password = input.value.trim();",
" if (!password || button.disabled) return;",
" button.disabled = true;",
" button.textContent = 'Checking\\u2026';",
" error.textContent = '';",
" fetch('" + SIGN_IN_ROUTE + "', {",
" method: 'POST',",
" headers: { 'content-type': 'application/json', accept: 'application/json' },",
" body: JSON.stringify({ password: password }),",
" })",
" .then(function (response) { return response.status; })",
" .catch(function () { return 0; })",
" .then(function (status) {",
" if (status === 200) {",
" if (window.location.pathname === '" + PASSWORD_PAGE + "') { window.location.replace('/'); } else { window.location.reload(); }",
" return;",
" }",
" error.textContent = status === 401 ? 'That password is not right.' : status === 429 ? 'Too many tries. Wait a minute and try again.' : 'The password could not be checked right now. Try again in a minute.';",
" button.disabled = false;",
" button.textContent = 'Continue';",
" input.focus();",
" });",
" });",
"})();",
].join('\\n');
// The page, as HTML. Nothing in it is fetched from the site itself: the site's
// files sit behind the very wall the page stands in front of.
export function renderPasswordPage() {
var title = SITE_TITLE ? escapeHtml(SITE_TITLE) + ' \\u2014 password required' : 'Password required';
var logo = CUSTOM_LOGO
? ""
: "
Enter the password to continue.
', "', "", '