Cmd+P · Save as PDF
BPFmap · Audit document

Airtable schema +
Buttons audit

Date · 2026-05-02 Scope · BPFmap-v344-routing-stable.html Base · appQ7B5TqP7RRK5Xp
Table of contents
  1. Airtable schema audit
  2. App copy — gap analysis
  3. Schema gaps — new fields needed
  4. Airtable implementation plan
  5. Buttons audit (hamburger + my-location)
  6. New button proposal
  7. Execution plan — buckets
  8. Sign-off questions

Airtable schema

Snapshot at 2026-05-02 of base appQ7B5TqP7RRK5Xp via API record sampling.

Tables overview

TableFieldsRecordsStatus
BPF_Venues 21 (venue_id, name, short_name, latitude, longitude, address_full, address_display, neighborhood, city, sort_order, access_url, access_type, access_display, hours_override_enabled, popup_enabled, is_active, is_featured, venue_status_mode, apple_maps_url, google_maps_url, BPF_Events) 17 Robust
BPF_Events 11 (event_id, title, Author, date, start_time, end_time, category_primary, event_type_display, access_override, venue, is_visible) ~45 Functional
BPF_Categories 8 (category_id, name, slug, icon_name, type, sort_order, is_active, is_user_filter) ~6 OK
BPF_App_Copy 5 (copy_key, state, title, body, is_active) 6 Under-used
BPF_Settings 3 (setting_key, value_number / value_text / value_json, notes) 15 OK

BPF_App_Copy — existing entries

copy_keystateexcerpt
welcome_bodywelcomeWelcome — Explore the city through the festival map
filtered_bodyfilteredExplore the city through the festival map
route_helper_bodyrouteRoute Helper
navigation_modal_bodynavigation_modalNavigation
festival_info_titlefestival_infoFestival Info
festival_info_bodyfestival_infoFestival Info Body

BPF_Settings — existing keys

keyvaluenotes
default_zoom13.5Default map zoom
default_lat44.4378Default map center latitude
default_lng26.0963Default map center longitude
map_padding_top80
map_padding_bottom180Bottom sheet map padding
map_center_bias_y-40
timezoneEurope/BucharestApp timezone
default_open_time10:00Default venue opening
default_close_time21:00Default venue closing
availability_enabledtrueEnable open/closed logic
festival_info_enabledtrueEnable festival info sheet
route_enabledtrueEnable route mode
mapbox_enabledtrueEnable Mapbox routing
mapbox_tokenpk.eyJ1...Public Mapbox token
routing_profilewalkingRouting mode

App copy — hardcoded strings

Aprox. 30+ user-facing strings sunt hardcoded în cod care ar trebui mutate în BPF_App_Copy pentru editorial flexibility (CMS-like).

⚠ Gap critical

Doar 6 din ~36 strings expuse utilizatorului sunt în Airtable. Editarea oricărei copy necesită code change + redeploy.

Welcome / empty state

welcome.kicker · "Witness — The 11th Edition"
welcome.lead · "Welcome to"
welcome.brand · "Bucharest Photofest"
welcome.year · "2026"
welcome.theme_line · "Witness · 9–18 October"
welcome.h3_default · "Photography across Bucharest"
welcome.editorial · "Photography as attention — ten days, seventeen venues, an invitation to see Bucharest differently."
welcome.stats · "17 Venues · 9–18 Oct 2026"
welcome.countdown_pre · "Opens in {days} days"
welcome.countdown_live · "Day {n} of {total}"
welcome.countdown_ended · "Festival ended — see you next year"
welcome.today_line · "Today · {ev} events at {v} venues"
welcome.cta_explore · "Explore the map"
welcome.cta_open_now · "Open Now"
welcome.cta_festival_info · "Festival Info"
welcome.cta_programme · "Programme ↗"
welcome.cta_show_all · "Show all venues"
welcome.empty_filtered · "Filter active — Open Now"
welcome.no_open_now · "Nothing open right now"

Venue sheet

venue.events_title · "Events at this venue"
venue.full_programme · "Full Programme"
venue.status_open · "Open now"
venue.status_closed · "Closed now"
venue.chip_pass · "Pass"
venue.chip_buy · "Buy"

Route preview (V355)

route.kicker · "Route preview"
route.from_label · "From"
route.to_label · "To Venue {n}"
route.from_default · "Your location"
route.mode_walk · "Walking"
route.strip_eta · "ETA"
route.strip_distance · "Distance"
route.strip_arrive · "Arrive"
route.cta_back · "Back to Venue"
route.cta_navigation · "Navigation"

Filters menu

filter.open · "Open now"
filter.screening · "Screenings"
filter.exhibition · "Exhibitions"
filter.talk · "Talks"
filter.nearby · "Nearby"
filter.reset · "Reset"

Navigation modal

nav.kicker · "Directions"
nav.body · "Pick your maps app to get to the next venue..."
nav.apple · "Apple Maps"
nav.google · "Google Maps"
nav.cancel · "Cancel"

Festival info

festival.title · "Bucharest Photofest 2026"
festival.subtitle · "oct–nov · 17 venues"
festival.theme · "Witness — The 11th Edition"
festival.section_facts · "Key facts"
festival.fact_dates · "9–18 Oct 2026"
festival.fact_theme · "Theme: Witness"

Field gaps

BPF_Venues — missing fields

BPF_Events — missing fields

BPF_Settings — missing keys

Implementation plan

Phase 1 — schema expansion (in Airtable, manual)

  1. Add hero_image_url, description_short to BPF_Venues
  2. Add Artist, Curator, description_short, image_url to BPF_Events
  3. Add 10 keys to BPF_Settings (see fields table above)
  4. Bulk-add ~36 entries to BPF_App_Copy organized by state buckets: welcome, route_preview, venue_sheet, filters, nav_modal, festival_info, system

Phase 2 — wire APP_COPY in code

Phase 3 — new fields adoption

Buttons audit

Floating circular controls in .controls at top-right: menuBtn (hamburger) + centerBtn (my-location). Both have functional + UI issues.

Hamburger — #menuBtn

Issues
  • Semantic mismatch — iconă sugerează "menu navigation", conţinut sunt filtre (Open now, Screenings, Exhibitions, Talks, Nearby, Reset)
  • Duplicate — există deja filter strip în empty-hero (V369 chips). Două căi pentru aceeaşi acţiune, discoverability slabă
  • UI primitiv — char Unicode plain, fără SVG icon, fără branding
  • Naming inconsistentmenuBtn + .ctrl.menu + menuPanel dar conţine filtre, nu meniu

My-location — #centerBtn

Issues
  • Iconă greşită — SVG actual e paper-plane / send glyph (M20.7 3.3L4.8 10.2c-.9.4-.9 1.6 0 2...), nu my-location. aria-label="My location" dar utilizatorul vede send icon → confuzie
  • Două handlere concurente — linia 6664 (reset) + linia 7450 (geolocation flyTo). V333 face cloneClean() care ar trebui să detach-eze primul, dar order-dependent
  • Fallback absent dacă geolocation refuzată — doar console.warn
  • Fără indicator vizual când location e activă
  • Zoom brutflyTo(coords, max(zoom, 14)), nu ţine cont de venue cluster

New button stack

Recomand 3 butoane verticale în .controls — preluăm slot-urile existente + adăugăm unul nou:

Filters
replaces hamburger
My location
crosshair, fixed
Programme
new shortcut
ButtonActionActive state
Filters Toggle filter panel (preia funcţia hamburger). Iconă filter funnel. Badge cu numărul de filtre active Dot indicator când any filter applied
My location Geolocation request + map.flyTo(coords) cu adaptive zoom. Toast feedback dacă denied Active dot + slight glow când coords disponibile + already-centered state
Programme Open programme sheet (today auto-selected). Direct shortcut — one-tap vs current 2–3 tap-uri Subtle bg tint când e festival live (festival_state === 'live')

UI improvements (general)

Execution buckets

Bucket A · now
Buttons redesign
Audit 02 fixes:
  • Replace centerBtn icon (paper-plane → crosshair)
  • Add Filters btn (preia hamburger)
  • Add Programme btn (nou)
  • Geolocation fallback toast
  • Active states
Estimat: ~80 linii CSS+JS în V376
Bucket C · later
Wire APP_COPY in code
După populare Airtable:
  • Replace hardcoded strings with lookup
  • V369/V373/V355/V336 read from Settings
  • P9, P16, P19 phase 2 unblocked

Sign-off questions

Hamburger fate
A · eliminăm complet, filter strip preia
B · reconvertim în Programme/Layers
Three-button stack
Confirm Filters + My-location + Programme? Sau alt mix (Layers, Theme toggle, Saved/Shortlist)?
Airtable bulk-add path
CSV livrat de mine (manually import) sau direct API populate (am tokenul)? Notă: API-ul actual nu are schema-meta permission, poate adăuga doar records în câmpuri existente — schema expansion se face manual de tine.
Phase 2 wire timing
Programăm sesiune dedicată după Airtable populated? Sau wire incremental (1-2 V-blocks per sesiune când prind disponibilitate)?
Welcome / directions / filter / venue feedback
Aşteptăm mesajul tău detaliat înainte de Bucket A? Sau pornim Bucket A acum + preluăm feedback în paralel?