BeamNG.Earth
A 1:1 scale streamed Earth for BeamNG.drive: real elevation and satellite imagery, floating origin, LOD streaming from a companion server
Photo scavenger hunts for friends, families, and teams. Pick a list, share a code, and race to photograph everything on it.
GamesRuby · HTMLGitHub @ericsaupeOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Photo scavenger hunt web app to play with your friends, family, and coworkers.
Taken from the repository README
Loading the full README.
Read the full README ↗Scavenger Hunt Party! is a simple web app to manage the experience of a photo scavenger hunt. A photo scavenger hunt is a scavenger hunt where the participants are required to take a photo or video of the item for it to count as being found. When the scavenger hunt is over all participants can see the results as well as the photos and videos taken by others.
bin/setupbin/devbin/test[__NSCFConstantString initialize] may have been in progress in another thread when fork() was called
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES before running the server.Photos and videos go straight from the browser to the storage service with Active Storage direct uploads, then the form sends the signed blob id to the app. In production the service is S3 (config/storage.yml), so the bucket needs a CORS rule that lets the site PUT objects and read the ETag header back. In the bucket's Permissions → Cross-origin resource sharing add:
[
{
"AllowedHeaders": ["Content-Type", "Content-MD5", "Content-Disposition"],
"AllowedMethods": ["PUT"],
"AllowedOrigins": ["https://scavengerhunt.party"],
"ExposeHeaders": ["ETag", "Origin"],
"MaxAgeSeconds": 3600
}
]
Add every origin the app is served from (staging, custom domains) to AllowedOrigins. Without the rule the browser blocks the upload and teams see the "couldn't be uploaded" banner on every attempt. Development and test use the Disk service, which needs no CORS setup.
Videos are limited to 150 MB and 60 seconds (Submission::MAX_VIDEO_BYTES, Submission::MAX_VIDEO_SECONDS); the browser checks both before uploading, the server checks the size when the upload lands, and the worker probes the duration with ffprobe before converting and refuses clips that are too long with a banner on the team's page. Photos are compressed in the browser before upload. A photo captured before the hunt ended is still accepted for 15 minutes after the end (Hunt::LATE_UPLOAD_GRACE) so slow connections do not lose last-minute finds.
Phones upload whatever they record (iPhones send HEVC .mov files that many Android, Windows and Firefox browsers cannot play), so every video is converted on the worker by TranscodeVideoJob into an H.264 MP4 (high profile, level 4.2, at most 1920×1080 and 60 fps) and attached as Submission#playback, with a poster frame generated at the same time. The original stays attached as photo for the archive; Submission#media_url serves the playable version once it exists and the original until then, and the checklist shows "Processing video" in the meantime. The job probes every upload first (ignoring any metadata the client sent) and refuses clips over the limit or ones that did not upload completely by purging the photo and sending a banner over the team's submissions stream. ffmpeg and ffprobe only ever run through VideoTranscoder.run, which restricts them to plain files and the mov/mp4, matroska and webm demuxers and kills them after ten minutes. bin/rails videos:transcode_missing queues the conversion for videos uploaded before this existed. The whole thing sits behind the Flipper feature video_transcoding, enabled by a migration; bin/rails runner 'Flipper.disable(:video_transcoding)' from a Render shell switches it off without a deploy: nothing is queued, queued jobs do nothing, and every page serves the originals again with no posters or processing state. Converted files stay in storage and are served again after Flipper.enable(:video_transcoding).
The conversion needs ffmpeg and ffprobe. Render has no package manager, so bin/install-ffmpeg downloads a pinned static Linux build into vendor/ffmpeg/ during both the web and worker builds (checked against its SHA-256) and production points config.active_storage.paths at it. Development uses whatever is on PATH (brew install ffmpeg); without it videos still upload but are never converted. The test suite never runs the real programs: spec/support/bin/ holds stand-ins that copy a fixture and print canned probe output.
Phones that installed the app and allowed notifications get a push when a hunt is five minutes from starting, when it is over and the results are up, when the photo show starts and when a new team takes the lead. Pushes are signed with VAPID keys from the Rails credentials. Generate a pair once:
bin/rails runner 'key = WebPush.generate_key; puts "public_key: #{key.public_key}", "private_key: #{key.private_key}"'
Then add them with bin/rails credentials:edit:
vapid:
subject: mailto:[email protected]
public_key: <public key>
private_key: <private key>
VAPID_PUBLIC_KEY, VAPID_PRIVATE_KEY and VAPID_SUBJECT environment variables work too. Without keys the opt-in sheet and the notification settings stay hidden and nothing is sent. The test environment generates a throwaway pair at boot. Rotating the keys invalidates every existing subscription, so phones have to allow notifications again.
Subscriptions live in push_subscriptions, one per phone and hunt, keyed by the viewer's user_id cookie. Only endpoints on the browsers' own push services (Google, Mozilla, Apple, Microsoft; see PushSubscription::PUSH_SERVICES) are accepted, so the worker never posts to an address a viewer made up; add a browser's service there if its subscriptions are refused. Push services answer 404 or 410 for a phone that revoked its subscription; those rows are deleted the next time a notification goes out.
One of the features of Scavenger Hunt is ready made hunt templates. These are loaded in during app boot from app/templates. To create a new scavenger hunt template just make a new YAML file in app/templates that is structured like a Hunt model with associated Categorys and Items.