Найден корректный robots.txt
Файл управления сканированием сайта роботами
?
Robots.txt указывает поисковым роботам, какие страницы сканировать, а какие — нет. Ошибки в файле могут случайно закрыть важные разделы от индексации.
Robots.txt настроен корректно. Размер файла: 18093 байт. Загружен за: 1сек.
Проверяемая страница не запрещена в robots.txt.
Показать содержимое robots.txt
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>404 — Tyler</title>
<link rel="stylesheet" href="/css/style.css">
<style>
.lost {
display: flex;
justify-content: center;
align-items: center;
flex: 1;
padding: 2rem;
text-align: center;
}
.lost__inner {
max-width: 480px;
}
.lost__code {
font-size: clamp(6rem, 20vw, 12rem);
font-weight: 700;
letter-spacing: -0.04em;
line-height: 1;
margin-bottom: 1rem;
position: relative;
display: inline-block;
cursor: default;
}
.lost__zero {
display: inline-block;
animation: spin 8s linear infinite;
transform-origin: center;
}
.lost__zero:hover {
animation-duration: 0.4s;
}
.lost__msg {
font-size: 1.1rem;
color: var(--text-secondary);
margin-bottom: 0.5rem;
line-height: 1.6;
}
.lost__sub {
font-size: 0.85rem;
color: var(--text-secondary);
opacity: 0.6;
margin-bottom: 2rem;
}
.lost__links {
display: flex;
gap: 1.5rem;
justify-content: center;
flex-wrap: wrap;
margin-top: 2.5rem;
opacity: 0.5;
}
.lost__links a {
font-weight: 600;
font-size: 0.95rem;
border-bottom: 1px solid var(--border);
transition: border-color 0.2s;
}
.lost__email-prompt {
margin-top: 2.5rem;
font-size: 0.85rem;
color: var(--text-secondary);
}
.lost__email-btn {
display: inline-block;
margin-top: 0.75rem;
padding: 0.5rem 1.2rem;
background: var(--text);
color: var(--bg);
border: none;
border-radius: 6px;
font-size: 0.85rem;
font-weight: 600;
font-family: inherit;
cursor: pointer;
transition: opacity 0.2s;
}
.lost__email-btn:hover { opacity: 0.85; }
.lost__tried {
margin-top: 2rem;
font-size: 0.75rem;
color: var(--text-secondary);
opacity: 0.4;
font-style: italic;
}
/* ---- Game ---- */
.game-overlay {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.5);
backdrop-filter: blur(4px);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
opacity: 0;
visibility: hidden;
transition: all 250ms ease;
padding: 1rem;
}
.game-overlay.visible {
opacity: 1;
visibility: visible;
}
.game-box {
background: var(--bg);
border: 1px solid var(--border);
border-radius: 12px;
padding: 1.5rem;
width: 100%;
max-width: 380px;
text-align: center;
transform: translateY(10px) scale(0.98);
transition: transform 250ms ease;
}
.game-overlay.visible .game-box {
transform: translateY(0) scale(1);
}
.game-box h3 {
font-size: 1rem;
font-weight: 700;
margin: 0 0 0.25rem;
}
.game-box p {
font-size: 0.8rem;
color: var(--text-secondary);
margin: 0 0 1rem;
line-height: 1.5;
}
.game-canvas-wrap {
position: relative;
width: 100%;
aspect-ratio: 3 / 1;
background: var(--card-bg);
border-radius: 8px;
overflow: hidden;
margin-bottom: 0.75rem;
touch-action: none;
cursor: pointer;
user-select: none;
-webkit-user-select: none;
}
.game-canvas-wrap canvas {
width: 100%;
height: 100%;
display: block;
}
.game-score {
font-size: 0.75rem;
color: var(--text-secondary);
margin-bottom: 0.75rem;
}
.game-hint {
font-size: 0.7rem;
color: var(--text-secondary);
opacity: 0.5;
margin-bottom: 0.75rem;
}
.game-close {
background: none;
border: none;
color: var(--text-secondary);
font-size: 0.8rem;
cursor: pointer;
font-family: inherit;
}
.game-close:hover { color: var(--text); }
.game-success {
display: none;
margin-top: 1rem;
}
.game-success p {
font-size: 0.8rem;
margin-bottom: 0.75rem;
}
.game-form {
display: flex;
flex-direction: column;
gap: 0.5rem;
text-align: left;
}
.game-form__row {
display: flex;
gap: 0.5rem;
}
.game-form__row input {
flex: 1;
}
.game-form input,
.game-form textarea {
width: 100%;
padding: 8px 10px;
background: var(--card-bg);
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text);
font-size: 0.85rem;
font-family: inherit;
outline: none;
resize: vertical;
transition: border-color 0.2s;
}
.game-form input::placeholder,
.game-form textarea::placeholder {
color: var(--text-secondary);
opacity: 0.5;
}
.game-form input:focus,
.game-form textarea:focus {
border-color: var(--hover);
}
.game-form .lost__email-btn {
width: 100%;
margin-top: 0.25rem;
}
.game-form .lost__email-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}
.game-form__sent p {
color: var(--hover);
font-weight: 600;
}
.game-form__error p {
color: #c9593a;
font-size: 0.8rem;
}
.game-form__email {
font-size: 0.75rem;
color: var(--text-secondary);
opacity: 0.6;
margin-top: 0.5rem;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="ribbon"></div>
<header class="site-header">
<a href="/" class="site-header__brand">TYLER</a>
<nav class="site-header__nav">
<a href="/blog">Blog</a>
<a href="/live">Live</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</nav>
<a href="/contact" class="site-header__cta">Hire Us</a>
</header>
<main class="lost">
<div class="lost__inner">
<div class="lost__code">4<span class="lost__zero">0</span>4</div>
<p class="lost__msg" id="lostMsg">This page doesn't exist. Yet.</p>
<p class="lost__sub" id="lostSub">Maybe it never did. Maybe it's just vibes.</p>
<div class="lost__email-prompt">
Think this page should exist?
<br>
<button class="lost__email-btn" id="btnEmailChallenge">Send me an email</button>
</div>
<div class="lost__links">
<a href="/">home</a>
<a href="/blog">blog</a>
<a href="/live">live</a>
<a href="/about">about</a>
</div>
<p class="lost__tried" id="lostTried"></p>
</div>
</main>
<!-- Game Modal -->
<div class="game-overlay" id="gameOverlay">
<div class="game-box">
<h3>Prove you're not a bot</h3>
<p>Jump over 3 obstacles. Tap, click, or press space.</p>
<div class="game-canvas-wrap" id="gameWrap">
<canvas id="gameCanvas"></canvas>
</div>
<div class="game-score" id="gameScore">0 / 3</div>
<div class="game-hint" id="gameHint">tap anywhere to jump</div>
<div class="game-success" id="gameSuccess">
<p>You're clearly human. Probably.</p>
<form id="contactForm" class="game-form">
<div class="game-form__row">
<input type="text" id="contactName" placeholder="Your name" required autocomplete="name" />
<input type="email" id="contactEmail" placeholder="Your email" required autocomplete="email" />
</div>
<textarea id="contactMessage" rows="3" placeholder="Why should this page exist?" required></textarea>
<button type="submit" class="lost__email-btn" id="contactSubmit">Send</button>
</form>
<div class="game-form__sent" id="contactSent" style="display:none;">
<p>Sent! I'll take a look.</p>
</div>
<div class="game-form__error" id="contactError" style="display:none;">
<p>Something went wrong. Email me directly:</p>
</div>
<p class="game-form__email">tylermoore@gmail.com</p>
</div>
<button class="game-close" id="gameClose">nevermind</button>
</div>
</div>
<footer class="site-footer">
<a href="/" class="site-footer__brand">TYLER</a>
</footer>
<script src="js/main.js?v=2"></script>
<script>
// ---- Random messages ----
const messages = [
["This page doesn't exist. Yet.", "Maybe it never did. Maybe it's just vibes."],
["You found the void.", "It's nice here. Quiet."],
["Nothing to see here.", "Literally. There's nothing here."],
["This page is on vacation.", "It didn't leave a forwarding address."],
["Plot twist: the page was inside you all along.", "Just kidding. It's gone."],
["404: page not found.", "But you found yourself. And that's beautiful."],
["I built 230+ tutorials and this page wasn't one of them.", "My bad."],
["The page you're looking for is in another castle.", "Classic."],
["This URL is just a string of characters now.", "It used to mean something."],
["Even my 470K subscribers can't find this page.", "It's that lost."],
];
const pick = messages[Math.floor(Math.random() * messages.length)];
document.getElementById('lostMsg').textContent = pick[0];
document.getElementById('lostSub').textContent = pick[1];
const tried = window.location.pathname;
if (tried && tried !== '/') {
document.getElementById('lostTried').textContent = 'you tried: ' + tried;
}
// ---- Jump Game ----
const $overlay = document.getElementById('gameOverlay');
const $wrap = document.getElementById('gameWrap');
const $canvas = document.getElementById('gameCanvas');
const $score = document.getElementById('gameScore');
const $hint = document.getElementById('gameHint');
const $success = document.getElementById('gameSuccess');
const $close = document.getElementById('gameClose');
const $emailLink = document.getElementById('emailLink');
const ctx = $canvas.getContext('2d');
const GOAL = 3;
let W, H;
let running = false;
let animId = null;
let cleared = 0;
let gameOver = false;
// Player
const player = { x: 0, y: 0, w: 0, h: 0, vy: 0, grounded: true };
// Obstacles
let obstacles = [];
let obstacleTimer = 0;
let speed = 3;
let groundY = 0;
// Physics
const GRAVITY = 0.6;
const JUMP_FORCE = -10;
function getColors() {
const s = getComputedStyle(document.documentElement);
return {
text: s.getPropertyValue('--text').trim() || '#2c2420',
secondary: s.getPropertyValue('--text-secondary').trim() || '#8a7e76',
hover: s.getPropertyValue('--hover').trim() || '#d4724e',
border: s.getPropertyValue('--border').trim() || '#e8e0d8',
};
}
function resizeCanvas() {
const rect = $wrap.getBoundingClientRect();
const dpr = window.devicePixelRatio;
$canvas.width = rect.width * dpr;
$canvas.height = rect.height * dpr;
ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
W = rect.width;
H = rect.height;
groundY = H - 20;
player.w = 20;
player.h = 20;
player.x = W * 0.18;
player.y = groundY - player.h;
}
function jump() {
if (!running || gameOver) return;
if (player.grounded) {
player.vy = JUMP_FORCE;
player.grounded = false;
}
}
function spawnObstacle() {
const h = 14 + Math.random() * 18;
const w = 10 + Math.random() * 10;
obstacles.push({
x: W + 20,
y: groundY - h,
w: w,
h: h,
passed: false,
});
}
function update() {
// Player physics
if (!player.grounded) {
player.vy += GRAVITY;
player.y += player.vy;
if (player.y >= groundY - player.h) {
player.y = groundY - player.h;
player.vy = 0;
player.grounded = true;
}
}
// Obstacles
obstacleTimer++;
const spawnInterval = Math.max(60, 110 - cleared * 10);
if (obstacleTimer >= spawnInterval) {
spawnObstacle();
obstacleTimer = 0;
}
for (let i = obstacles.length - 1; i >= 0; i--) {
const o = obstacles[i];
o.x -= speed;
// Passed check
if (!o.passed && o.x + o.w < player.x) {
o.passed = true;
cleared++;
if (cleared >= GOAL) {
win();
return;
}
}
// Collision (generous margins)
const margin = 4;
if (
player.x + player.w - margin > o.x + margin &&
player.x + margin < o.x + o.w - margin &&
player.y + player.h > o.y + margin
) {
// Hit — reset
resetGame();
return;
}
// Off screen
if (o.x + o.w < -10) {
obstacles.splice(i, 1);
}
}
}
function draw() {
if (!running) return;
update();
ctx.clearRect(0, 0, W, H);
const c = getColors();
// Ground line
ctx.beginPath();
ctx.moveTo(0, groundY);
ctx.lineTo(W, groundY);
ctx.strokeStyle = c.border;
ctx.lineWidth = 2;
ctx.stroke();
// Ground dashes (scrolling)
ctx.strokeStyle = c.border;
ctx.lineWidth = 1;
ctx.globalAlpha = 0.3;
const dashOffset = (Date.now() * speed * 0.05) % 24;
for (let x = -dashOffset; x < W; x += 24) {
ctx.beginPath();
ctx.moveTo(x, groundY + 8);
ctx.lineTo(x + 10, groundY + 8);
ctx.stroke();
}
ctx.globalAlpha = 1;
// Player (circle)
const px = player.x + player.w / 2;
const py = player.y + player.h / 2;
const pr = player.w / 2;
ctx.beginPath();
ctx.arc(px, py, pr, 0, Math.PI * 2);
ctx.fillStyle = c.hover;
ctx.fill();
// Eyes (two dots facing right)
ctx.fillStyle = c.text;
ctx.globalAlpha = 0.7;
ctx.beginPath();
ctx.arc(px + 4, py - 3, 2, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(px + 4, py + 3, 2, 0, Math.PI * 2);
ctx.fill();
ctx.globalAlpha = 1;
// Shadow under player
ctx.beginPath();
ctx.ellipse(px, groundY, pr * 0.8, 3, 0, 0, Math.PI * 2);
ctx.fillStyle = c.text;
ctx.globalAlpha = 0.08;
ctx.fill();
ctx.globalAlpha = 1;
// Obstacles
for (const o of obstacles) {
ctx.fillStyle = c.text;
ctx.globalAlpha = 0.6;
ctx.beginPath();
// Triangle obstacle
ctx.moveTo(o.x + o.w / 2, o.y);
ctx.lineTo(o.x + o.w, o.y + o.h);
ctx.lineTo(o.x, o.y + o.h);
ctx.closePath();
ctx.fill();
ctx.globalAlpha = 1;
}
// Score
$score.textContent = cleared + ' / ' + GOAL;
animId = requestAnimationFrame(draw);
}
function resetGame() {
cleared = 0;
obstacles = [];
obstacleTimer = 0;
speed = 3;
player.y = groundY - player.h;
player.vy = 0;
player.grounded = true;
$hint.textContent = 'you hit one! try again';
setTimeout(() => { $hint.textContent = 'tap anywhere to jump'; }, 1500);
}
function startGame() {
cleared = 0;
obstacles = [];
obstacleTimer = 0;
speed = 3;
gameOver = false;
running = true;
$success.style.display = 'none';
$close.style.display = '';
$score.style.display = '';
$hint.style.display = '';
$hint.textContent = 'tap anywhere to jump';
resizeCanvas();
player.y = groundY - player.h;
player.vy = 0;
player.grounded = true;
draw();
}
function stopGame() {
running = false;
gameOver = true;
cancelAnimationFrame(animId);
}
function win() {
stopGame();
ctx.clearRect(0, 0, W, H);
$score.style.display = 'none';
$hint.style.display = 'none';
$close.style.display = 'none';
$success.style.display = 'block';
// Pre-fill the message with the missing page
document.getElementById('contactMessage').value = 'I think this page should exist: ' + window.location.href + '\n\n';
}
// Input — tap canvas, click anywhere in modal, or spacebar
$wrap.addEventListener('pointerdown', function(e) {
e.preventDefault();
jump();
});
document.addEventListener('keydown', function(e) {
if (e.code === 'Space' && running && !gameOver) {
e.preventDefault();
jump();
}
});
// Open / close
document.getElementById('btnEmailChallenge').addEventListener('click', function() {
$overlay.classList.add('visible');
startGame();
});
$close.addEventListener('click', function() {
stopGame();
$overlay.classList.remove('visible');
});
$overlay.addEventListener('click', function(e) {
if (e.target === $overlay) {
stopGame();
$overlay.classList.remove('visible');
}
});
window.addEventListener('resize', function() {
if (running) resizeCanvas();
});
// ---- Contact Form ----
document.getElementById('contactForm').addEventListener('submit', async function(e) {
e.preventDefault();
const btn = document.getElementById('contactSubmit');
btn.disabled = true;
btn.textContent = 'Sending...';
document.getElementById('contactError').style.display = 'none';
const data = {
name: document.getElementById('contactName').value.trim(),
email: document.getElementById('contactEmail').value.trim(),
message: document.getElementById('contactMessage').value.trim(),
page: window.location.pathname,
};
try {
const res = await fetch('./api/contact.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
});
const result = await res.json();
if (res.ok && result.success) {
document.getElementById('contactForm').style.display = 'none';
document.getElementById('contactSent').style.display = 'block';
} else {
document.getElementById('contactError').style.display = 'block';
}
} catch (err) {
document.getElementById('contactError').style.display = 'block';
}
btn.disabled = false;
btn.textContent = 'Send';
});
</script>
</body>
</html>