Skip to main content

Routes

Status: Scaffolded 2026-09-24

Every path the site answers, in three groups: public pages anyone can load, the /app area that needs a session, and the three text routes for crawlers and agents.

Public​

RouteRendersData
/landing: what Vegan Grove is, this week's public events, the map teaserGET /api/stats, GET /api/events
/placesthe map, filters by type and vegan level, a list for the current viewportGET /api/places?bbox= from the browser as the map moves
/places/[slug]one place: name, type, vegan level, address, hours, photos, reviewsGET /api/places/:slug
/eventsupcoming public events by area and dateGET /api/events
/events/[slug]one event: when, where as far as the organizer allows, who is hosting, RSVP countGET /api/events/:slug
/groves and /groves/[slug]groves by area, and a grove's description with its public eventsGET /api/groves
/media and /media/[slug]the documentary and film library, click-to-load trailersGET /api/media
/guides and /guides/[slug]outreach, rights, vegan 101, sanctuary, nutritionGET /api/guides
/login, /signupforms posting to the session route handler
/privacy, /termsstatic

Public pages are server-rendered, never carry a session, and are cacheable. Nothing on them is personalized.

Authenticated: /app​

src/app/app/layout.tsx renders the member shell and is behind middleware.ts, which redirects a request without the vg_session cookie to /login?next=<path>. Inside:

RoutePurpose
/app/feedfriends, grove, or public scope
/app/messagesconversations, Socket.IO for live updates
/app/friendsfriends, requests, invite codes
/app/companionIvy, streaming over SSE
/app/settingshandle, avatar, home area, the privacy switches, sessions, delete account

All five are stubs in the scaffold: the layout, the gate, and the navigation exist; the screens render placeholders.

There is no profile route​

There is no /u/[handle], no /members, no /app/profile/[id]. Profiles are never public (ADR 0004), and a member's own profile is /app/settings. If a public-posts view ships later it will read GET /api/handles/:handle/posts, show the handle, the avatar, and those posts, and nothing else: no bio, no area, no friends, no counts, and it will not be called a profile.

Machine-readable routes​

/robots.txt (src/app/robots.ts): allow everything public, disallow /app and /api, point at the sitemap. Generated so the sitemap URL follows NEXT_PUBLIC_SITE_URL.

/sitemap.xml (src/app/sitemap.ts): the static public routes plus every approved place, published event, grove, media item, and guide, fetched from the API at request time and revalidated hourly. Nothing under /app, and no handle pages, because there are none.

/llms.txt (src/app/llms.txt/route.ts): a plain-text description of the site for language-model agents, with the public routes and a link to these docs. It says what the site is and where the public data lives; it does not enumerate members or anything behind a session.

Not found and errors​

not-found.tsx and error.tsx at the app root render on the site's own shell. A place or event the API answers 404 for, whether missing or not visible to the caller, renders the same not-found page; the web app does not try to tell the difference, matching the error-handling rule.