UGO Cycle is a specialized electric bike retailer in Quebec. With multiple branches and a catalog of over 476 products, the team used Lightspeed R-Series to manage their sales and inventory. Their main need: integrate Affirm Canada financing directly into their sales process — a feature missing from Lightspeed for the Canadian market.
At H1Site, we designed and developed this custom POS application using Next.js 14, Supabase, and the Lightspeed R-Series API. In this case study, we detail every technical aspect of the project — from architecture to deployment — to show how a custom web application can transform retail operations.
The challenge: integrating Affirm into the sales process
UGO Cycle uses Lightspeed R-Series to manage its inventory, reports, and sales. The standard POS works well for daily operations. However, a critical need was missing: Affirm Canada financing.
Electric bikes are a significant investment for customers — often between $2,000 and $8,000. Offering financing in installments via Affirm is a crucial sales lever. The problem: Affirm was not integrated into Lightspeed for the Canadian market, forcing a tedious and error-prone manual process.
The solution? Build a complementary POS application that integrates with Lightspeed via its API and adds the Affirm financing flow directly into the sales process. As a bonus, we were able to add features that enhance employee workflow:
- Affirm Canada Financing: full OAuth flow integrated directly into checkout, allowing customers to finance their purchase in just a few clicks.
- Kit Builder Menu: a handy tool for quickly adding components (motor, battery, screen) when configuring an electric bike.
- Optimized touch interface: an experience tailored to UGO Cycle's workflow with quick search, multi-store, and automatic tax calculation.
- Flexible discounts: per item or invoice, in percentage or fixed amount.
The best of both worlds: the power of Lightspeed for inventory management and reporting, combined with a web application that adds Affirm financing and custom point-of-sale features.
Technical architecture
The architecture of the UGO Cycle POS is based on a modern stack optimized for performance and reliability:
- Next.js 14 (App Router): deployed on Vercel for fast rendering and efficient Server Actions. The App Router allows us to structure the application with shared layouts (POS sidebar, admin header) and server-side rendering for management pages.
- Supabase (PostgreSQL): the central database that stores Lightspeed OAuth tokens, product and category cache, store configurations, users, and sessions. PostgreSQL provides the power of SQL for complex queries and extensions like pg_cron for automation.
- Lightspeed R-Series API: OAuth 2.0 connection for bidirectional product synchronization, sales creation, and inventory management. The Lightspeed REST API is the bridge between our POS and their ecosystem.
- Affirm Canada: OAuth integration for consumer financing. The checkout flow redirects to Affirm for approval, then returns to the POS to complete the sale.
- Framer Motion: smooth animations for the touch interface — panel transitions, kit menu appearance, visual feedback for user actions.
The POS system: a full-screen touch interface
The POS interface was designed to be used on tablets and touch screens in full-screen mode. Every pixel is optimized for speed and clarity:
- Product grid with images: products are displayed in a visual grid with their photos, prices, and SKU. An employee can identify and add a product with a single tap, without having to read long text lists.
- Category filtering: Lightspeed categories are synchronized and displayed as filter buttons at the top of the grid. A tap on “Electric Bikes” instantly filters the 476+ products to show only bikes.
- Search by name and SKU: a real-time search field filters products as the employee types. The search works on both product name AND SKU for maximum flexibility.
- Sidebar cart with quantities: the cart is always visible on the right side of the screen. Each item displays its name, price, quantity (adjustable with + and -), and a delete button. The subtotal, taxes, and total are calculated in real-time.
- Automatic tax calculation: GST 5% + QST 9.975% are automatically calculated on each item. The total with taxes is always visible in the cart, giving the employee and customer a clear view of the final amount.
- Multi-store: the application supports multiple branches — UGO Cycle (main store), Mascouche, and Warehouse. The employee selects their store at login, and products, prices, and inventories are filtered accordingly.
The Kit Builder: the key innovation
The kit menu is the feature that alone justifies the development of a custom POS. It's the innovation that sets this application apart from any market POS solution.
When an employee adds an electric bike to the cart, the kit menu automatically opens. This slide-in panel presents 12 predefined component categories:
- Motors: rear hub motors, mid-drive motors, different power levels (250W, 500W, 750W).
- Batteries: lithium-ion batteries of different capacities (10Ah, 14Ah, 17Ah, 20Ah).
- Displays: LCD and LED displays with different features (speedometer, battery level, pedal assist).
- Controllers: controllers compatible with different motor/battery configurations.
- Accessories: pedal sensors, wiring, throttles, regenerative brakes, and more.
Each component is added to the cart with a single tap thanks to a slide-in popup optimized for the touch screen. An orange “+ Kits” button appears under each bike in the cart, allowing the kit menu to be reopened at any time to modify the configuration.
The result? What previously took 5 to 10 minutes of manual searching now takes 30 seconds. Configuration errors are virtually eliminated as compatible components are predefined and logically organized.
Lightspeed Integration: the major technical challenge
Integration with Lightspeed R-Series via OAuth 2.0 is the technical backbone of the application. It is also the component that required the most engineering work to ensure reliability.
OAuth 2.0 with tokens in Supabase
Lightspeed uses the standard OAuth 2.0 protocol with limited-lifetime access tokens and refresh tokens. Tokens are securely stored in Supabase with encryption at rest. The full authentication flow (authorization, code exchange, token storage) is managed by the admin panel.
Auto-refresh via pg_cron
The main challenge with OAuth in a serverless environment (Vercel): tokens expire and need to be refreshed regularly. In a traditional server, a background process would handle this. On Vercel, there is no persistent process.
Our solution: use pg_cron, Supabase's PostgreSQL extension that allows scheduling tasks directly in the database. Every 3 minutes, a pg_cron job checks if the token is near expiration and automatically refreshes it via a call to the Lightspeed API.
Distributed lock to prevent concurrent refreshes
In a serverless environment, multiple instances of the application may attempt to refresh the token simultaneously. If two refreshes use the same refresh token, Lightspeed invalidates both and the application loses its connection.
We implemented a distributed lock system in PostgreSQL: before refreshing a token, the process acquires an exclusive lock in the database. If the lock is already taken, it waits for the first refresh to complete and uses the new token. This approach ensures that only one refresh runs at a time, even with dozens of concurrent requests.
Data synchronization
Products, categories, and stores are synchronized from Lightspeed to Supabase. Sales created in the POS are sent to Lightspeed as “pending sales” (without immediate inventory take), allowing the manager to review and complete the sale in Lightspeed according to their usual workflow.
Flexible discount system
UGO Cycle's discount system needed to be more flexible than what Lightspeed natively offers. We developed a two-tier system:
- Per item discount: each product in the cart can have an individual discount — either a percentage (e.g., 10% off) or a fixed amount (e.g., $50 off). The original price is displayed strikethrough with the new price in red, providing clear visibility of the savings.
- Global invoice discount: a discount can be applied to the total invoice — again in percentage or fixed amount. This discount is proportionally distributed across each item when sent to Lightspeed to maintain report consistency.
Both types of discounts can be combined. Tax calculation (GST + QST) automatically adjusts after discounts are applied. All discounts are correctly transmitted to Lightspeed so that sales reports reflect reality.
Checkout and Affirm financing
The checkout flow integrates a customer form and Affirm Canada financing — two critical features for an electric bike business where the average purchase price often exceeds $2,000.
- Integrated customer form: name, email, phone, and address are collected directly in the POS. The information is sent to Lightspeed with the sale for complete customer tracking.
- Pickup store selection: the customer chooses which store they will pick up their bike from — UGO Cycle main or Mascouche. This information is attached to the sale in Lightspeed.
- Affirm Canada OAuth flow: when the customer chooses financing, they are redirected to the Affirm platform in production to complete their financing application. Affirm evaluates the credit, proposes payment terms, and returns the customer to the POS with an approval status.
- Redirection management: the POS correctly handles the three return scenarios from Affirm — confirmation (sale completed), cancellation (return to cart), and error (error message with option to retry or pay differently).
Supabase Cache: performance and independence
A POS that relies on an external API for every action is a fragile POS. If the Lightspeed API is slow or unavailable, sales are blocked. Our cache strategy solves this problem.
- 476+ products cached in Supabase: all products, with their images, prices, SKU, and categories, are stored in PostgreSQL. The POS loads its data from Supabase, not from Lightspeed.
- Instant loading: the POS loads and displays products instantly, without waiting for a response from the Lightspeed API. The user experience is smooth even if Lightspeed is slow.
- Sync cron every 15 minutes: a pg_cron job synchronizes products and categories from Lightspeed to Supabase every 15 minutes. New products, price changes, and inventory updates are automatically reflected.
- Token required only for sales: the Lightspeed OAuth token is only required when a sale is created. Navigation, product search, and cart construction work without an active API connection.
This decoupled architecture means that even if the Lightspeed token expires or the API is temporarily unavailable, employees can continue to use the POS to prepare sales. Only the final submission requires an active connection.
Admin Panel: centralized management
The admin panel is the control center of the POS. It allows managers to configure and monitor all aspects of the application.
- Lightspeed Connection: display of OAuth connection status (connected/disconnected), date of last token refresh, button to initiate or reset OAuth connection. A green/red visual indicator provides an instant overview of the integration's health.
- Product Management: list of 476+ synchronized products with the ability to toggle the visibility of each product in the POS. Discontinued or out-of-season products can be hidden without deleting them from Lightspeed.
- User Management: creation and management of employee and administrator accounts. Two distinct roles: employees have access only to the POS, admins have access to both the POS and the admin panel.
- Secure Authentication: passwords are hashed with SHA-256 server-side. Sessions are managed via secure HTTP-only cookies to prevent session theft by client-side JavaScript.
Results and business impact
The custom POS application has transformed UGO Cycle's daily operations:
- Reduced transaction time: the automatic kit menu has eliminated the 5 to 10 minutes of manual component searching per bike sold. With several bikes sold per day, the time savings are significant.
- Configuration errors eliminated: before the custom POS, component errors (wrong motor, incompatible battery) caused costly returns and reassemblies. The kit menu with its predefined components has virtually eliminated this issue.
- Workflow-adapted interface: instead of forcing employees to adapt to a generic POS, the POS adapts to their way of working. The visual grid, always-visible cart, and kit menu reflect UGO Cycle's exact sales process.
- Integrated Affirm financing: the seamless integration of Affirm Canada allows customers to finance their purchase directly at the point of sale, without parallel processes or additional paperwork. This increases the conversion rate for high-priced purchases.
To discover other projects we have completed, visit our clients page.
Lessons learned
This project taught us several valuable lessons that we now apply in all our custom web application projects:
- pg_cron for OAuth token reliability: in a serverless environment like Vercel, there is no background process to refresh tokens. Moving this responsibility to the database via Supabase's pg_cron is an elegant and reliable solution. The refresh occurs independently of user requests, eliminating expired token issues at the critical moment of a sale.
- Supabase Cache for independence: never rely on an external API for critical daily operations. By caching data in Supabase, the POS remains functional even when the Lightspeed API is slow or unavailable. Periodic synchronization keeps data up to date without affecting real-time performance.
- Distributed lock for serverless environments: serverless functions are stateless and can run in parallel. For operations that should only execute once (like refreshing an OAuth token), a distributed lock in PostgreSQL is essential. Without this mechanism, concurrent refreshes would have regularly invalidated our tokens.
These patterns — local cache, automatic refresh, and distributed lock — are applicable to any application that integrates a third-party API in a serverless environment. We have documented and reused them in our subsequent projects, particularly for integrations with other e-commerce and POS platforms.
If you want to learn more about the benefits of Next.js for this type of project, check out our article Next.js vs WordPress which explains why we choose Next.js for complex web applications. You can also read our case study on the creation of a client portal for a company to see another example of our approach.
Also read
H1Site
Web Agency Vaudreuil