Helping businesses turn their ideas into reality

We are a passionate team of developers, entrepreneurs, and technology enthusiasts based in England. We’ve partnered with dozens of startups to turn their ideas into successful, profitable businesses.

Crafting user experiences
Building scalable products

We're your all-in-one project solution

Experience the advantage of an all-inclusive project solution, where excellence, speed, and responsiveness converge to ensure the highest quality outcome.

  • Excellence

    We care about doing great work. Every project gets our full attention and highest quality.

  • Speed

    We work fast and stay focused — not just for speed’s sake, but to deliver real value on time, where it matters most.

  • Responsiveness

    You can count on us to communicate clearly and respond quickly, every step of the way.

Years of experience
15+
Projects completed
100s
The tools I use on my day-to-day

Our latest work

My goal is to create effective digital experiences that make people’s lives easier and better. I hope my work is a reflection of this.

ruby-on-rails-development
fastapi
python

EventScope: Edge-to-Cloud Analytics for Live Event Intelligence

Infinity Loop developed EventScope for Johnson & Johnson’s Medical Division — a real-time, privacy-first analytics platform that reveals how visitors engage with booths and content during live events. Using edge computing and computer vision, it provides actionable insights on dwell time, engagement, sentiment, and interactions without relying on cloud connectivity.

View Case Study
node

Alertive API: Serverless Messaging Infrastructure

We developed a production-grade serverless API for Alertive's enterprise messaging platform, enabling automated alerts, task management, and real-time conversations. The API integrates with existing XMPP infrastructure while providing modern REST endpoints backed by comprehensive OpenAPI documentation and OAuth 2.0 security.

View Case Study
design
python
fastapi

Interactive Photobooth for Johnson & Johnson Medical - EADV 2025

Developed a sophisticated interactive photobooth application for Johnson & Johnson Medical at the European Academy of Dermatology and Venereology (EADV) conference.

View Case Study

Carwow

We were brought in to support Carwow in enhancing their online automotive marketplace, working alongside their tech lead to deliver new features, improve platform stability, and ensure long-term scalability.

View Case Study

Thoughts on design, business and indie-hacking

How to Modernize a Legacy Ruby on Rails App with Zero Downtime

**Upgrading a legacy Ruby on Rails application** can feel like changing the engine of a moving train. Users expect stability, while engineers wrestle with outdated dependencies, brittle code, and zero downtime requirements. This guide walks through a proven approach to modernizing a Rails app safely, from code auditing to deployment, without breaking production. ## Why Modernization Matters Over time, even well-built Rails applications start to slow down: - Outdated gems introduce security risks - Monolithic codebases become hard to extend - Test coverage drops as features grow - Deployments feel risky and time-consuming Modernization isn’t just about chasing the newest Rails version, it’s about **restoring developer confidence and ensuring long-term scalability**. ## 1. Start with a Code Audit Before touching a single file, understand where your app stands today. ### Inventory Your Stack - Ruby version and Rails version - Database engine and adapters - Frontend framework (if any) - Background job systems (Sidekiq, Resque, etc.) - CI/CD tools and hosting environment Use tools like `bundle outdated` to identify obsolete dependencies and potential conflicts. ### Assess Dependencies Check each gem’s support window and compatibility with your target Rails version. Pay attention to: - Deprecated gems - Forked libraries with unmaintained code - Security vulnerabilities (`bundle audit` is your friend) ### Evaluate Architecture Look for: - Tight coupling between models and controllers - Overgrown ActiveRecord models - Missing service layers or presenters Document pain points — these notes become your modernization roadmap. ## 2. Strengthen Test Coverage Your tests are the **safety net** for any major refactor. ### Measure Coverage Run `simplecov` to see which files are untested. Prioritize: - Business-critical flows - Controllers that handle payments, authentication, or data mutations ### Add Missing Tests If tests are weak, start with **request specs and smoke tests** — you don’t need perfect coverage, just protection around key paths. ### Automate Testing Set up CI with GitHub Actions, CircleCI, or GitLab CI. Even a minimal pipeline running `bundle exec rspec` and `rubocop` adds huge value. ## 3. Plan Incremental Refactors Modernization should be **iterative**, not a “big bang.” ### Techniques for Safe Refactoring - **Feature flags:** Gradually roll out changes to small user groups - **Service objects:** Extract logic from controllers to simplify testing - **Background migrations:** Avoid long-running DB locks - **API versioning:** Introduce new endpoints without breaking existing clients Each small refactor should leave the app in a working state — the **Boy Scout Rule**: *always leave the code cleaner than you found it.* ## 4. Upgrade Rails (Step by Step) Upgrading between major Rails versions (e.g., 5 → 6 → 7) is safer than jumping directly. ### Recommended Path 1. **Lock gem versions** in `Gemfile.lock` 2. **Run tests**, fix deprecations, and clean warnings 3. **Upgrade Ruby**, then the smallest Rails version increment 4. **Test and deploy** between each step Use [railsdiff.org](https://railsdiff.org) to compare versions and see what’s changed. ## 5. Achieve Zero-Downtime Deployments The biggest modernization fear: downtime during release. ### Blue-Green or Rolling Deploys Run two environments (old and new). Deploy to the new one, verify it, then switch traffic instantly. ### Database Migration Safety - Avoid destructive changes (e.g., dropping columns) in live migrations - Use the `strong_migrations` gem to catch unsafe operations - For large tables, migrate in batches with background jobs ### Caching and Assets Precompile assets and warm caches before switching traffic. This prevents initial load spikes. ## 6. Monitor, Measure, and Iterate After upgrading, monitor performance metrics and logs closely. - Track request times, error rates, and memory usage - Use tools like Skylight, New Relic, or Datadog for visibility - Schedule regular dependency updates (monthly or quarterly) Modernization isn’t a one-time project, it’s an **ongoing process of keeping technical health aligned with business goals**. ## Conclusion Modernizing a legacy Ruby on Rails app doesn’t require downtime or chaos. With careful auditing, strong tests, and incremental refactors, you can evolve your codebase confidently — while users keep enjoying a seamless experience. **Next step:** [Download the Rails Modernization Checklist →](#) ### FAQs **1. How long does a Rails upgrade take?** It depends on your codebase size and test coverage. A well-tested app can upgrade in weeks; untested monoliths may take months. **2. How do you test database migrations safely?** Run them on staging with production data clones and use `strong_migrations` to detect locking operations. **3. Can I modernize Rails 4 directly to 7?** It’s risky. Upgrade incrementally (4 → 5 → 6 → 7) to avoid breaking dependencies. **Primary Keyword:** rails upgrade guide **Secondary Keywords:** legacy modernization, app refactoring, zero downtime deploys, ruby on rails upgrade

minute read
ruby-on-rails-development

Rails Testing Gotcha: When Concerns Work in Console But Not in Tests

If you've ever encountered a situation where your Rails model associations work perfectly in the console but mysteriously fail in your test suite, you're not alone. I recently ran into this exact issue and wanted to share the solution along with some insights about Rails' autoloading behavior. ## The Problem I was working with a Rails app that uses concerns to share common functionality across models. One of these concerns, `Addressable`, defines a polymorphic association: ```ruby module Addressable extend ActiveSupport::Concern included do has_many :addresses, as: :addressable, dependent: :destroy accepts_nested_attributes_for :addresses, allow_destroy: true, reject_if: :all_blank end def full_address address = addresses.last return "No address available" if address.nil? # ... rest of method end end ``` My `Estate` model includes this concern: ```ruby class Estate < ApplicationRecord include BelongsToOrganisation include Addressable include ActiveAccountingPeriod has_many :blocks has_many :properties, through: :blocks # ... other associations end ``` Everything worked beautifully in the Rails console. I could create estates, add addresses, and call all the methods from the concern without any issues. But then my FactoryBot tests started failing: ```ruby # spec/factories/estates.rb FactoryBot.define do factory :estate do sequence(:name) { |n| "Estate #{n}" } association :organisation after(:create) do |estate| estate.addresses << build(:address, addressable: estate) end end end ``` The error was confusing: ``` NoMethodError: undefined method 'addresses' for an instance of Estate ``` ## The Investigation What made this particularly puzzling was that the concern seemed to be loaded properly. When I added debug output to check the model's ancestors, I could see `Addressable` was included: ```ruby puts estate.class.ancestors # => [Estate, ActiveAccountingPeriod, Addressable, BelongsToOrganisation, ...] ``` But when I checked the available associations: ```ruby puts estate.class.reflect_on_all_associations.map(&:name) # => [:pay_customers, :charges, :subscriptions, :blocks, :properties, :expense_categories, :transactions, :accounting_periods] ``` Notice what's missing? The `addresses` association from the `Addressable` concern wasn't there. ## The Root Cause The issue stems from Rails' different autoloading behavior between development and test environments: **Development Environment:** - Rails uses lazy loading - When you reference `Estate` in the console, Rails loads the model and properly includes all concerns - The `included` block in concerns executes when the model is first loaded **Test Environment:** - Rails optimizes for fast test startup - Models and concerns aren't always loaded in the same order or manner - The `included` block in concerns might not execute before your tests run ## The Solution The fix is to explicitly require your concerns and models in your test setup. Add this to your `rails_helper.rb`: ```ruby # spec/rails_helper.rb Dir[Rails.root.join('app/models/concerns/*.rb')].each { |f| require f } Dir[Rails.root.join('app/models/*.rb')].each { |f| require f } ``` This ensures that all your models and their concerns are loaded before any tests run, making the test environment behave consistently with development. ## Alternative Approaches There are a few other ways to solve this issue: ### 1. Eager Load Everything ```ruby # In rails_helper.rb RSpec.configure do |config| config.before(:suite) do Rails.application.eager_load! end end ``` This loads your entire application, which is more comprehensive but potentially slower. ### 2. Adjust Test Environment Configuration ```ruby # config/environments/test.rb config.eager_load = true ``` Though this changes the fundamental behavior of your test environment. ### 3. Force Model Loading in Factories ```ruby # At the top of your factory file Estate # Forces the model to load FactoryBot.define do factory :estate do # ... factory definition end end ``` ## Why This Matters This issue highlights an important aspect of Rails development: the framework's autoloading behavior can vary between environments. While this usually works seamlessly, it can occasionally lead to subtle bugs that are hard to track down. The explicit `require` approach I used is targeted and fast—it only loads what you need rather than the entire application. It's also explicit about the dependency, making it clear that your tests rely on these files being loaded. ## Takeaways - **Environment differences matter**: Always test your code in the same environment where it will run in production - **Explicit is better than implicit**: When in doubt, explicitly require the files you need - **Debug systematically**: Use Rails' reflection methods to understand what's actually loaded - **Consider autoloading**: Be aware of how Rails loads your code in different environments Have you encountered similar issues with concerns and testing? I'd love to hear about your experiences and solutions in the comments below. This post originally started as a question to the Rails community on Discord and Twitter. Thanks to everyone who shared their insights and experiences!

minute read

How Small Businesses Can Build Their Own Website Using Wix, WordPress, or Shopify — No Agency Needed

Need a website for your business but don’t have the budget for a web agency? You’re not alone—and the good news is, **you can absolutely do it yourself**. Whether you run a café, offer services, or sell products, platforms like **Wix**, **WordPress**, and **Shopify** offer powerful tools that let you launch a clean, professional website in just a few hours—with no coding required. This article breaks down the best options for small business owners and walks you through how to get started. ## ⚙️ 1. Wix: Drag-and-Drop Simplicity Best for: Local businesses, service providers, portfolio sites, one-pagers ### Why choose Wix? - Super easy drag-and-drop editor - Hundreds of pre-designed templates - Built-in hosting and SSL - Great for “set it and forget it” websites ### What you can do: - Add sections like “About Us”, “Contact”, or “Book Online” - Set up a blog or image gallery - Connect a custom domain (e.g. yourname.com) Costs: Free to start; paid plans with custom domain from ~£10/month 🔗 [Start with Wix](https://www.wix.com/) ## 🌐 2. WordPress.com: A Bit More Flexible Best for: Small businesses who may grow into more complex needs (e.g. blogging, SEO, integrations) ### Why choose WordPress.com? - Open-source power with a user-friendly interface - Tons of themes and plugins - Built-in blogging tools - Room to grow (and upgrade later) ### What you can do: - Build multi-page websites with menus, forms, and maps - Add plugins for bookings, email newsletters, or reviews - Improve SEO with tools like Yoast Costs: Free basic site; business plans start at ~£7/month 🔗 [Get started with WordPress](https://wordpress.com/) ## 🛒 3. Shopify: The Best Choice for Online Stores Best for: Product-based businesses (ecommerce), shipping physical or digital goods ### Why choose Shopify? - Everything you need to launch an online store - Easy inventory, payments, and shipping setup - Mobile-optimised checkout - Built-in analytics ### What you can do: - Add unlimited products - Accept card payments and PayPal - Connect Instagram/Facebook shopping Costs: Starts from ~£25/month (14-day free trial available) 🔗 [Start your store with Shopify](https://www.shopify.com/) **🧠 Tips for Going DIY Successfully** - Start with a template — don’t build from scratch - Keep it simple — focus on key info: what you do, who you are, how to contact you - Write your content first — then choose a layout that fits - Test on mobile — most visitors will view your site on their phones - Buy your own domain — it looks more professional and builds trust ## 👋 Final Thought: You Can Do This If you can write a few paragraphs and upload a photo, you can absolutely create your own website. Wix, WordPress, and Shopify give you the tools—you just need to take the first step. And if you ever need help down the line (e.g. integrations, custom design, or upgrading your site), an experienced web development team (like us 👋) is always here when you’re ready.

5 minute read

Subscribe to our newsletter

Join 10,000+ entrepeneurs and get creative site breakdowns, design musings and tips directly into your inbox.