# Verj

Verj is one app (`index.html`) with five tabs: **Map**, **Venues**, **Pod**, **Meetups**, and **You**.

- **Map** — one shared map: every venue pin (coloured by live signal), your Pod's people, meetup pins, and place talk. Tapping a venue opens one sheet with its signals, Pod notes, "Suggest a meetup here", and "Suggest for the vote".
- **Venues** — tonight's signal board, venue detail, crowd check-ins, plus what open Pods are talking about and other Pods open to vibe.
- **Pod** — start or join a Pod (optional — you can browse venues without one), members, invite link and QR code, leader controls, and the group vote.
- **Meetups** — rendezvous suggestions, RSVPs, and ETAs.
- **You** — optional sign-in (it fills in your Pod name), pace profile, and venue-operator specials.

`demo.html` now just redirects to the app, keeping `?room=` and `?venue=`, so older invitation links and QR codes still work.

## Verj Pod — five-person shared location

### Tabs and mobile map

Joining a Pod opens the map. On phones, navigation stays at the bottom and the map fills the remaining screen; the expand button opens a full-screen map. Map tools center your location or fit your Pod. Location sharing and meetup suggestions open compact sheets. Leader settings and QR invitations live in the Pod tab. The design uses the supplied Verj logo, black and white surfaces, and the signature gradient.

### Pod leader and social discovery

The Pod leader has a private control panel for its name and vibe: **Single and ready to mingle**, **Vibing on our own**, **Here to meet new friends**, or **Leave us alone**. Everyone in the room sees the current vibe.

Discovery is off by default. For the two open vibes (single/friends), the leader can explicitly share a selected Shelby Farms or Huey's meetup spot with other active Pods. The directory and map publish only the Pod name, group vibe, and chosen public spot; they do not publish personal live locations, member names, invitations, or access credentials. The shared spot is a leader-selected meeting place, not a claim that members are physically there. Quiet vibes stay out of discovery, and inactive/expired rooms disappear.

The leader can transfer leadership to another active room member. The recipient immediately gains all leader controls, and the previous leader remains a regular member. Existing vibe, visibility, distance, timer, meetups, and RSVPs are preserved. If a leader leaves or times out, the next active member takes over.

Run `npm install` (once), then `npm start`, and open [Verj](http://localhost:3000/).
Create a room, copy its invitation link, and open it in up to four other tabs or devices.
Or have friends scan the room's **Scan to join** QR code with their phone camera and tap the link. Each person still enters their name and consents before joining. Use the live HTTPS demo for phone scanning, since localhost links only work on the host computer. QR codes are generated in the browser using the bundled MIT-licensed `qr-creator` library.
Each participant chooses a display name and agrees to share with the room. No account or database is required.

- Choose **Share my live location** to show GPS positions, or select a clearly labeled simulated test spot.
- Choose the same test spot in two tabs to see **Time to vibe!**. Move one to another spot to clear the alert.
- The host chooses the nearby and restaurant arrival radius from 100 to 5,000 meters (default 250). Everyone shares the same setting. The next participant becomes host when the current host leaves or expires.
- Test spots include Shelby Farms and all ten Huey's locations, plus the original three sample spots. Shelby Farms uses its City of Memphis park polygon; Huey's coordinates come from the map pins on the official restaurant pages. See `data/demo-spots.json` for per-location sources. The 2025 Census Tennessee area-landmark shapefile was checked but contained no named Shelby Farms feature.
- Group arrivals appear in the page and optional device notifications. GPS accuracy must be 100 meters or better and arrivals confirm after six seconds inside the spot. Test arrivals are immediate and labeled. Remaining at a spot does not repeatedly alert. Restaurant exits allow a 40-meter buffer to reduce GPS edge jitter. Recent arrival notices last up to ten minutes, with at most 20 stored per active participant.
- Nearby pairs match within the host's distance or anywhere inside the same named spot, including the park. GPS and test positions do not match each other.
- **Rendezvous point:** after joining, tap the map (or use your shared location), name the point, and suggest a future time within seven days. All room members see the suggestion and map marker, with optional device alerts. Times are stored as UTC and displayed in each person's local time zone. The proposer or host can cancel a suggestion. A room can hold five suggestions; each clears an hour after its proposed time. Suggestions persist only while the demo room has active participants; no scheduled or background reminder is sent.
- **RSVPs and ETAs:** choose **I'm coming** and share your own estimated minutes until arrival (1–240). The group sees your estimated arrival time; update it, mark yourself arrived, or cancel your RSVP. These are participant-provided estimates, not traffic or routing predictions. GPS/test spot arrivals remain separate from manually marking yourself arrived.
- **Room expiry:** a new room lasts at most two hours by default. The host can reset the countdown to 15–480 minutes from now. The server enforces expiration even while members remain active. Meetup times and ETAs must precede room expiry. Expired/closed invitations cannot recreate the room; create a new room for a new invite. If everyone disconnects, the empty room can close earlier.
- The server enforces five active participants **per room**. A sixth gets a room-full message.
- Locations refresh every 3 seconds, expire after 30 seconds, and inactive participants expire after 45 seconds. Leaving frees a slot immediately; stopping sharing clears the location at the next successful sync.
- Alerts always appear in the page. Optional device notifications depend on browser support and permission. Keep the demo open; background push is not included.

For phones, run one Node server and share its HTTPS address (localhost works on the host computer only). All participants must use the same server. Plain HTTP on a LAN supports test spots but usually cannot use GPS.

On Vercel, rooms are shared through PostgreSQL using the integration-provided `POSTGRES_URL`, with `DATABASE_URL` as a fallback. A locked transaction enforces capacity across simultaneous requests and separate server instances. Demo data lives in the `tempace_private.demo_state` table, outside the public API schema. Expired locations and people are excluded from responses and removed on the next demo request. No location history is collected. With no database configured, local development uses temporary memory instead.

Anyone with an invitation can join until the room is full, so only share invitations with intended participants. This storage design is for a small demo, with up to 100 rooms and five people per room.

Deploy to the linked Vercel project with `npx vercel --prod`. Production needs a working `POSTGRES_URL` or `DATABASE_URL` with permission to create the private demo schema. HTTPS on Vercel supports browser GPS permission prompts.

Run `npm test` for the room capacity, location, proximity, authorization, and expiry checks.
For the database integration test, set `RUN_DEMO_DB_TESTS=1` and run `node --test tests/demo-database.test.js`. It creates temporary test participants, verifies two independent servers share a room, and removes its participants afterward.

Verj is a privacy-first nightlife discovery prototype based on the requirements in `App Development V1.docx`. The experience turns anonymous user presence into translated venue signals instead of exposing raw people counts or personally identifying information.

## What's included

- `index.html`: single-page app shell
- `styles.css`: responsive visual system with nightlife-oriented styling
- `app.js`: mock data plus launch-rule logic for signal strength, crowd size, social vibe, and age bands
- `docs/product-requirements.md`: product scope and MVP expectations
- `docs/technical-design.md`: recommended architecture and implementation path
- `docs/privacy-and-safety.md`: privacy constraints and safety guardrails

## How to run

Because this is a dependency-free front-end prototype, you can run it with any static file server.

Example with Python:

```bash
python -m http.server 8000
```

Then open `http://localhost:8000`.

## Prototype goals covered

- Nightlife-focused version 1 with bars, lounges, and restaurants
- Anonymous user profile inputs from the brief
- Privacy-safe translation logic for age bands and relationship status
- Launch fallback for crowd prompts when live traffic is thin
- Historical-data labeling that stays separate from live signal
- Development documentation for continuing into backend and mobile builds

## Suggested next build steps

1. Move mock venue data into a backend service.
2. Add authenticated business dashboards for specials and venue metadata.
3. Implement background location collection only after explicit consent, policy review, and retention limits are finalized.
4. Build map and detail views from the same translation layer used by the cards.
