Sports Club Website Development on 1C-Bitrix
A sports club website is neither a corporate business card nor a traditional e-commerce platform. It simultaneously manages training schedules, tournament standings, ticket sales with seat selection, and a media portal for fans. Each of these components requires separate data architecture, and together they create a load that standard Bitrix components handle only with proper configuration.
Information Block Structure
For a sports club, a hierarchy of interrelated information blocks is established:
- Teams — primary information block linked to sport type, league, and season. Properties: roster (linked to "Athletes" block), coaching staff, logo, team colors.
- Athletes — detailed profile block: full name, position, number, anthropometric data, action photos, seasonal statistics (goals/points/assists stored in separate Highload-block for fast retrieval).
-
Matches and Training Sessions — Highload-block (
b_hlblock_schedule), because thousands of records accumulate over several seasons. Fields: date/time, type (training/match/friendly), home team, away team, venue, status (scheduled/in-progress/completed/postponed), score. - Tournaments — information block linked to season. Tournament standings are generated by a custom component based on match results from the Highload-block.
Relationships between information blocks are implemented through "Link to elements" property type (E) or via Highload-directories when query performance is critical.
Schedule: Highload-Block and Caching
The training and match schedule is the hottest section of the website. Fans check upcoming games, coaches review training schedules, administrators update results in real-time.
The Highload-block is chosen deliberately: with 300+ matches per season and 5-6 teams in a club, a standard information block starts to lag on complex filtering. The Highload-block stores data in a separate MySQL table with direct queries bypassing information block API overhead.
Frontend filtering: by team, event type, month. The component renders a calendar grid with color coding — training sessions in gray, home matches in green, away matches in blue. For SEO, each match gets a dedicated detail page with a clean URL like /matches/2024-25/spartak-vs-dinamo-12-10/.
Caching is tag-based, bound to tag schedule_updated. When any Highload-block element is updated via the HighloadBlockOnAfterUpdate event handler, only this specific tag is cleared, not the entire site cache.
Ticket Sales Through the sale Module: SVG Stadium Layout
This is the key and most technically complex part of the project. The standard Bitrix sale module is designed for shopping cart items — add, checkout, pay. A ticket for a specific seat in a specific section is entirely different mechanics.
Solution Architecture:
Each stadium (hall, arena) is described by an SVG file where each seat is a separate <rect> or <circle> element with attributes data-sector, data-row, data-seat. The SVG loads in the browser; a JavaScript handler manages interactivity: highlighting on hover, seat selection on click, occupied seats displayed in gray.
Seat Storage and States:
A Highload-block hl_stadium_seats is created with fields:
| Field | Type | Purpose |
|---|---|---|
UF_STADIUM_ID |
Number | Link to stadium |
UF_SECTOR |
String | Sector code (A, B, C...) |
UF_ROW |
Number | Row number |
UF_SEAT |
Number | Seat number |
UF_CATEGORY |
Dictionary | Category (VIP, standard, fan zone) |
UF_PRICE_ZONE |
Dictionary | Price zone |
UF_SVG_ID |
String | SVG element ID for matching |
For each match, a booking table is created — another Highload-block hl_ticket_bookings:
| Field | Type | Purpose |
|---|---|---|
UF_MATCH_ID |
Number | Match ID from schedule |
UF_SEAT_ID |
Number | Seat ID from hl_stadium_seats |
UF_STATUS |
List | free / reserved / sold / blocked |
UF_ORDER_ID |
Number | Order ID in sale module |
UF_RESERVED_AT |
DateTime | Reservation time (for auto-release) |
UF_USER_ID |
Number | Buyer |
Purchase Process Step-by-Step:
- User opens match page; SVG layout loads.
- AJAX request to REST-controller retrieves occupied seats for the match. JavaScript colors them gray and removes click handler.
- User clicks a free seat — marked as
reservedinhl_ticket_bookingswith timestamp. Reservation lasts 15 minutes, then the cron agent (CTicketReserveAgent) clears expired reservations. - Selected seats are added to cart as trade offers. Each price zone is represented as a trade offer in the catalog. Cart property
SEAT_INFOstores serialized seat data. - Order checkout is standard —
sale.order.ajaxwith customized template. Upon successful payment, status changes tosold, PDF ticket with QR code is generated via TCPDF library. - QR contains a signed token (HMAC-SHA256) verified at entry by scanner.
Concurrent Access — critical concern. Two fans cannot book the same seat. Solution: UPDATE ... WHERE UF_STATUS = 'free' with affected row check. If 0 rows returned — seat already occupied, frontend shows notification and redraws SVG.
SVG Performance: a 10,000-seat stadium is 10,000 DOM elements. On mobile devices this causes lag. Optimization: Canvas rendering for overview with SVG switching on zoom to specific sector. Or division by sectors — first select sector on simplified layout, then load detailed SVG only for selected sector.
Tournament Standings
Custom component custom:tournament.table aggregates data from match Highload-block: calculates points (3 for win, 1 for draw), goal differential, sorts results. Output is cached with tag tournament_{ID}, cleared when any match score in that tournament is updated.
For team sports with playoffs, the component can render playoff bracket via SVG — pairings, winners, connections between rounds.
Athlete Profiles
Detailed athlete page includes: photo, biography, career achievements (timeline via information block multiple property — club, years, achievements), current season statistics from Highload-block, photo/video gallery linked via CIBlockElement::GetProperty.
For SEO — schema.org/Person micromarkup with athlete in jobTitle field, linked to schema.org/SportsTeam.
Fan Zone and Merchandise Store
News section implemented with standard news.list / news.detail components with customized template. Photo and video gallery — information block with match and athlete relationships.
Merchandise store — full-fledged e-commerce on catalog + sale modules: jerseys, scarves, memorabilia. Trade offers by size and color, 1C integration for stock management. Works parallel to ticket system but in separate information block type to prevent catalog overlap.
Integration with Ticket Operators
If the club sells tickets not only through its website but also through Ticketland, Kassir.ru or similar systems — synchronization is needed. Implemented via REST API: when booking/sale occurs on operator side, webhook updates status in hl_ticket_bookings. Conversely, site sales send data to operator.
Sync cron agent runs every 2 minutes to pull changes that may not have arrived via webhook (network failures, timeouts).
Development Phases
| Phase | Scope | Duration |
|---|---|---|
| Design | Information block structure, HL-blocks, SVG layout prototypes | 2–3 weeks |
| Markup and Frontend | Responsive templates, interactive SVG, calendar | 3–4 weeks |
| Backend Ticketing | Booking module, sale integration, PDF tickets | 4–5 weeks |
| Content and Catalogs | Athlete profiles, tournament standings, merchandise | 2–3 weeks |
| Integrations | Ticket operators, 1C, payment systems | 2–3 weeks |
| Testing | Load testing SVG (10,000 seats), concurrent booking | 1–2 weeks |
| Launch and Support | Deploy, agent monitoring, editor training | 1 week |







