Skip to content

Client applications

The golfer-facing clients mirror the same workflow and JSON contract:

  • capture or select a lie photo
  • submit the context to the API
  • display the returned recommendation immediately
  • read the recommendation aloud
  • Built with React 19, TypeScript, PrimeReact, SCSS, Axios, and React Router.
  • API access lives under clubhouse/src/api.
  • Shared contracts live in clubhouse/src/types/index.ts.
  • Pages live in clubhouse/src/pages.
const { data } = await apiClient.post<Photo>('/photos/upload', formData, {
headers: { 'Content-Type': 'multipart/form-data' },
});
  • Built with SwiftUI.
  • Models/Models.swift mirrors the web contracts.
  • Networking/APIClient.swift is the native equivalent of the shared Axios client.
  • Features/Upload/UploadView.swift preserves the same upload and spoken-output flow.
func post<T: Decodable>(_ path: String, query: [URLQueryItem] = []) async throws -> T {
var request = URLRequest(url: try makeURL(path: path, query: query))
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
return try decode(try await send(request), as: T.self)
}
  • Built with Kotlin and Jetpack Compose.
  • model/Models.kt mirrors the iOS and web models.
  • network/ApiClient.kt mirrors the web and iOS transport layer.
  • feature/upload/UploadScreen.kt is the on-course capture flow.
suspend fun postString(path: String, query: List<Pair<String, String>> = emptyList()): String =
execute(Request.Builder().url(buildUrl(path, query)).post(emptyBody).build()).decodeToString()

Parallel structures reduce cognitive load when implementing features across surfaces. A developer can often infer the corresponding code location in another client by understanding the naming and layout in the first one.