Releases: HiEventsDev/Hi.Events
Release list
v2.0.0-rc.1
Hi.Events v2.0.0-rc.1
The biggest release since the project started. v2 adds recurring and multi-date events, embedded
checkout, product add-ons, a rebuilt check-in app, a documented REST API, and a redesigned organizer
dashboard, along with a set of platform upgrades that require action before you upgrade.
Read the Upgrading section before running this on an existing installation. There
are new minimum requirements and several one-way migrations.
Recurring and multi-date events
An event is no longer a single date. Every event now has one or more occurrences, and you can
generate them from a recurrence rule.
- Daily, weekly, monthly and yearly schedules, with intervals, multiple times per day, and
per-slot labels and durations. Monthly supports both "the 15th of the month" and "the last
Friday of the month". The recurrence API additionally accepts excluded dates and one-off extra
dates. - Set a schedule to end after a number of dates or on a specific date. Up to 1,200 occurrences per
event. - Per-date capacity, per-date pricing overrides, per-date product visibility, and per-date venues.
- Cancel a single date, refund its orders in one action, and notify the attendees. Orders that
span several dates are left for manual refund. Cancelling writes the date back into the schedule
as an exclusion so it does not reappear. - Bulk edit across dates: shift times, change duration, update capacity, relabel, or change venue,
with options to only affect future dates and to skip dates you have edited by hand. - Attendees, orders, waitlist entries, reports and exports can all be filtered by date.
- A new Occurrence Summary report breaks down sales, attendance and check-ins per date.
Buyers get a calendar and time-slot picker on the event page and in the embedded widget, with
remaining-capacity hints, sold-out states, and deep links straight to a specific date via
?occurrence_id=.
Single-date events keep working exactly as before. They get one occurrence created automatically and
the buyer never sees a date picker.
Embedded checkout
The embeddable widget now runs the entire checkout in a modal over your own page, from ticket
selection through payment to confirmation.
- Rendered in a shadow DOM, so your site's CSS cannot break it and it cannot leak styles into your
page. Full screen on mobile, a centred dialog on desktop. - Apple Pay and Google Pay work inside it. Payments that redirect away for authentication (3DS,
wallets) come back straight into the modal rather than dumping the buyer on a bare page, and the
redirect parameters are cleaned off your URL afterwards. - Closing the modal mid-checkout asks for confirmation and cancels the order. An accidental page
reload or navigation is safe though: when the buyer returns in the same tab, the checkout reopens
at the step they left off, as long as the reservation has not expired. - Set
data-hievents-checkout="new-tab"if you would rather keep the old behaviour of opening
checkout in a new tab.
The embed snippet has not changed. Existing embeds pick all of this up with no edits to your
site.
There is also a widget playground at /widget-test on dev builds (or in production with
WIDGET_TEST_PAGE_ENABLED=true) for trying colours, locales and checkout modes against a real
event, with a live log of the messages the widget sends to the host page.
Product add-ons
Attach add-ons to a ticket: merch, parking, a workshop upgrade. Add-ons appear nested under their
parent in the widget and stay inert until the parent is in the cart. Mark a product "add-on only"
and it will not appear as a standalone item.
Reusable locations and address autocomplete
Addresses were previously free text stored on each event. They are now a proper location library
per organizer, with a saved-venue picker and Google Places autocomplete.
Autocomplete is optional. Set GOOGLE_MAPS_API_KEY to turn it on. Without a key everything still
works, you just type the address in by hand.
Events can be in-person or online, and recurring events can have a different venue per date. The
public payload now returns a structured event_location object instead of the old
location_details blob.
Rebuilt check-in app
The scanner was reorganised into three tabs: Scan, Search and Stats.
- Camera scanning is now inline rather than a separate screen, and USB scanner mode shows a live
listening indicator and a visible input buffer. - A stats tab with totals, progress, and a live throughput figure over a rolling five-minute window.
- An attendee detail sheet with check-in history.
- A date filter for recurring events, so door staff only see the session they are working.
- Haptic feedback, an offline indicator, and undo on accidental check-ins.
- Check-in lists moved to a table view, and you can now control what an unauthenticated check-in
link exposes: attendee notes, question answers, and order details are each off by default.
Payments moved to the organizer
Stripe Connect, VAT settings and fee configuration used to live on the account. They now live on the
organizer, so one account can run multiple organizers with separate payout destinations.
- Reuse an existing Stripe connection across organizers in the same account (SaaS mode only), or
connect each one separately. - Disconnect Stripe from an organizer without touching the Stripe account itself.
- Existing connections are migrated automatically. Nobody has to reconnect.
You can also change an event's currency yourself now, as long as the event has no orders with a
monetary value.
Account deletion
Account owners can request deletion from Account settings, under Danger Zone.
- 30 day grace period with a reminder email 7 days before the deletion runs, cancellable at any
point. - Accounts that have never taken a completed order are deleted outright. Accounts that have are
anonymised instead, so financial records stay intact. - Blocked while upcoming events still have completed orders, with the blocking events named.
- Live events are moved to draft as soon as the request is made.
Deletions are executed by an hourly scheduled job, so schedule:run needs to be active.
REST API documentation
The API now ships an OpenAPI spec generated from the code itself.
Set API_DOCS_ENABLED=true and browse interactive docs at /docs/api on your own instance, or
export the spec with php artisan scramble:export. Off by default.
Announcements
Superadmins can post in-app banners or modals to users on their instance, targeted at everyone, at
specific accounts, or at specific users, with seen and dismissed counts. This is entirely local to
your installation. There is no remote feed and nothing is pushed into your install from outside.
Redesigned dashboards
- Stat cards replaced with sparklines and period-over-period comparisons.
- A new period selector covering both recent activity (last 7, 30, 90 days) and event lifetime
(first 7, 30, 90 days, full event). - A rebuilt setup checklist with a progress bar, which disappears once you are done.
- A publish flow that checks for missing pieces before you go live: it warns about missing tickets
or dates, and blocks publishing when payments are not set up. - For recurring events, a hero panel for the next date with a live countdown that turns into a
check-in shortcut once the date starts.
Checkout
- The checkout header was rebuilt: a step counter, the event title, and a compact reservation timer
that turns red as it runs down. - Ticket selection was redesigned. One-price tickets show inline without expanding, descriptions
moved behind a Details toggle, fees and tax have a collapsible breakdown, and low stock shows a
remaining-quantity hint. - The floating "Get tickets" button turns into a checkout button showing your cart total once you
scroll past the ticket list, and its label is configurable per event.
Everything else
- Nine new event categories (Family, Hobbies, Wellness, Spirituality, Outdoors, Tours, Film, Dance,
Seasonal), and the category now sets the default wording. A wellness event says "Classes" and
"Book Now" rather than "Tickets" and "Continue". - Fixed-amount promo codes can now discount the order total rather than each product.
- Offline payment orders can be refunded, in full or in part. This records the refund and can
optionally email the buyer, it does not move money. - Attendee tickets were redesigned, and cancelled or unpaid tickets now clearly show as void instead
of displaying a scannable code. - Waitlists are date-aware. One person can hold a place on several dates, offers name the date, and
cancelling a date releases its waitlist. - Product create and edit moved into a wide drawer with a live preview of the real widget that
updates as you type. - The frontend loads less up front. Every date-formatting locale used to be bundled whether you used
it or not and now loads on demand, the rich text editor is loaded only when a page needs it, and
theme colours are computed on the server rather than in the browser. Event management pages also
make fewer duplicate API calls. - k6 load test scripts (
misc/k6/) and a split backend test suite, with the unit suite kept fast
and database-free.
A comprehensive end-to-end test suite
This release was built alongside a new Playwright E2E suite: over 160 tests across 66 spec files,
driving the real application — Laravel backend, SSR frontend, Postgres, Redis and a mail catcher —
in a real browser. Registration, event creation, free and Stripe checkout, recurring schedules,
promo codes, questions, messaging, check-in, webhooks and more. Test data is arranged through the
REST API and every spec asserts on real page content, not just URL chan...
v1.11.1-beta
v1.11.1-beta
Security release — upgrading is recommended, especially for hosted or multi-tenant setups. Thanks to the researchers who reported these privately.
Security
- Webhook SSRF — URLs were only checked at save time; redirects were followed anywhere and IPv6 transition addresses bypassed the filter. Delivery now re-validates, pins the resolved address, and checks every redirect hop — thanks @tonghuaroot, @de3erve, @JaimeRamirez-coder, @senti-man, @angelystor, @1amplant, @tikket1, @Fewword, @dizconnectz
- Formula injection in exports — buyer-supplied names and answers were written as live spreadsheet formulas; now written as text — thanks @senti-man
- Order completion race — concurrent requests could complete an order twice, duplicating attendees and exhausting capacity — thanks @tonghuaroot
- Sale windows not enforced at checkout — products and price tiers could be bought before going on sale, after closing, or at an expired tier — thanks @angelystor
max_per_orderbypass — the limit was applied per order line, so repeating a product multiplied it — thanks @angelystor- Product ownership not checked — questions, capacity assignments and check-in lists accepted products from other events, and cross-event edits detached the owner's products — thanks @Fewword
- Promo code enumeration — the public lookup endpoint is now throttled — thanks @senti-man
- Cross-event question tampering — editing or deleting a question via another event rewrote its product links and deleted its answers
Fixes
- Order, attendee, product and check-in webhooks now dispatch on the queue instead of inline
Other changes
- Update contact message by @daveearley in #1270
- Update email subject by @daveearley in #1271
Upgrading
No migrations or config changes. Three behaviour changes worth knowing: webhooks to endpoints that redirect to internal addresses now fail; webhook delivery runs on the queue, so a non-sync connection needs a worker; export cells starting with =, +, - or @ render as text.
Full Changelog: v.1.11.0-beta...v1.11.1-beta
v.1.11.0-beta
What's Changed
🌍 Translations & Localization
- Added Slovak (
sk) translation and fixed missing strings across all locales by @pipozzz in #1210 - Improved French translation by @lionep in #1240
🎟️ Ticketing & Checkout
- Prevented purchase of hidden products via public checkout by @daveearley in #1259 (Thanks to @0xh3lix for the report.)
- Rendered offline payment instruction tokens by @realicon23 in #1235
- Prefilled public checkout from URL query params, including name, email, and optional locking by @skvost in #1234
🔐 Security & Privacy
- Prevented XSS via event titles in inline script contexts by @daveearley in #1260 (Thanks to @0xh3lix for the report.)
⚙️ Configuration & Infrastructure
- Exposed SMTP TLS controls for local relays by @realicon23 in #1244
New Contributors
- @pipozzz made their first contribution in #1210
- @lionep made their first contribution in #1240
- @skvost made their first contribution in #1234
Full Changelog: v.1.10.0-beta...v.1.11.0-beta
v.1.10.0-beta
What's Changed
🌍 Translations & Localization
- Added Spanish translations by @sandraR01 in #1177
- Completed Spanish (
es) translations and fixed hardcoded English labels by @sandraR01 in #1219 - Updated Italian translations by @albanobattistella in #1201
- Added Greek (
el) language support by @angelospk in #1193 - Fixed localized delete confirmations by @rayhan206 in #1230
🎟️ Ticketing & Checkout
- Added ticket date display options by @daveearley in #1214
- Added organizer setting to hide the checkout “Copy my details to attendees” control by @giuliosmall in #1218
- Fixed issue where unrelated capacity assignments could block checkout by @realicon23 in #1222
- Rejected negative product quantities during order creation by @daveearley in #1231
- Enforced promo code usage limits at order reservation by @daveearley in #1233
🔐 Security & Privacy
- Sanitized question and organizer descriptions on write by @daveearley in #1232
- Hid attendee email addresses from the public check-in resource by @realicon23 in #1229
🧪 Tests & Maintenance
New Contributors
- @sandraR01 made their first contribution in #1177
- @realicon23 made their first contribution in #1222
- @rayhan206 made their first contribution in #1230
- @giuliosmall made their first contribution in #1218
- @angelospk made their first contribution in #1193
Full Changelog: v1.9.0-beta...v.1.10.0-beta
v1.9.0-beta
What's Changed
- feat: add organizer tracking pixels with cookie consent by @daveearley in #1166
- feat: add date range event dashboard charts by @mrjbj in #1161
- feat: add homepage font controls by @manaskumar3003 in #1169
- fix: unhide hidden categories in event manage view by @Viburnum in #1138
- fix: wrap hardcoded "at" in order summary email in translations by @dalsoop in #1171
- fix: prevent SSR crash on unhandled locale in LanguageSwitcher by @dalsoop in #1170
- fix: handle CHARGE_REFUNDED and REFUND_CREATED events for non-SaaS Stripe refunds by @mrjbj in #1156
- fix: preserve sized image dimensions after page reload by @mrjbj in #1158
- i18n: update Italian translations by @albanobattistella in #1151
New Contributors
v1.8.0-beta
What's Changed
- Add docker-compose.override.yml to .gitignore by @officialJCReyes in #1137
- Add AI development guidelines and improve contribution docs by @daveearley in #1148
- Add dropdown item on order to copy customer checkout summary url by @LogFlames in #1147
- Expose webhook signing secret on creation by @ptaranat in #1149
New Contributors ❤️
- @officialJCReyes made their first contribution in #1137
- @LogFlames made their first contribution in #1147
- @ptaranat made their first contribution in #1149
Full Changelog: v1.7.1-beta...v1.8.0-beta
v1.7.1-beta
What's Changed
- feat: Add environment variable to bypass NoInternalIP rule for specific webhook hosts by @MineTech13 in #1122
- fix: Clone question description by @veym-it in #1125
- fix: Validate sort_by parameter against allowlist in repositories by @tikket1 @daveearley in #1128
New Contributors
- @MineTech13 made their first contribution in #1122
- @veym-it made their first contribution in #1125
- @tikket1 for their security fix
Full Changelog: v1.7.0-beta...v1.7.1-beta
v1.7.0-beta
What’s Changed
-
✨ Feature: Waitlist for sold out products (#1043) by @daveearley
-
✨ Feature: Add scheduled message support (#1036) by @daveearley
-
✨ Feature: Introduce organizer-level webhooks for event lifecycle management (#1050) by @Sipioteo
-
✨ Feature: Add congrats modal when making event live (#1031) by @daveearley
-
✨ Feature: Support any currency for application fees (#1029) by @daveearley
-
✨ Feature: Improve overselling safety (#1045) by @daveearley
-
✨ Feature: Add event and organizer delete, archive, and management improvements (#1104) by @daveearley
-
🐛 Fix: Update attendee statistic updates (#1071) by @daveearley
-
🐛 Fix: Waitlist race conditions and capacity double-counting (#1072) by @daveearley
-
🐛 Fix: XSS, SSRF, and missing session verification (#1081) by @daveearley
-
🐛 Fix: Negative quantity validation error on tiered products (#1087) by @daveearley
-
🐛 Fix: Widget color validation rejecting uppercase hex values (#1103) by @daveearley
-
🐛 Fix: Null price error in attendee ticket email context (#1102) by @daveearley
-
🐛 Fix: Sanitize email template body with HTMLPurifier (#1105) by @daveearley
-
🐛 Fix: Cast page and per_page to int in QueryParamsDTO (#1113) by @daveearley
-
🐛 Fix: Handle empty enum values in BaseDTO and suppress ResourceConflictException reporting (#1114) by @daveearley
-
🐛 Fix: Skip payout events from Stripe Connect accounts (#1115) by @daveearley
-
🐛 Fix: Hardcoded database username and DB name in AIO compose file (#1111) by @anthonyrom
-
🐛 Fix: Capture document.currentScript before DOMContentLoaded (#1054) by @vianmora
-
🔧 Improvement: Move UTC handling (#1082) by @daveearley
-
🧹 Chore: Generic docs cleanup (#1046) by @daveearley
-
🧹 Chore: Update sentry settings (#1112) by @daveearley
-
🚀 Infra: Add Laravel scheduler to all-in-one Docker setup (#1090) by @daveearley
-
🚀 Infra: Add version management and system info endpoint (#1091) by @daveearley
-
🌍 Localization: Update Italian translations (#1039, #1088) by @albanobattistella
-
🌍 Localization: Fix Italian assets trailing character (#1070) by @zabaj1
-
🌍 Localization: Fix "Google Mapa" typo in location settings (#1034) by @anthonyrom
Upgrade Notes
To support waitlists and scheduled messages, you must ensure the Laravel scheduler is running.
If you are using the all-in-one Docker image, the scheduler is already included.
If you are running the backend image or from source, you will need to run it yourself.
See Laravel docs for setup:
https://laravel.com/docs/12.x/scheduling#running-the-scheduler
If the scheduler is not running, waitlists will not release tickets and scheduled messages will not be sent.
New Contributors
- @anthonyrom made their first contribution in #1034
- @vianmora made their first contribution in #1054
- @Sipioteo made their first contribution in #1050
- @zabaj1 made their first contribution in #1070
Full Changelog
v1.6.0-beta.1...v1.7.0-beta
v1.6.0-beta.1
What's Changed
Feat
- feat(stripe): allow bypassing application fee (#1002) by @daveearley
- feat(i18n): add Swedish localization (#882) by @VKronmar
- feat(i18n): add Polish language support (#1010) by @mikolajqc
- feat(invoice): design improvements (#1021) by @daveearley
Fix
- fix(orders): error when marking offline order as paid (#1007) by @daveearley
- fix(checkout): missing “Complete Order” button (#1009) by @nitinog10
- fix(settings):
notify_organizer_of_new_orderstoggle not persisting (#1022) by @daveearley
Chore
- chore(frontend): bump
@tabler/icons-reactfrom 2.47.0 to 3.35.0 (#842) by @dependabot[bot] - chore(backend): bump
laravel/vapor-corefrom 2.40.0 to 2.41.0 (#817) by @dependabot[bot]
Other
- update: Stripe Indian tax law compliance (#997) by @on3ss
- i18n: update
it.po(#979) by @albanobattistella
New Contributors
- @on3ss made their first contribution in #997
- @VKronmar made their first contribution in #882
- @nitinog10 made their first contribution in #1009
- @mikolajqc made their first contribution in #1010
Full Changelog: v1.5.1-beta.1...v1.6.0-beta.1
v1.5.1-beta.1
What's Changed
- Feature: Messaging tiers by @daveearley in #986
- Feature: Add mail failover by @daveearley in #988
Full Changelog: v1.5.0-beta.1...v1.5.1-beta.1