🧭 Trip order consistency across all surfaces — balionline.hu

Every utazás-listing surface honors the client's ranking field, in one consistent order (departure date soonest-first baseline, 'coming soon' last). Behavioral spec + Expected-Behavior Oracle.

Personas & jobs-to-be-done

Each journey is walked by a named protagonist (BMAD pattern): a concrete persona with a job-to-be-done trigger, so the spec reads as behaviour rather than abstract requirements.

2 personas5 scenariosslug trip-order-consistency
P1

Réka — first-time visitor anonymous visitor, browsing on desktop and mobile, comparing Bali trips before enquiring

JTBD: When I browse balionline.hu's trips across the homepage, the menu and the collection page, I want them in one consistent, sensible order (soonest departures first, 'coming soon' last) so that I can quickly find a trip I can actually book and trust that the site is current.

P2

Anna — Analit office admin (CMS editor) logged-in WordPress editor, non-technical, manages the trips from wp-admin

JTBD: When I want to feature a particular trip, I want to set its ranking number once in the CMS and have every page of the site honor that order, so that my featured trip leads everywhere without asking the developer.

Scenario catalog

Every distinct leaf path, classified happy / edge / failure / recovery. The proposed test-IDs are the bridge that plan-techspec reads from scenario_map.json to seed acceptance checks.

IDScenarioPersonaPathStepsProposed test-IDs
S1Visitor sees ONE consistent trip order across every surfaceP1🟢 happy6F2, F3, F4, F5, F6, C1
S2Client edits a trip's ranking number and it propagates to every surfaceP2🟢 happy7B3, F0, F1, F3, F4, F5, C1
S3Coming-soon placeholders are always pinned lastP1🟡 edge2F2
S4A trip with no ranking value is never dropped (data-loss guard)P2🟡 edge2F1, F3
S5Baseline & tie-break order = departure date, soonest firstP1🟡 edge2F3, F4, F5, C1

Scenarios — click-by-click step tables

Each row is one concrete UI interaction: who acts · the exact element clicked or seen · the copy shown · the system action · the resulting state · where it branches.

S1 — Visitor sees ONE consistent trip order across every surface 🟢 happy P1

Trigger: Réka opens balionline.hu and moves between the homepage, the nav dropdown, the collection page and a single trip's related-trips block.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userOpen balionline.hu and look at the trips block on the homepageBali trip cards (title + departure date per card)server-rendered WP_Query for post_type=utazas, shared orderinghomepage_trip_list_rendered
2userOpen the top-nav 'Utak' dropdown submenuDynamic trip links (the '<!-- Itt hívjuk be a dinamikus utakat -->' list)dynamic menu lists utazas posts via the shared orderingnav_dropdown_open
3userClick through to the collection page (/csoportos-utak-gyujtooldal/) and read Grid-1trip-card grid, h3.trip-title per cardpage template WP_Query for the bookable-trips grid, shared orderingcollection_grid1_rendered
4userScroll to the bottom of the collection page trips area'Tervezés alatt' placeholder cards (Thaiföld / Japán / Mexikó)placeholder grid rendered after the active gridplaceholders_visible
5userOpen a single trip (/utazas/<slug>/) and scroll to the related / other-trips blockrelated-trips cardssecondary WP_Query for related trips, shared orderingrelated_trips_rendered
6userView the homepage, nav dropdown and collection page at 375px mobile widthsame trip cards, reflowedresponsive layout, same query ordermobile_render

Proposed acceptance test-IDs: F2, F3, F4, F5, F6, C1

Expected-Behavior Oracle — the answer key the tests assert against
#You doYou should seeElement that changes (copy · look · where)What changes underneathMust NOT happen
1Open balionline.hu and look at the trips block on the homepageThe homepage trip block lists the active Bali trips, soonest departure first, with the same trips that appear elsewhere on the site.Copy: Trip cards in order T1, T2, T3 … · Look: grid of trip cards, each with title + date · Where: homepage trips sectionThe homepage order must NOT differ from the nav dropdown or the collection page; a 'coming soon' placeholder must NOT appear before a bookable trip.
2Open the top-nav 'Utak' dropdown submenuThe dropdown lists the SAME trips in the SAME order as the homepage.Copy: Trip links in order T1, T2, T3 … · Look: vertical dropdown menu list · Where: top navigation, under 'Utak'The nav order must NOT differ from the homepage / collection page (this is the original bug).
3Click through to the collection page (/csoportos-utak-gyujtooldal/) and read Grid-1Grid-1 (the bookable trips) shows the same trips in the same order, soonest departure first.Copy: trip-card titles in order T1, T2, T3 … · Look: responsive card grid (div.trips-grid > div.trip-card) · Where: main column of the collection pageA September-29 departure must NOT sit below an October one; the order must NOT be arbitrary or differ from the homepage/nav.
4Scroll to the bottom of the collection page trips areaThe 'Tervezés alatt' (coming-soon) cards appear LAST, after every bookable trip.Copy: 'Tervezés alatt' cards (Thaiföld, Japán, Mexikó) · Look: muted/secondary card grid · Where: below Grid-1, end of the trips areaA placeholder must NOT appear among or before the bookable trips.
5Open a single trip (/utazas/<slug>/) and scroll to the related / other-trips blockThe related/other-trips block uses the SAME ordering rule as the rest of the site.Copy: related trip cards in the shared order · Look: card row/grid · Where: lower section of the single-trip pageThe related-trips order must NOT use a different (e.g. publish-date or random) ordering.
6View the homepage, nav dropdown and collection page at 375px mobile widthThe trip order is identical at mobile and desktop on every surface.Copy: same order T1, T2, T3 … at 375px · Look: single-column reflow · Where: all listing surfaces, mobileThe order must NOT change between mobile and desktop.
Sub-flow — what the user sees & does (arrows carry the system detail)
flowchart TD
  S1U1(["Open balionline.hu and look at the trips block on the homepage"])
  S1U2(["Open the top-nav 'Utak' dropdown submenu"])
  S1U3(["Click through to the collection page (/csoportos-utak-gyujtoold…"])
  S1U4(["Scroll to the bottom of the collection page trips area"])
  S1U5(["Open a single trip (/utazas/<slug>/) and scroll to the related…"])
  S1U6(["View the homepage, nav dropdown and collection page at 375px mo…"])
  S1U1 -->|server-rendered WP_Query for post_type=utazas…| S1U2
  S1U2 -->|dynamic menu lists utazas posts via the share…| S1U3
  S1U3 -->|page template WP_Query for the bookable-trips…| S1U4
  S1U4 -->|placeholder grid rendered after the active gr…| S1U5
  S1U5 -->|secondary WP_Query for related trips, shared…| S1U6
S2 — Client edits a trip's ranking number and it propagates to every surface 🟢 happy P2

Trigger: Anna wants to push a specific trip to the top and expects the new order everywhere, without a developer. (This journey is the subject of the client SOP guide.)

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userGo to balionline.hu/wp-admin and log in (from a whitelisted IP, past cPGuard)WordPress login form → DashboardWP authenticationwp_admin_authenticated
2userClick 'Utazások' in the left admin menu to open the trips listUtazások list (all utazas posts)list table for post_type=utazastrips_list_open
3userClick the trip to promote to open its edit screentrip edit screenload post editor + meta boxtrip_edit_open
4userType a new value into the ranking-number field (lower number = appears earlier)ranking number inputfield value staged for saverank_value_entered
5userClick 'Frissítés' / 'Update' to save the trip'Utazás frissítve' / 'Post updated'POST save_post → meta persistedrank_value_persisted
6userOpen the public collection page (incognito) and find the edited tripcollection Grid-1front-end WP_Query reads the ranking field (shared helper)collection_reordered
7userOpen the homepage and the nav dropdown and locate the same triphomepage + nav trip listssame shared helper feeds bothall_surfaces_reordered

Proposed acceptance test-IDs: B3, F0, F1, F3, F4, F5, C1

Expected-Behavior Oracle — the answer key the tests assert against
#You doYou should seeElement that changes (copy · look · where)What changes underneathMust NOT happen
1Go to balionline.hu/wp-admin and log in (from a whitelisted IP, past cPGuard)The real WordPress login form loads (not the cPGuard/recaptcha.cloud interstitial), and after login the dashboard appears.Copy: 'Vezérlőpult' / Dashboard · Look: standard wp-admin chrome · Where: wp-adminwp-login.php must NOT be permanently exposed — the temporary IP allowance is reverted afterwards (check C2).
2Click 'Utazások' in the left admin menu to open the trips listThe full list of utazás trips, including the trip Anna wants to promote.Copy: trip titles list · Look: wp-admin list table · Where: Utazások admin screen
3Click the trip to promote to open its edit screenThe trip's edit screen, including the ranking-number field Dani added.Copy: ranking-number field (exact label resolved in B3) · Look: number input in a meta box / sidebar panel · Where: trip edit screen
4Type a new value into the ranking-number field (lower number = appears earlier)The ranking field accepts the new number for this trip only.Copy: the new rank value, e.g. '1' · Look: number input field · Where: trip edit meta box / sidebarThis trip's ranking meta value is updated; the existing values on OTHER trips are kept (F0 = keep the client's values, no re-seed).No other trip's ranking value is changed; the client's existing values are NOT mass-overwritten.
5Click 'Frissítés' / 'Update' to save the tripA 'trip updated' confirmation; the new ranking value is saved.Copy: 'Utazás frissítve.' · Look: admin success notice (green bar) · Where: top of the trip edit screenThe new ranking value is persisted to the database for this trip.The save must NOT error or silently drop the ranking value.
6Open the public collection page (incognito) and find the edited tripThe edited trip now sits at its new position in Grid-1.Copy: the promoted trip card at its new index · Look: trip-card in the grid · Where: collection page Grid-1The front-end ordering reflects the new ranking value on the next page load.The reorder must NOT require a developer redeploy, and must NOT appear on only one surface.
7Open the homepage and the nav dropdown and locate the same tripThe trip is at the SAME new position on the homepage, the nav dropdown and the collection page.Copy: the promoted trip first/at its new index on all three · Look: card grid / dropdown list · Where: homepage, nav, collectionThe new position must NOT differ between surfaces (the bug this whole feature fixes).
Sub-flow — what the user sees & does (arrows carry the system detail)
flowchart TD
  S2U1(["Go to balionline.hu/wp-admin and log in (from a whitelisted IP,…"])
  S2U2(["Click 'Utazások' in the left admin menu to open the trips list"])
  S2U3(["Click the trip to promote to open its edit screen"])
  S2U4(["Type a new value into the ranking-number field (lower number =…"])
  S2U5(["Click 'Frissítés' / 'Update' to save the trip"])
  S2U6(["Open the public collection page (incognito) and find the edited…"])
  S2U7(["Open the homepage and the nav dropdown and locate the same trip"])
  S2U1 -->|WP authentication| S2U2
  S2U2 -->|list table for post_type=utazas| S2U3
  S2U3 -->|load post editor + meta box| S2U4
  S2U4 -->|field value staged for save| S2U5
  S2U5 -->|POST save_post → meta persisted| S2U6
  S2U6 -->|front-end WP_Query reads the ranking field (s…| S2U7
S3 — Coming-soon placeholders are always pinned last 🟡 edge P1

Trigger: A 'Tervezés alatt' trip exists (Thaiföld / Japán / Mexikó), possibly even with a low ranking number set by the client.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1userOpen the collection page and look at both trip gridsGrid-1 (bookable) + Grid-2 ('Tervezés alatt')two grids renderedtwo_grids_rendered
2systemApply ordering when a placeholder trip has a low ranking numberplaceholder cardplaceholder pinned last regardless of rank valueplaceholder_pinned_last

Proposed acceptance test-IDs: F2

Expected-Behavior Oracle — the answer key the tests assert against
#You doYou should seeElement that changes (copy · look · where)What changes underneathMust NOT happen
1Open the collection page and look at both trip gridsBookable trips fill Grid-1; the 'Tervezés alatt' trips sit in Grid-2 below.Copy: 'Tervezés alatt' cards last · Look: second, muted grid · Where: below Grid-1
2Apply ordering when a placeholder trip has a low ranking numberEven if a 'coming soon' trip has a low ranking number, it still renders AFTER all bookable trips.Copy: 'Tervezés alatt' card index > every active index · Look: placeholder card · Where: end of the trips area on every surfacePlaceholders are pinned last by design (handoff §3), independent of the ranking field.A placeholder must NOT jump above a bookable trip just because its rank number is low.
Sub-flow — what the user sees & does (arrows carry the system detail)
flowchart TD
  S3U1(["Open the collection page and look at both trip grids"])
  S3U2["Apply ordering when a placeholder trip has a low ranking number"]
  S3U1 -->|two grids rendered| S3U2
S4 — A trip with no ranking value is never dropped (data-loss guard) 🟡 edge P2

Trigger: A live bookable trip whose ranking-number field was never filled in (ADR-0002: the naive meta_value_num INNER JOIN would silently drop it).

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1systemRender every listing surface when one bookable trip has an empty ranking fieldall trip listingsmissing-value-safe orderby (LEFT JOIN / relation OR / NOT EXISTS)unranked_trip_included
2userRead where the unranked trip lands in the collection gridcollection Grid-1rank-then-date orderingunranked_sorted_by_date

Proposed acceptance test-IDs: F1, F3

Expected-Behavior Oracle — the answer key the tests assert against
#You doYou should seeElement that changes (copy · look · where)What changes underneathMust NOT happen
1Render every listing surface when one bookable trip has an empty ranking fieldThe unranked trip still appears in every listing surface.Copy: the unranked trip's card · Look: normal trip card · Where: in the active grid, sorted last among activeThe query keeps trips with no ranking meta (count of rendered trips == count of published bookable trips).The unranked trip must NOT silently disappear from any surface — no INNER-JOIN drop.
2Read where the unranked trip lands in the collection gridThe unranked trip sorts after the ranked trips, by departure date.Copy: unranked trip after ranked block, in date order · Look: trip-card · Where: tail of the active tripsThe total trip count must NOT drop versus the number of published bookable trips.
Sub-flow — what the user sees & does (arrows carry the system detail)
flowchart TD
  S4U1["Render every listing surface when one bookable trip has an empt…"]
  S4U2(["Read where the unranked trip lands in the collection grid"])
  S4U1 -->|missing-value-safe orderby (LEFT JOIN / relat…| S4U2
S5 — Baseline & tie-break order = departure date, soonest first 🟡 edge P1

Trigger: Trips have no custom rank, or several share the same rank value — the order must be deterministic, not arbitrary.

#ActorUI element (clicked / seen)Copy shownSystem actionResulting stateBranch to
1systemOrder trips that have no rank or an equal rank valuetrip gridsecondary sort by departure date ascendingdate_baseline_applied
2userCompare the date-baseline order on the homepage, nav dropdown and collection pagethree surfacessame shared helperbaseline_consistent

Proposed acceptance test-IDs: F3, F4, F5, C1

Expected-Behavior Oracle — the answer key the tests assert against
#You doYou should seeElement that changes (copy · look · where)What changes underneathMust NOT happen
1Order trips that have no rank or an equal rank valueTrips with no rank or the same rank read by departure date, soonest first.Copy: earliest departure first · Look: ordered trip cards · Where: any listing surfaceDeparture date ascending is the baseline / tie-break (handoff §3).The order must NOT be arbitrary, by publish date, or random.
2Compare the date-baseline order on the homepage, nav dropdown and collection pageAll three surfaces show the identical, date-ascending baseline order.Copy: identical order across surfaces · Look: card grids / dropdown · Where: homepage, nav, collectionThe baseline order must NOT differ between surfaces.
Sub-flow — what the user sees & does (arrows carry the system detail)
flowchart TD
  S5U1["Order trips that have no rank or an equal rank value"]
  S5U2(["Compare the date-baseline order on the homepage, nav dropdown a…"])
  S5U1 -->|secondary sort by departure date ascending| S5U2

Global branching flowchart

Conditions on the arrows; colours follow the path-type legend. Per-scenario sub-flows appear inside each scenario above.

No global flowchart supplied — see per-scenario sub-flows above.

Copy index — message · copy · source · mode · status

MessageCopy / subjectSourceSend / show modeStatus
Coming-soon placeholder labelTervezés alattcollection page template (placeholder grid)in-pagelive
Nav dynamic-trips marker (HTML comment)<!-- Itt hívjuk be a dinamikus utakat -->header / nav templatein-pagelive
Trip-edit save buttonFrissítés / Updatewp-admin trip editorin-pagelive
Ranking-number field label(exact label resolved in checklist B3)utazas edit screen meta boxin-pageto-confirm

State reference

StateMeaningEntered byExits to
shared_orderingthe single utazas_query_args() helper (ADR-0001) that every listing query uses: rank-then-date, missing-value-safe (ADR-0002), placeholders lastany utazas listing query on any surfacerendered list on that surface
rank_value_persisteda trip's ranking-number meta saved in the CMS (client-owned value, never mass re-seeded)Anna saves the trip edit (S2.5)front-end reorder on next page load
unranked_trip_includeda trip with no ranking meta is still returned by the query (no INNER-JOIN drop)missing-value-safe orderbysorts last among active, by date

Generated by the user-journeys skill on 2026-06-26 · hosted at https://trip-order-consistency-journeys.pages.dev. Rendering: Mermaid flowchart syntax. No screenshots — this is a behavioral spec, not a visual QA artifact.