How we developed a dashboard tool created to help ease the workflow of managing puzzles for our Connections editor.
By Shafik Quoraishee and Wyna Liu
In the game Connections, every puzzle is a meticulously crafted challenge designed to captivate our audience and spark intellectual curiosity. Developing these puzzles can sometimes be a time consuming and intricate task. Each puzzle requires planning, beginning with conceptualizing fresh categories and plausible misleads, followed by testing the combinations for balance and solvability, and concluding with refinement and publication-ready formatting. The process requires both creativity and quality control.
Wyna Liu, the editor of Connections has the responsibility of constructing and reviewing multiple puzzles spanning various dates, ensuring that each board remains consistent, fresh and challenging to our puzzle solvers. This is a challenging endeavor where there isn’t much room for error. In order to address the challenge, we developed the Connections Reference Dashboard — an in company tool aimed at streamlining data management while providing the puzzle editor with an intuitive, aesthetically pleasing interface that enhances the daily workflow.
There were two considerations in developing this tool. Firstly was technical work in handling a dynamically changing payload of puzzle data. We wanted to create a rich and visually resonating interface that was easy to navigate and gave a bit of the feel of the Connections game itself.
Therefore, everything from the board results to the search interface was designed with these ergonomics in mind. We wanted to create a level of tactility to the tool which was reminiscent of and which reduced the number of manual steps needed to cross reference both categories and words in individual boards.
The primary functionality that Wyna was after was the ability to quickly identify words that have appeared in previous Connections boards, as well as their contexts — the categories they were members of, and the other categories that belonged to that board. Connections is a puzzle built around the novel ‘misleads’. A “mislead” in the game refers to the specific way words are presented or combined within a particular puzzle that might tempt a player to form an incorrect group. An example is the word “ARCHER”, which might mislead you to group it with “BOW”, “ARROW”, and “TARGET” (for “archery terms”), when its intended category is actually “TV SHOWS” with words like “LOST” and “FRASIER.” While words and categories can be repeated over time, the misleads ideally should not. With more than 700 puzzles, keeping track of what has run, on what date, and in what context, has been a vital part of the construction workflow.
Previously, there was no comprehensive search view to assist in checking this easily, either in Google Sheets, where the game is constructed, or in our internal admin tool, where the game is published. The dashboard tool provides all the necessary information at-a-glance, which has been an enormous time saver, especially since searching for words that have previously run is done multiple times while constructing each Connections board.
The backend, built with Flask, serves as the cornerstone of the dashboard. It is responsible for fetching puzzle data from external sources, caching it locally, and ensuring that the data is available in real time for the frontend. One of the key components of our backend is the data caching mechanism, which minimizes unnecessary network calls by checking if data for a given date is already available. If it is not, the system fetches the data from the NYT Connections API and caches it on disk. This not only speeds up subsequent requests but also provides redundancy against network issues. For example, consider the function below, which checks for cached data before fetching new data:
if resp.status_code == 200:data = resp.json()
if data and isinstance(data.get("categories"), list):
puzzle_obj = {}
ALL_PUZZLES[date_str] = puzzle_obj
try:
with open(cache_filename, "w", encoding="utf-8") as f:
json.dump(puzzle_obj, f, ensure_ascii=False, indent=2)
except Exception as e:
print(f"[fetch_puzzle_and_cache] Write error {date_str}: {e}")
return puzzle_obj
In addition to this caching strategy, an auto-fetch mechanism has been implemented to preload upcoming puzzles. This ensures that even future, unpublished boards are available for planning and review. The auto-fetch function calculates a date range that includes several weeks into the future and then iterates through that range to fetch and cache each puzzle.
<script setup>import { reactive, watch, onMounted } from 'vue';
import axios from 'axios';
const state = reactive({
includeUnpublished: true,
puzzles: [],
loading: false,
});
const fetchPuzzles = async () => {
state.loading = true;
try {
const { data } = await axios.get(‘api’', {
params: {
start: state.dateRange.start,
end: state.dateRange.end,
includeUnpublished: state.includeUnpublished,
},
});
state.puzzles = data.puzzleData;
} catch (error) {
console.error('Error fetching puzzles:', error);
}
state.loading = false;
};
onMounted(fetchPuzzles);
watch(
[() => state.dateRange, () => state.includeUnpublished],
fetchPuzzles
);
</script>
The above snippet is an example of how the front end communicates with the server component we set up, through the data api, and all updates occur seamlessly, and allow the addition of filtering parameters that allow for checking whether the results should contain unpublished boards.
The layout is created using Vue.js, employing a grid system to structure four vertical columns, each containing a heading and a list of related items. Each column is encapsulated as an individual Vue component or dynamically rendered from an array of category objects. Data management typically involves an array of objects, with each object containing a category label (e.g., “CONSUMED”, “ALSO”) and an associated list of terms.
Components such as <CategoryColumn> accept props like title and items, displaying each entry within styled containers. Conditional styling for special cells, such as highlighting “HORSE” in yellow, is managed through props or reactive state, signaling active or selected items.
UnoCSS is utilized for styling, ensuring uniformity and rapid development with concise, utility-first CSS classes. The grid layout leverages CSS Grid or Flexbox, providing clear borders, appropriate padding, and interactive hover states.
On the frontend, the choice of Vue.js significantly contributes to a clean, responsive design. The Vue-based interface is intuitive, adapting smoothly across multiple devices and screen sizes. Its reactive nature ensures immediate reflection of changes from the puzzle editor — such as adjustments in date ranges or toggling puzzle visibility — with no noticeable delay.
<template><div class="my-4 p-4 border rounded-lg bg-white shadow">
<input
v-model="searchTerm"
type="text"
placeholder="Search for a word..."
class="w-full p-2 border rounded focus:outline-none focus:ring focus:border-blue-300"
/>
<ul v-if="filteredWords.length" class="mt-4 space-y-2">
<li
v-for="word in filteredWords"
:key="word"
@click="selectWord(word)"
class="cursor-pointer p-2 bg-blue-100 hover:bg-blue-200 rounded"
>
{{ word }} (found in {{ getFrequency(word) }} puzzles)
</li>
</ul>
<div v-else class="mt-4 text-gray-500">No words match your search.</div>
</div>
</template>
Vue’s built-in directives like v-model, v-if, v-for, and @click dramatically simplify the process of building interactive components. In our live word search feature, these directives let us handle input binding, conditional rendering, list generation, and event handling — all in a few lines of clean, declarative markup. This approach reduces boilerplate and eliminates manual DOM manipulation, allowing the puzzle editor to interact with a responsive, real-time interface without the overhead of complex logic or state wiring.
An advancement in the puzzle review process brought about by this dashboard is the ability to look up the construction history of puzzles in terms of how often duplicate words occurred. What was once a time-consuming procedure has been streamlined into an efficient workflow. We are able to, through the backend, look up duplicates through the use of a word-frequency count. This allows one to observe how often puzzles with recurring words are present and the spacing in time of puzzles with duplicate words occur. Take for instance ‘BALL’, which occurred 23 times so far through the history of connections.
We also created a convenient method of looking up the frequency count of all words used in connections in descending order of their usage. This not only provides interesting construction information about connections, but could also lead to interesting statistical analysis, such as separation distance between words over time, least frequency used words, and most frequently used words.
The search itself is multi-facetted with several capabilities. The user can search through all the words in all the boards over the duration and lifetime of Connections through using a basic word search for exact matches, and for words contained as parts of other words through the use of regex search. Not only words on their own can be searched for, but categories and category titles as well, which present different snapshots into how words were previously used and in what combination with other words in specific groupings. This can help with organizing future puzzles and providing insights to new category possibilities.
I was excited to collaborate with Wyna on this opportunity as it was an amazing experience in working with editorial to make useful tools to come to life, and give me as a developer the feeling im building something positive that contributes to the mission of the Games Team bringing joy to our users by helping the creative process (in addition to working on the actual games).
In order to build the tool to be as useful to Wyna as possible, I had to make sure to really work the board to be rapidly prototypable so different combinations of optimal systems could be swapped in and out. Sometimes the optimal product and tool isn’t known until you go through several iterations.
And unsurprisingly to me, the process was not only an incredible learning experience, and an opportunity to work with Wyna, but also a ton of fun, and an opportunity to exercise my skills in tool building, which as a developer I feel compelled to build systems that provide joy to others.
Looking ahead, the architecture of the Connections Reference Dashboard is designed to be future-proof and scalable. The modular approach — where the backend and frontend operate as separate yet integrated components — allows for easy enhancements and the addition of new features over time. This flexibility means that as the needs of the puzzle editor evolve or as new challenges arise, the dashboard can be updated and expanded without disrupting the existing workflow
Happy puzzling!