Skip to content

setrf/thistouristdoesnotexist

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

thistouristdoesnotexist

Minimal UI image stream: every page load returns one random photo, rendered inside a bare HTML shell with no text chrome. The image response is uncached so it changes on every refresh.

October 2025: The root path now serves a lightweight HTML wrapper that embeds Google Analytics property G-4CHJNC8WWB, displays the random image inside an <img> tag, and still sources content from nginx random_index. Direct links under /photos/… continue to return raw images.

Live

Overview

  • Purpose: Serve a different image on each request for playful “this person/place does not exist” vibes, wallpapers, or inspiration.
  • UX: Hitting / serves the minimal HTML shell, which immediately loads /photos/?v=<timestamp> to fetch a random file; deep links under /photos/<filename> serve that exact file.
  • Simplicity: No app server — implemented directly in nginx via random_index.

How It Works

  1. Incoming GET / serves index.html, an ultra-minimal page that immediately requests /photos/?v=<timestamp> inside an <img> element.
  2. nginx location = /photos/ enables random_index on; which selects a random file within the directory and returns its contents.
  3. Caching is turned off (Cache-Control: no-store) to prevent browsers/CDNs from reusing the same image.

Directory Layout

/var/www/apps/thistouristdoesnotexist/
├─ photos/            # Put your images here (the random pool)
└─ analytics/         # Optional: static HTML analytics reports (GoAccess)

Add/Manage Photos

  • Upload path: /var/www/apps/thistouristdoesnotexist/photos/
  • Methods: SFTP, scp, or rsync from your machine.
    • Example (rsync): rsync -avz ./my-photos/ root@<droplet>:/var/www/apps/thistouristdoesnotexist/photos/
  • Supported formats: .jpg, .jpeg, .png, .gif, .webp, .svg.
  • Permissions: typical 0644 (rw‑r‑‑r‑‑); directory owned by root and readable by nginx.
  • Live updates: adding/removing files takes effect immediately; no reload needed.

Content Tips

  • Keep only image files in photos/ — random_index returns any file in the folder.
  • Prefer reasonably sized files (e.g., ≤ 2–4 MB). For faster loads on mobile, consider ≤ 1 MB.
  • Optimize images (lossy JPEG/WebP) and strip EXIF when privacy matters.
  • Name files however you like; order doesn’t affect selection.

Nginx Config (Installed)

server {
  listen 443 ssl; listen [::]:443 ssl;
  server_name thistouristdoesnotexist.com www.thistouristdoesnotexist.com;

  # Serve analytics if present
  location ^~ /analytics/ {
    root /var/www/apps/thistouristdoesnotexist;
    try_files $uri $uri/ =404;
  }

  # / -> /photos/ (internal)
  rewrite ^/$ /photos/ last;

  # Return a random file from photos (no caching)
  location = /photos/ {
    root /var/www/apps/thistouristdoesnotexist;
    random_index on;
    expires off;
    add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0" always;
  }

  # Direct file access (no listing; no caching)
  location ^~ /photos/ {
    root /var/www/apps/thistouristdoesnotexist;
    autoindex off;
    try_files $uri =404;
    expires off;
    add_header Cache-Control "no-store, no-cache, must-revalidate, max-age=0" always;
  }

  # Security headers
  add_header X-Content-Type-Options nosniff;
  add_header X-Frame-Options SAMEORIGIN;
  add_header Referrer-Policy no-referrer-when-downgrade;
}

server {
  listen 80; listen [::]:80;
  server_name thistouristdoesnotexist.com www.thistouristdoesnotexist.com;
  return 301 https://$host$request_uri;
}

HTTPS

  • Let’s Encrypt via Certbot is enabled for apex + www; HTTP redirects to HTTPS.
  • Renewal test: sudo certbot renew --dry-run

Analytics & Logs

  • Per‑site access log: /var/log/nginx/thistouristdoesnotexist.com.access.log (if configured).
  • Static analytics (optional): /var/www/apps/thistouristdoesnotexist/analytics/index.html.
    • Generated by cron every 5 minutes via /usr/local/bin/update-goaccess-reports and GoAccess.
  • Runtime logs: /var/log/nginx/access.log, /var/log/nginx/error.log.

Runbook

  • Add new photos:
    1. Upload files into photos/ via SFTP/rsync.
    2. Verify: curl -I https://thistouristdoesnotexist.com/ (check 200 and Content-Type: image/*).
  • Remove a photo:
    • Delete from photos/; randomness updates immediately.
  • Validate config/reload nginx (if you ever change nginx):
    • sudo nginx -t && sudo systemctl reload nginx
  • Disk usage checks:
    • du -sh /var/www/apps/thistouristdoesnotexist/photos
  • Backups:
    • tar -C /var/www/apps -czf /root/backup-thistouristdoesnotexist-$(date +%F).tgz thistouristdoesnotexist/photos

Troubleshooting

  • Blank/404 on root:
    • Ensure at least one file exists in photos/.
    • Check: curl -I https://thistouristdoesnotexist.com/photos/<existing-filename>200.
  • Same image repeats:
    • True randomness can repeat; with few files, repeats are common.
    • Also check that no intermediary (browser, proxy, CDN) is caching; headers send no-store.
  • Wrong MIME type:
    • nginx infers from extension; verify the file’s extension matches its content.
  • Slow loads:
    • Optimize or resize large images; consider WebP/AVIF for best size/quality trade‑off.

Local Preview (optional)

  • nginx random_index is server‑side, but you can quickly preview randomness with a tiny static server:
    • Node one‑liner (random file): npx http-server -p 8080 --silent & while true; do sleep 0.1; done (then manually hit random files), or
    • Minimal script idea: a tiny Node/Express route that picks a random file from a folder and res.sendFile(...).

Security & Privacy

  • Keep only images in photos/ (no HTML/JS executables).
  • Strip EXIF if you don’t want to leak GPS/camera metadata.
  • Directory listing is disabled; only direct file paths and the random endpoint are served.

Extensibility Ideas

  • Weighted randomness (e.g., newer files more likely) — requires a small server shim.
  • Category subfolders /photos/<tag>/ with random per tag.
  • Add a simple HTML wrapper page that centers the image and offers copy/download.

FAQ

  • Q: Can I put this behind a CDN?
    • A: Yes, but disable caching on / and /photos/ or vary by a cache‑busting header, otherwise randomness will be lost.
  • Q: Can I guarantee no repeats for N requests?
    • A: Not with pure random_index. Implement a server with a small stateful shuffle queue if you need non‑repeating draws.

License

  • Content (images) copyright remains yours. Server config and docs follow the repository’s license.

About

Zero‑UI random image site (nginx random_index). Each refresh returns a different photo; no caching.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages