Writing and Video Portfolio

I've spent almost my entire 20 year career in large enterprise data centers and SaaS technology. During that time, I've built a broad, adaptable skillset in documentation and training, process and procedure standardization, solution engineering, troubleshooting and root cause analysis, large-scale implementation and remediation, and cross-team/cross-organization coordination. I know that sounds like buzzwords, but it's no exaggeration.

My documentation and video toolkit has spanned several different software titles over the years:

  • Git Repos: GitHub | Bitbucket
  • Git Clients: Tower | SourceTree | VS Code
  • Productivity: Google Workspace | Office 365
  • Developer Tools: VS Code | BBEdit
  • Documentation & Training: Camtasia | SnagIt | Markdown | Hugo | Confluence | Readme.com
  • Task Management: Jira | Jira Service Manager | Trello | Microsoft Planner
  • Diagramming: Miro | LucidChart | Draw.io | Visio
  • Work OS: Apple iPadOS and macOS (preferred) | Windows 10/11 (experienced)

This site uses the following technologies: Cloudflare (Websites, Analytics, Pages), Github, Hugo, Markdown, and the Hugo Clarity theme.

About Public Content Below

Note that some of the content below was written by me but owned by another organization, and may be removed at any point in time.

Documentation

Category Document Description
Hands-On Lab Getting Started with Digital Workspace I designed and authored this lab's Apple iOS (Module 2) and macOS (Module 3) sections. These modules are aimed at customers and prospects new to Workspace ONE and unified endpoint management concepts. In addition to the initial source, I maintained these modules every 6 months as we updated the backing SaaS environment to adopt new features. Most of this content was authored based on my expertise, though I reviewed it with product managers for final sign-off.
Troubleshooting Troubleshooting macOS Management This comprehensive troubleshooting document served as a tutorial for macOS Administrators needing to troubleshoot Workspace ONE functionality. I was responsible for the first three iterations of this guide and used it primarily as a tool for knowledge sharing with both coworkers and customers. I wrote this content in ScreenSteps based on my own testing and research. I collaboraed with the Support SMEs and macOS Product Managers for peer review.
Tutorial Managing iOS Updates I authored this tutorial to clarify the configuration process and expected behaviors for a feature (iOS Update Management) across multiple versions of iOS. The idea for this document was sourced from a Product Manager, but the content was based on my testing and authored in ScreenSteps.
Glossary Mapping concepts from Munki to Workspace ONE UEM At the time I authored this page, I was receiving numerous questions about a recently-released integration between Workspace ONE UEM and Munki. This glossary page linked the Workspace ONE equivalents to the Munki terminology many of the macOS community knew. I wrote this on my personal blog (using Markdown, Hugo, and VS Code) for the benefit of the macOS admin community.
Best Practices Best Practices for Apple Admins in Workspace ONE UEM I wrote this best practices document after reading a blog article about the loss of a system administrator. The point of this guide was to show prospective Apple Administrators how to set their environments up for survivability of the unexpected (layoffs, catastrophic accident, etc). The toolset for this is also Markdown, Hugo, and VS Code.

How-To Videos

I created this video for a "Developer Month:" 28 days of posts to Git Commit(ted) to Dev Resources. In this video, I'm using a hands-on demonstration to describe the components of an API and how to use the Workspace ONE API specifically. I wrote the entire video script, recorded the demos and voiceover, and put it all together in Camtasia.

I created the following video to illustrate a new feature released in the Workspace One Intelligent Hub for macOS. As with most feature walk-through videos (and internal training documents), I worked directly with the Product Manager to understand the feature and intended use cases. Then, I created the script and recorded all the screenshots and videos directly from my device and test environment. Like the previous video, I wrote the entire script, recorded the demo screens and voiceover, and put it all together in Camtasia.

Code Sample

I strive to find repeatable processes and automate them. At one employer, I created multiple product satisfaction surveys in Gainsight PX. I wrote a script to combine the responses from all the surveys into a single CSV file (that also integrated additional information about the respondents and the accounts to which they belong). In the snippet below, I use Python to aggregate the responses from a single survey in Gainsight PX. I subsequently posted this Github Gist to the Gainsight PX Community to assist others in learning how to leverage the scrollID to return multiple pages of data from the API. The full version of this script included additional helper functions for the additional API's (account/user info) and loops (aggregating responses from multiple surveys).

 1# Example Gainsight Paging API Call
 2
 3##############################################################################
 4# Reference API documentation:
 5# https://gainsightpx.docs.apiary.io/#reference/surveyresponse
 6#
 7# Use the returned scrollId to make a request for the next page of results (i.e. /users?pageSize=100&scrollId=XXXXXXX)
 8# Scroll until the returned result list is less than the requested size. Do not depend on the scrollId becoming null,
 9# in some cases it does not be null even though the last page of results is returned.
10##############################################################################
11
12
13import json, requests, sys
14from datetime import datetime, timedelta, date
15
16##############################################################################
17## CONSTANTS
18##############################################################################
19
20# BaseURL for API calls
21BASE_URL = "BASE-URL-HERE"
22# API Key Name
23API_KEY_NAME = "X-APTRINSIC-API-KEY"
24# API Key Value
25API_KEY_VALUE = "GUID-HERE"
26# API Page Size
27API_PAGE_SIZE = 100
28# Survey Engagement ID
29ENGAGEMENT_ID = "ENGAGEMENT-ID-HERE"
30
31
32##############################################################################
33## HELPER FUNCTION
34##############################################################################
35
36# create a function to get the list of survey responses for a specific survey
37def get_surveyresponsesapi(engagementId, scrollId, datefiltertimestamp):
38
39    if scrollId == "":
40        # Set the request url for the first page of results
41        if datefiltertimestamp == "":
42
43            url = BASE_URL + "/v1/survey/responses?filter=engagementId=="+ engagementId + "&pageSize=" + str(API_PAGE_SIZE) + "&sort=-date"
44
45        else:
46
47            url = BASE_URL + "/v1/survey/responses?filter=engagementId=="+ engagementId + ";date>" + str(datefiltertimestamp) + "&pageSize=" + str(API_PAGE_SIZE) + "&sort=-date"
48
49    else:
50        # Set the request url for the subsequent pages of results
51        url = BASE_URL + "/v1/survey/responses?filter=engagementId=="+ engagementId + "&pageSize=" + str(API_PAGE_SIZE) + "&sort=-date" + "&scrollId=" + scrollId
52
53    payload={}
54    headers = {
55    'Accept': 'application/json',
56    API_KEY_NAME: API_KEY_VALUE
57    }
58
59    # Make the API call
60    return requests.request("GET", url, headers=headers, data=payload)

See more of this code at my Gist