
Case Study: Splashlight App for the City of Hilliard Ohio
Bringing together the community of Hilliard through engaging activities and modern aquatics.

Client
Hilliard's Station Park
With splash fountains, outdoor café tables, an amphitheater and public restrooms, Hilliard’s Station Park is the perfect location for community events.
Located at the beginning of the seven-mile Heritage Trail, Hilliard’s Station Park marks the location of an old railroad station and Hilliard’s original town square. The park boasts distinctive architectural qualities that reflect its rich history in the community.
Project
Splashlight for the splashpad
The project utilized Elixir and the Phoenix Framework, deployed on a Raspberry Pi. This technology stack provided scalability, fault tolerance, and cost-effectiveness while minimizing power consumption. Despite challenges such as limited access to previous system documentation, augustwenty’s approach of reverse engineering and stakeholder interviews resulted in a highly reliable and efficient solution.
The final outcome exceeded expectations: zero downtime, significant cost savings, reduced maintenance efforts, and a system ready for future enhancements. The City of Hilliard now benefits from a reliable, autonomous Splash Pad system that meets current needs while offering the flexibility to grow.
The City of Hilliard, Ohio, faced persistent issues with its Splash Pad system, including unreliable performance, outdated technology, and labor-intensive maintenance. Augustwenty was engaged to design a modern, reliable solution that would streamline operations and reduce maintenance costs.
By reverse engineering the original hardware and software, augustwenty implemented a new, scalable system ahead of schedule, integrating additional features at no extra cost. The objective was to create a “set it and forget it” system that required minimal user intervention. Seasonal interns, typically responsible for Splash Pad maintenance, could rely on an automated, time-scheduled system.
Our Approach
Creating context and building understanding
Our research and analysis methods were thorough and data-driven, focusing on gathering comprehensive information about the previous application we were replacing. We collected and reviewed all available documentation, user feedback, and technical specifications of the existing system. This allowed us to gain a deep understanding of its functionalities, performance, and limitations. By leveraging this information, we were able to make informed decisions regarding the technology stack and system requirements for the new application, ensuring that it would not only meet but exceed the capabilities of the previous system.
In addition to analyzing the existing application, we conducted interviews with the Director of Recs and Parks to gain valuable insights into the current advantages and shortcomings of the system. This direct engagement allowed us to understand the specific needs and expectations, which was crucial in shaping the design and development process. By combining this qualitative feedback with our technical analysis, we ensured that the new application would address existing pain points while also incorporating features that would enhance overall efficiency and user experience

Implementation
The strategy of development
To address the challenges of replacing the existing application, we made a strategic decision to use the Elixir programming language with the Phoenix Framework. Elixir's concurrency model, built on the Erlang VM, provided the scalability and fault-tolerance necessary for our application, ensuring it could handle high traffic and multiple simultaneous processes without compromising performance. Phoenix, known for its speed and efficiency, complemented Elixir by offering a robust web framework that allowed us to build a high-performance application with real-time features. This combination ensured that our solution was both powerful and future-proof.
We also chose to deploy the application on a Raspberry Pi, a decision driven by the need for a compact, cost-effective, and energy-efficient platform. The Raspberry Pi’s low power consumption and flexibility made it an ideal choice for our deployment, allowing us to create a portable and reliable solution without sacrificing performance. By leveraging Elixir and Phoenix on a Raspberry Pi, we were able to build a highly efficient system that met our technical requirements while keeping operational costs low.
Challenges faced
One of the significant challenges we faced during the project was the lack of access to the "scenes" used by the previous application, as well as the absence of clear documentation detailing how information flowed through the system. This gap in available resources made it difficult to fully understand the application's internal workings and data structures. Consequently, we had to rely heavily on reverse engineering the application based on user feedback and observable behaviors, as well as piecing together fragmented information from various sources. This added complexity to our analysis and design processes, requiring us to be both creative and meticulous in reconstructing the system's functionality and ensuring that our replacement application could seamlessly integrate and improve upon the existing workflows.
Results
Value focused outcomes
Mobile Friendly
Leveraged a responsive design that adapts to any device, offering fast loading and intuitive navigation enabling numerous ways to interact with the system.

Cost Savings
Achieved significant cost savings by eliminating monthly support expenses and implementing a cost-effective system with minimal downtime.

Reliability
Ensured high reliability with zero downtime since implementation. Increased efficiency through reduced maintenance and fully autonomous operation, saving employee time.

Scalability
Built a future-ready system designed for flexibility, accommodating future enhancements and advanced features when the City of Hilliard is ready.
dmx_channels
|> Enum.with_index()
|> Enum.map(fn {value, index} ->
if index >= start_index and index < start_index + length(dmx_overlay) do
Enum.at(dmx_overlay, index - start_index)
else
value
end
end)
|> Enum.join("," )