Project examples
A few examples of how I approach designing and delivering production platforms. Examples are taken from my own passion projects, I do not show client work.
Bitszer: in-game trading platform
Bitszer lets gamers trade and interact with each other directly inside the games they play. I built the core platform and SDK that shipped on the Unity Asset Store, with support for both iOS and Android titles.
Bitszer-powered games have been downloaded over 100,000 times, so the platform had to handle real player traffic and unpredictable usage patterns without drama.
- • Clear separation between game, trade, and wallet domains using domain-driven design.
- • Contract-first SDK design so Unity developers integrate with a small, stable surface area.
- • Observability-by-default: structured logs, metrics, and traces around every trade flow.
- • CI pipelines that validated the SDK across Unity versions and mobile platforms before release.
Adszer: real-time ad distribution
Adszer is a real-time ad distribution platform where advertisers can gather genuine feedback from potential customers, and users get paid when they're selected to view an ad.
I designed and implemented a proprietary model that builds profiles for users based on their input and historical responses. As new ads arrive, they're matched to users in real time based on advertiser preferences and budget.
Users receive push notifications on their phones; if a user declines an ad or doesn't respond, the system selects and notifies the next best candidate automatically.
- • Event-driven matching pipeline that reacts to new ads, budget changes, and user responses.
- • Profile-based targeting model tuned from real user feedback, not just static demographics.
- • Feedback loops from responses back into the model to improve assignment quality over time.
- • Budget-aware assignment logic that stays robust under changing traffic and inventory.
Tip the Play: NIL compliant fan tipping platform
Tip the Play is a platform that lets fans send monetary tips and messages directly to college athletes. I built the platform end to end, from authentication and authorization to payments and the web experience.
The system handles sensitive flows like onboarding athletes, linking payout accounts, creating payment intents, and surfacing tip history and messages in a way that's simple for athletes but safe for the business.
- • Authentication and user management via AWS Cognito with clear separation between fans and athletes.
- • GraphQL APIs (AppSync) for profile data, messages, and tipping flows, with strict, typed contracts.
- • Stripe integration for payments and payouts, using idempotent operations and well-defined webhooks.
- • Next.js front end designed around clear states: onboarding, active accounts, pending verification, and error handling.
- • Security-by-default: least-privilege access patterns and guardrails around financial operations.
Code samples
A few representative snippets that show how I approach infrastructure, AppSync pipeline resolvers, and VTL with authorization baked in.
getMySentMessages:
handler: functions/get-my-sent-messages.handler
environment:
USERS_TABLE: !Ref UserTable
MESSAGES_TABLE: !Ref MessagesTable
logRetentionInDays: 30
iamRoleStatements:
- Effect: Allow
Action:
- dynamodb:GetItem
Resource: !GetAtt UserTable.Arn
- Effect: Allow
Action:
- dynamodb:Query
Resource:
- Fn::Join:
- "/"
- [!GetAtt MessagesTable.Arn, "index/byFrom"]CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Enabled: true
Origins:
- DomainName: !GetAtt ContentBucket.RegionalDomainName
Id: S3ContentBucket
S3OriginConfig:
OriginAccessIdentity: ''
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
CachedMethods:
- GET
- HEAD
TargetOriginId: S3ContentBucket
ViewerProtocolPolicy: redirect-to-https
ForwardedValues:
QueryString: false
Cookies:
Forward: none
ViewerCertificate:
CloudFrontDefaultCertificate: true
DefaultRootObject: index.html
PriceClass: PriceClass_100
Restrictions:
GeoRestriction:
RestrictionType: whitelist
Locations:
- US
Tags:
- Key: Environment
Value: ''
- Key: Name
Value: cloudfront-distribution# Build UpdateExpression dynamically from non-null input fields
#set($updateExpression = "set")
#set($expressionValues = {})
#set($expressionNames = {})
#foreach($key in $context.arguments.adsInput.keySet())
#set($value = $context.arguments.adsInput[$key])
#if(!$util.isNull($value))
#if($util.isString($value) && $value == "")
## Skip empty strings
#else
#set($updateExpression = "$updateExpression #$key = :$key,")
#if($util.isList($value))
#set($dynamoDBList = [])
#foreach($item in $value)
$util.qr($dynamoDBList.add($util.dynamodb.toString($item)))
#end
#set($expressionValues[":$key"] = {"L": $dynamoDBList})
#elseif($util.isNumber($value))
#set($expressionValues[":$key"] = {"N": "$value"})
#else
#set($expressionValues[":$key"] = {"S": "$util.escapeJavaScript($value)"})
#end
#set($expressionNames["#$key"] = $key)
#end
#end
#end
#set($len = $updateExpression.length() - 1)
#set($updateExpression = $updateExpression.substring(0, $len))
{
"version" : "2018-05-29",
"operation" : "UpdateItem",
"key": {
"id": $util.dynamodb.toDynamoDBJson($context.identity.username)
},
"update" : {
"expression" : "$updateExpression",
"expressionNames" : $util.toJson($expressionNames),
"expressionValues" : $util.toJson($expressionValues)
}
}