TattleTown — location-based UGC social
A SwiftUI iOS social app anchored to real-world places, with an AI moderation pipeline keeping user-generated content safe. Submitted to the App Store.
What I built
TattleTown — anonymous, place-anchored short stories (“Tattles”) dropped on real-world locations, iOS. A native revival of a 2010–2015 idea: I carried the domain model and retro brand forward, not the code. Live production API; submitted to the App Store.
How it works
Anonymous-first: pick a signature identity, drop a pin, write, and submit. Every submission enters a pending state and passes an AI moderation stage before it can go live — moderation was in the data model from day one. Nearby Tattles surface on a map; QR “Markers” link the physical place to its stories.





How I built it
A deliberate two-layer split. All the logic — models, API client, geo — lives in `TattletownKit`, a Foundation-only Swift package that compiles and tests headlessly (no Xcode), so it can be verified by any sub-agent. The SwiftUI app imports the kit and is the only Xcode-only part.
- Moderation pipeline: submissions flow pending → approved → removed, with an AI stage designed to make anonymous UGC shippable under App Store review.
- Client: URLSession async/await API client (anon device-JWT), haversine geo (no CoreLocation dependency in the kit), a live API at tt-api.woords.io, Dynamic Island compass, push, and web share pages.
- Release discipline: cut on `rc-beta` branches with a handoff per cut; always compile-verify Swift before merge.
Questions this project answers
How do you make anonymous user-generated content safe enough to ship? By designing for it from day one instead of bolting it on. Every submission enters a pending state and passes an AI moderation stage before it can go live — the pending → approved → removed flow was in the data model from the first schema, not added after a problem. That's what makes anonymous, place-anchored UGC defensible under App Store review.
Why split the app into a Foundation-only kit and a thin UI layer? So the logic is verifiable without Xcode. All the models, the API client, and the geo math live in `TattletownKit`, a Foundation-only Swift package that compiles and tests headlessly — which means any sub-agent can verify it, and only the SwiftUI shell needs the full Xcode toolchain. The architecture is shaped by how it gets tested: keep the hard logic where a machine can check it in seconds.
What does "trust and safety by design" look like in a small solo project? It looks like the safety path being load-bearing, not decorative. Nothing a user writes is visible until it clears moderation, the client authenticates with an anonymous device-JWT so there's no account friction but still a revocable identity, and the model was built pending-first. Safety isn't a feature I added — it's the state machine the whole app runs on.
How does an agent-driven workflow change the way you architect an app? It pushes you to make correctness machine-checkable. The Foundation-only kit exists precisely so logic can be compiled and tested outside Xcode by an agent, and releases are cut on `rc-beta` branches with a compile-verify gate before any merge. When agents do the edits, the architecture's job is to make "is this still correct?" a fast, automatable question.
Results
- Live production API (tt-api.woords.io) with a public feature gallery; app submitted to the App Store.
- The Foundation-only kit compiles and tests headlessly (green), keeping logic verifiable without Xcode.
- An AI moderation pipeline built into the model from day one — not bolted on.
Skills
AI / Agentic
- AI moderation pipeline (pending → approved → removed)
Frontend
- SwiftUI
- iOS 17+
- MapKit
- Dynamic Island
- geolocation UX
Backend / Infra
- TattletownKit (Foundation-only SPM, headless-tested)
- URLSession API client (JWT)
- live API (tt-api.woords.io)
- haversine geo
Leadership
- founder & sole engineer
- anonymous-UGC trust & safety design
- App Store submission