Files
hwilliams-dev/data/content.ts

335 lines
14 KiB
TypeScript

export type MoreSection = {
title?: string;
text: string;
}
export type SocialLink = {
label: string;
url: string;
icon: "gh" | "li" | "x" | "dev";
};
export type ContactMethod = {
masked: boolean;
label: string;
icon: string;
}
export type Project = {
id: number;
slug: string;
title: string;
description: string;
details?: string;
tags: string[];
images?: string[];
videos?: string[];
link: string;
year: string;
};
export const PROFILE = {
name: "Hunter W",
title: "Software Engineer",
email: "contact@hwilliams.dev",
bio: `I build user experiences before I write code.
Experience with full-stack development across a variety of frameworks and languages including Vue,
React, Next.JS, Nuxt, Node.JS, Express, Flask, FastAPI, Gunicorn, and more.`,
moreSections: [
{
title:"A little more about me",
text: `I graduated with a B.S. in Computer Science from Georgia Southern University in May 2025.
I have been working with AWS building analytics and monitoring dashboards with a sprinkle of prompt
engineering on major production projects.`
},
{
text: "I make mods for video games such as Space Engineers and Rimworld in my free time."
},
{
title:"My goals",
text: `User experience. \n \n Nothing makes me happier than seeing someone excited to use the software I make, and the way that happens is by practicing
development techniques that make a good user experience. I especially enjoy peeling back the layers of old systems to explore how an existing
user experience can be improved. I love the words 'Wow, it used to be difficult to do this!'.
`
},
{
title:"My dreams",
text: `Stop me if you've heard this one before: I left college with a burning passion for machine learning and artificial intelligence. It's still there, and despite
the trouble going on in the world right now I see a bright future for how these incredibly advanced statistical models can still be applied in new ways.
\n
`
},
{
title:"Wow, you're still here?",
text: `I appreciate you, but I am totally out of things to talk about.`
}
] satisfies MoreSection[],
moreSectionsStart: 1,
links: [
{ label: "GitHub", url: "https://github.com/FerrenF", icon: "gh" },
{ label: "LinkedIn", url: "https://www.linkedin.com/in/hwilliamsf/", icon: "li" }
] satisfies SocialLink[],
contactMethods: [{
masked: true,
label: "contact@hwilliams.dev",
icon: "email"
}
] satisfies ContactMethod[]
};
export const SITE = {
title: "Hunter W. - Software Engineer",
description: "SWE Looking for work",
source: {
label: "Git",
link: "https://git.hwilliams.dev/hwilliams/hwilliams-dev"
}
};
export const PROJECTS: Project[] = [{
id: 1,
slug: "workflows-app",
title: "Flowdesk: Hit the ground running",
description: "Flowdesk is a microservices platform for breaking down complex business processes into guided workflows with a focus on collapsing the gap between a novice agent and an expert one.",
details: `# Flowdesk: A Flow-based support platform designed for event-based organizations.
<br/>
<blockquote>It's not just "make the UI simpler" but "make a day-one hire perform like a veteran on this task, every time."
<a target="_blank" href="/img/projects/fam/example-welcome.png">
<img src="/img/projects/fam/example-welcome.png" alt="Alt text" width="600"/>
</a>
</blockquote>
<br/>
## App Overview
Flowdesk is a microservices platform for breaking down complex business processes into guided workflows. The focus here is on collapsing the gap in time it takes to perform tasks between a novice agent and an expert one.
The even shorter version: Two agents doing the same check-in shouldn't take 90 seconds and 6 minutes. Flowdesk as a product seeks to compress that spread in variance.
As an objective it is measurable, demonstrable, and directly tied to money (labor cost, queue length, guest satisfaction, throughput per desk). **The metric is time-to-task and its variance - not just the average.**
It's not just "easy software. It's not just "make the UI simpler". It's "make a day-one hire perform like a veteran on this task, every time."
<a target="_blank" href="https://flowdesk.hwilliams.dev">Preview: Flowdesk Development Site</a>
<blockquote>State driven navigation and visual consistency between controls make complex tasks feel easier.
<a target="_blank" href="/img/projects/fam/example-step-2.png">
<img src="/img/projects/fam/example-step-2.png" alt="Alt text" width="800"/>
</a>
</blockquote>
## Private Repository
This is a real product that is in development. The source code is not public, but the platform may soon be available as a service or for licensing.
Please contact me for more information or exceptions to this.
<blockquote>A step demonstrating input components.
<a target="_blank" href="/img/projects/fam/example-step.png">
<img src="/img/projects/fam/example-step.png" alt="Alt text" width="800"/>
</a>
</blockquote>
<blockquote>A short video of the platform's operation. This is a custom implemntation of the architecture for a specific event.
The platform is highly configurable and can be used for many different business processes.
<video width="1000" controls>
<source src="/img/projects/fam/runthrough.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>
</blockquote>
## Details
In Flowdesk, an \`interaction\` is the behavior that occurs between a guest and an agent.
An \`agent\` is a real-person who is interacting with this \`guest\` in order to exchange information or complete some task.
A front-desk employee at a hotel checking in a guest is an easy to reach example.
<blockquote>A standard conversation flow
<a target="_blank" href="/img/projects/fam/standard-conversation-flow.png">
<img src="/img/projects/fam/standard-conversation-flow.png" alt="Alt text" />
</a>
</blockquote>
A normal business day might see these interactions repeated hundreds or thousands of times, and the time taken to complete these interactions
might vary significantly from one agent to another. Each agent can also generally only handle one interaction at a time.
<blockquote>A line of workflows waiting to happen
<a target="_blank" href="/img/projects/fam/flow-lineup.png">
<img src="/img/projects/fam/flow-lineup.png" alt="Alt text" />
</a>
</blockquote>
Scale this up.
Hundreds of guests, or thousands of guests arriving at a high rate. A once a year event, if you will.
<blockquote>An surge of workflows happening all at once
<a target="_blank" href="/img/projects/fam/flow-lineup-at-scale.png">
<img src="/img/projects/fam/flow-lineup-at-scale.png" alt="Alt text" />
</a>
</blockquote>
Okay, most organizations aren't going to have a single agent out there handling such scale, but even with numerous agents the variance in handling time
is a real bottleneck to operations. Little variances in the amount of time spent might have a very high cumulative impact on a business' ability to scale
operation to bursts in demand.
Flowdesk envisions breaking these interactions down into streamlined, consistent, efficient, repeatable, and flexible
workflows that can be completed by agents of any skill level with minimal training.
The images below are more technical documentation, but they do look neat. Bonus points if you get it.
<blockquote>
<a target="_blank" href="/img/projects/fam/workflow-steps.png">
<img src="/img/projects/fam/workflow-steps.png" alt="A workflow divides some business process into a sequence of steps." width="800"/>
</a>
</blockquote>
<blockquote>
<a target="_blank" href="/img/projects/fam/workflow-abandon.png">
<img src="/img/projects/fam/workflow-abandon.png" alt="A workflow is easy to repeat or abandon." width="800"/>
</a>
</blockquote>
<blockquote>
<a target="_blank" href="/img/projects/fam/workflow-sequence-trav.png">
<img src="/img/projects/fam/workflow-sequence-trav.png" alt="A workflow may allow traversal between steps." width="800"/>
</a>
</blockquote>
There is a minimum amount of time that it takes an agent to complete a task in a UI, on average, and a reasonable maximum amount of time that might
be spent on the same task in the same UI, on average. Flowdesk compresses the space between the minimum amount of time taken to complete a task and the maximum aount of time taken.
<blockquote>
<a target="_blank" href="/img/projects/fam/variables.png">
<img src="/img/projects/fam/variables.png" alt="Attempt to demonstrate variance in workflows." width="800"/>
</a>
</blockquote>
# Flowdesk Process
The prerequisite to a good set of Flowdesk is to identify the tasks that are being performed by agents and the time taken to complete these tasks.
Most tasks can be broken down into sequences of steps, and these steps can be made into workflows that are repeatable and consistent.
You divide these more modular tasks into stages, and then create consistent UX/UI experiences for each of these stages.
Some tasks share stages, and some stages are unique to a task. Some stages are simple, and some stages are complex.
Some tasks may even involve one another.
Task identification from business analysis are made into functional workflows that support reducing the time taken to complete tasks while also addressing the variability in
how much time that it takes to complete these tasks.
Flowdesk is not a one-size-fits-all solution, but it is a platform that can be used to create solutions for many different business processes.
Just 50% coverage of tasks can have a significant impact on organizations that have a high volume of interactions with their customers, clients, or guests.
See the testimonial below for a real-world example of how this platform was used to improve the guest experience at a large convention in Atlanta, Georgia.
<blockquote>Technical document. Partial app structure.
<a target="_blank" href="/img/projects/fam/reference-1.png">
<img src="/img/projects/fam/workflow.png" alt="Workflow architecture" width="800"/>
</a>
</blockquote>
## Steps
A step can contain any type of work, and can be used in multiple workflows.
An identification step for a check-in process using the default template might look like such:
<blockquote>The general feel of a workflow step.
<a target="_blank" href="/img/projects/fam/flow-look-1.png">
<img src="/img/projects/fam/flow-look-1.png" alt="Example Step" width="800"/>
</a>
</blockquote>
In this picture, a guest has had their member ID scanned on the first and their profile information is displayed. The first step is now locked and the agent must reset to go back.
The area with a marching border on the right side integrates an external barcode scanner in order to
read information on the back of US driver's license.
This information is compared with the displayed profile on the left, and discrepencies are highlighted in yellow.
Checking the acknowledgement box at the bottom moves the workflow into the next step by fulfulling the step advancement conditions.
<blockquote>The major components of this UI.
<a target="_blank" href="/img/projects/fam/flow-look-2.png">
<img src="/img/projects/fam/flow-look-2.png" alt="Example Step" width="800"/>
</a>
</blockquote>
## Implementation
This platform was implemented as a solution for in-person registration, VIP registration, pre-event mailouts, and entitlements fulfillment for an Atlanta-based organization's yearly convention for May 2026, where it achieved significant success:
The setup consists of a Vue 3 frontend and a configurable backend interface. This particular implementation utilized a Perl catalyst backend. Standard 2D barcode scanning devices and RFID tag readers were used
in the guest identification system and have out-of-the box modular support in flows created on the platform.
<pre>Some Stats:</pre>
- Single day registration of over 10,000 guests with an average processing time of about 45 seconds.
- Previous year: ~2 minutes.
- No single guest wait time greater than 10 minutes.
- Previous year had lines that wrapped around the entire building and there were stories of four hour waits.
<blockquote>A testament
<a target="_blank" href="/img/projects/fam/stats-2026-1.png">
<img src="/img/projects/fam/stats-2026-1.png" alt="Example Step" width="800"/>
</a>
</blockquote>
A real-world solution for event staff and volunteer management.
`,
tags: ["Vue", "Node.JS", "Event-Management", "Real-Time", "Full-Stack"],
link: "https://flowdesk.hwilliams.dev",
year: "2026",
images: [ "img/projects/fam/example-welcome.png", "img/projects/fam/example-step-2.png", "img/projects/fam/example-step.png"],
//videos: [ "img/projects/fam/runthrough.mp4" ]
},{
id: 2,
slug: "clean-space",
title: "Clean Space",
description: "Clean Space is an architecture, proof of concept, and an in-development tool for Space Engineers and Space Engineers 2 server owners featuring client and server side .",
tags: ["C#", ".NET", "WPF", "Netcode", "Security"],
link: "https://github.com/FerrenF/CleanSpace",
year: "2025",
}, {
id: 3,
slug: "personal-portfolio",
title: "Personal Portfolio Website",
description: "This very website! Built with Next.JS, React, and TypeScript. Featuring a custom CMS and a lot of custom-built components and hooks.",
tags: ["Next.JS", "React", "TypeScript", "Vercel"],
link: "https://git.hwilliams.dev/hwilliams/hwilliams-dev",
year: "2026",
}];
import { remark } from "remark";
import remarkParse from "remark-parse";
import rehypeRaw from "rehype-raw";
import rehypeStringify from "rehype-stringify";
import remarkRehype from "remark-rehype";
export async function getProjectDetails(slug: string) {
const p = PROJECTS.find((v)=>v.slug == slug);
if (!p || !p.details) return null;
const re = await remark()
.use(remarkParse)
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeRaw)
.use(rehypeStringify).process(p.details);
return re?.toString();
}