Category Archives: Tech

Revolutionizing Cemetery Data Management with AI-Powered Development

In the ever-evolving landscape of technology, the ability to rapidly develop and deploy software solutions has become a game-changer, particularly in the nonprofit sector. At GiveCamp Memphis, I had the opportunity to apply cutting-edge tools to a real-world problem, helping Center Point Cemetery modernize its data management. By leveraging AI-powered coding with Cursor, I transformed a complex collection of spreadsheets into a fully integrated database solution, all within a remarkably short timeframe.

The Challenge: A Data Maze

Center Point Cemetery, like many historical cemeteries, relied on an extensive but fragmented system of spreadsheets to manage its records. Their database consisted of:

  • 65 separate spreadsheets
    • One “Main Spreadsheet”
    • 63 sub-spreadsheets
    • A cemetery map for plot visualization
  • 2189 plots with names on them
  • A total of 3,041 rows of data

Manually consolidating and cleansing this data would have been an arduous task. The goal was to create a centralized, structured database that could be easily maintained and accessed via a new WordPress-based website.

The Solution: AI-Assisted Development with Cursor

Cursor is an AI-powered coding assistant that emerged as a fork of VS Code in 2023, Microsoft’s open-source code editor. The decision to fork VS Code was driven by the desire to integrate AI more deeply into the development experience, enabling features such as real-time code suggestions, automated debugging, and intelligent refactoring. By leveraging this advanced tooling, developers can streamline workflows and boost productivity without leaving their coding environment.

Given the complexity of the data, I turned to Cursor, an AI-powered coding assistant, to streamline the development process. In just 45 minutes, I was able to:

  1. Generate a Node.js application to handle data cleansing and the merging of all 65 spreadsheets.
  2. Define a package.json file for dependency management, allowing for an efficient and structured workflow.
  3. Develop an automated upload application to transfer all 3,041 rows of cleaned data into the newly built WordPress site.

Code Implementation: Merging and Cleaning Data

What made this process unique was that I never manually typed code into the editor. Instead, I engaged in a conversation with Cursor, describing the problem, refining the logic, and iterating on the solution step by step. Cursor generated the initial code, and through dialogue, I was able to refine it efficiently.

For example, I started with a basic script to merge spreadsheets, but as I interacted with Cursor, I asked it to:

  • Modify the script to dynamically read all .xls and .xlsx files from a directory after I requested this adjustment.
  • Implement logic to ensure that the “Paid” field was correctly mapped from the main spreadsheet when section, row, and plot matched, based on my direction.
  • Improve data cleansing by standardizing date formats and handling missing fields after I pointed out inconsistencies in the dataset.
  • Redesign the upload logic for Advanced Custom Fields (ACF) in WordPress after I instructed Cursor to streamline the integration.

To handle data consolidation, I used Node.js with the xlsx package to read, clean, and merge all spreadsheets dynamically from a directory. The samples are simply samples where the full codebases would be several pages each. 
Here’s an updated snippet:

const xlsx = require('xlsx');
const fs = require('fs');
const path = require('path');

const dataDir = './data'; // Directory containing all Excel files
const mainFile = path.join(dataDir, 'Main.xlsx');
let mergedData = [];

// Function to load data from an Excel file
function loadExcelFile(filePath) {
    const workbook = xlsx.readFile(filePath);
    const sheetName = workbook.SheetNames[0];
    return xlsx.utils.sheet_to_json(workbook.Sheets[sheetName]);
}

// Load main data
const mainData = loadExcelFile(mainFile);
mergedData.push(...mainData);

// Read and process all spreadsheets in the directory
fs.readdirSync(dataDir).forEach(file => {
    const filePath = path.join(dataDir, file);
    if (file !== 'Main.xlsx' && (file.endsWith('.xls') || file.endsWith('.xlsx'))) {
        const data = loadExcelFile(filePath);
        data.forEach(entry => {
            const match = mainData.find(m => m.Section === entry.Section && m.Plot === entry.Plot && m.Row === entry.Row);
            if (match) {
                entry.Paid = match.Paid || 'Unknown';
            }
            mergedData.push(entry);
        });
    }
});

fs.writeFileSync(path.join(dataDir, 'merged_data.json'), JSON.stringify(mergedData, null, 2));
console.log('Data merged successfully!');

Uploading Data to WordPress with ACF

To ensure structured data management in WordPress, we leveraged Advanced Custom Fields (ACF), a powerful tool for handling custom metadata. This allowed us to map cemetery records to dedicated fields for easy retrieval and display.

After merging the data, I needed to upload it to WordPress using the REST API. Here’s an example of how I structured the upload:

const axios = require('axios');
const data = require('./data/merged_data.json');

const WP_API_URL = 'https://example.com/wp-json/wp/v2/cemetery_records';
const AUTH_TOKEN = 'your-auth-token';

async function uploadData() {
    for (const entry of data) {
        await axios.post(WP_API_URL, entry, {
            headers: { 'Authorization': `Bearer ${AUTH_TOKEN}` }
        });
        console.log(`Uploaded: ${entry.Name}`);
    }
}

uploadData().then(() => console.log('Upload complete!'));

AI’s Impact: Accelerating Development

Traditional data integration projects often require weeks of planning, scripting, and testing. With Cursor:

  • Data parsing and validation were automated, ensuring consistency and accuracy.
  • Data transformation logic was quickly generated, reducing manual intervention.
  • Integration with WordPress was streamlined, allowing for a seamless upload process.

Results: A New Digital Presence

By the end of the GiveCamp weekend, Center Point Cemetery had:

  • A fully functional WordPress site with a structured database.
  • A consolidated, searchable record of all cemetery plots.
  • A scalable digital solution that will support future data updates.

Reflections: AI as a Coding Partner

This project was a revelation in how AI can transform software development. Traditionally, coding requires a methodical process of writing, testing, and debugging. With Cursor, I skipped directly to problem-solving.

Instead of manually typing code, I described my intent, and Cursor generated the initial implementation. When refinements were needed—whether to process all .xls files, map the “Paid” field, or improve data cleansing—I simply asked. Cursor adjusted instantly, making the process iterative and frictionless.

This conversational approach to coding didn’t just speed up development; it reshaped how I think about software creation. AI-powered tools like Cursor allow developers to focus on solutions rather than syntax, making high-quality software more accessible—especially for nonprofits that lack extensive technical resources.

GiveCamp Memphis wasn’t just an opportunity to build something useful; it was a firsthand experience in how AI is revolutionizing development. The future of coding isn’t about typing—it’s about collaborating with AI to create solutions faster, smarter, and more efficiently.

You can learn more about GiveCamp Memphis at https://givecampmemphis.org and Center Point Cemetery at https://centerpointcemetery.org.

Back in the Web Dev World

So I’ve switched roles at Microsoft. For the last 11.5 years at Microsoft (which is 9.5 years longer than I thought I’d be here), I’ve been in some form of developer relations. However, I’ve never shipped a product at Microsoft.

In my new role, I’m joining the Web Platform Team to run the Web Applications and Frameworks team – my new title is the Principle PM for WAF. I’m managing two products related to people writing apps with web technologies. The first is WWAHost which is how we write Progressive Web Apps which are native apps written with web standards and technologies.
Check out Get started with Progressive Web Apps for more details.

The second is Webview which is how you incorporate web tech into a standard native app written in .NET, C++ and so on.
Check out Microsoft Edge WebView for Windows 10 apps for more details.

I also work with JavaScript frameworks internal and external to Microsoft. To this end, I’ve got a great dev on my team named John-David Dalton. He’s had a continuous streak of activity on Github since July 23, 2013. This has included building lodash, contributions to Babble and even as far as adding ESM support to Node.JS and NPM.

I’m looking forward to shipping a product that touches millions of people. 🙂

Tessel 2 Nitrogen

I’ve been playing a ton with the IoT space over the past 4-6 months. It’s been a ton of fun from a number of directions.

  1. I love to play with devices. I’ve got Arduinos, Raspberry PIs, Minnow Boards, Galileos and more. But my latest is the Tessel.
  2. I love playing with large scale cloud infrastructures as well.
  3. I love learning new technologies.

This last bit has pushed me in all three of those areas. I’ve been working with Tim Park on an IoT framework called Nitrogen which is built in node.js and runs in Azure. Working on Nitrogen has really pushed my node.js knowledge and I had never done anything with Ember prior to this. And then pile on top of that the vast number of devices out there and there’s something new for me to learn every day. 🙂

Yesterday I started playing with my Tessel and seeing if I could connect it up to Nitrogen’s MQTT gateway. Ivan Judson was kind enough to stand one up for me that I can start playing with. It was ridiculously easy to get going from there.

I started with the Climate Logging over MQTT project found on the Tessel site and modified it for Nitrogen.

The big change with Nitrogen is the format of the topic for subscriptions. Rather than being a simple string is a JSON object. For example, rather than just being “temperature” or something like that, is a subscription to messages routed to this particular device.

var subscription = ‘{“to”: \”‘+deviceId+‘\” }’

Check out all the code on Github at https://github.com/joshholmes/tessel2nitrogen.

https://github.com/joshholmes/tessel2nitrogen