Browser SDK · v0.1 beta
Install and initialize graphics-js.
Render a clean CADDIE.100 golf graphic into a dedicated DOM element, then add protected Smart Components and client-authored Annotation primitives in an independent interactive layer.
Installation
Add the SDK to a client application.
Install the package with the package manager used by your web project. Graphics JS exposes TypeScript types with its browser client, rendered asset, mounted view, graphic request, and overlay component contracts.
npm install @caddie100/graphics-jsc100_pk_live_… or c100_pk_test_… publishable key. Never ship a private c100_live_… or c100_test_… credential in browser code.Initialization
Create one client for the experience.
createCaddie100Client validates the key family immediately and uses the CADDIE.100 production origin by default. A custom baseUrl, fetch implementation, credentials mode, or bounded image-cache policy can be supplied for controlled environments and testing.
import { createCaddie100Client } from "@caddie100/graphics-js";
const caddie = createCaddie100Client({
apiKey: "c100_pk_live_…",
imageCache: {
maxAgeMs: 2 * 60 * 60 * 1000,
},
});First mount
Give Graphics JS a dedicated element.
mount renders the requested artifact, fetches it as an authenticated browser blob, and replaces the container contents with an SDK-controlled viewport. Inside it, an aspect-ratio-locked stage holds both the responsive image and component layer. Smart Components are optional and can be added when the view is first mounted, reconciled later with setSmartComponents, or appended with addSmartComponent. Component types may repeat; stable IDs keep their controls independent. Local Image, Shape, and Text Annotations can be added with setAnnotations.
Every Smart Component color field accepts the shared GraphicColor format: transparent, #RRGGBB, #RRGGBBAA, rgb(r,g,b), or rgba(r,g,b,a). Alpha is preserved during server resolution and local restyling; a component's separate opacity control multiplies the color alpha when both are supplied.
<div id="course-graphic"></div>
<script type="module">
const container = document.querySelector("#course-graphic");
const view = await caddie.mount(container, {
courseId: "COURSE_ID",
subject: { type: "hole", holeNumber: 1 },
output: { format: "webp", width: 900, height: 1500 },
}, [], {
fit: "contain",
});
// Release the blob URL and DOM when this experience unmounts.
// view.destroy();
</script>Keep the returned CaddieGraphicView. It owns visibility, styles, movement, reset state, event delivery, reconciliation, a bounded artifact-specific placement cache, and cleanup for every component on that graphic.
Responsive stage
One coordinate plane at every browser size.
The requested output width and height define the stage's internal pixel coordinate system and aspect ratio. Graphics JS applies one uniform scale to that stage, its image, and every overlay. A smaller same-ratio host therefore preserves exact placement, while a differently shaped host never stretches the image independently from its components.
contain
Fits the complete graphic against both dimensions of a fixed card, modal, split pane, or viewport. Unused space is centered instead of cropping the artifact.
width
Fills the available width and derives height from the artifact ratio. Use it when the host grows naturally or deliberately scrolls.
A ResizeObserver responds to responsive columns, sidebars, orientation changes, and resizable panels. Call view.setStageFit("width") to change policy locally or view.refreshLayout() after an unusual host mutation. view.destroy() disconnects the observer.
mount. The internal .c100-graphic stage is the image-coordinate plane and should not receive independent dimensions or padding.Loading state
Observe the whole visual lifecycle.
Each mounted graphic has one immutable GraphicLoadingState. Its status remains loading while the artifact, base image, protected Smart Components, or component images needed by the requested presentation are unfinished. It becomes idle only after all overlapping visual work settles.
Graphics JS also renders loading UI by default: a configurable graph-paper stage with a rolling inline-SVG golf ball during the descriptor, artifact, and base-image wait, followed by a small corner spinner only while protected Smart Component responses are pending. These visuals use CSS transforms, require no extra asset request, and become static when the browser requests reduced motion.
const view = await caddie.mount(container, graphicRequest, components, {
loadingUi: {
image: {
backgroundColor: "#07110D",
grid: { color: "rgba(255, 255, 255, 0.08)", gap: 32, lineWidth: 1 },
ball: {
color: "#FFFFFF",
dimpleColor: "rgba(7, 17, 13, 0.22)",
groundColor: "#A3FF12",
size: 44,
durationMs: 900,
label: { text: "Loading", color: "#CBD5E1" },
},
delayMs: 120,
},
smartComponents: {
color: "#A3FF12",
trackColor: "rgba(255, 255, 255, 0.22)",
scale: 1.1,
position: { topPercent: 3, rightPercent: 3 },
delayMs: 120,
},
},
});The image loader also accepts initialAspectRatio; grid and ball can each be false. The default Loading caption beneath the ground line accepts custom text and color, or set ball.label: false to remove only that caption. Spinner position accepts one of leftPercent or rightPercent and one of topPercent or bottomPercent. Set loadingUi: false to remove all SDK presentation, or disable either image or smartComponents independently. This is a browser-only SDK option and is never sent to the HTTP graphics API.
const view = await caddie.mount(container, graphicRequest, components, {
loadingUi: false,
onLoadingStateChange(state) {
loadingElement.hidden = !state.isLoading;
},
});
const unsubscribe = view.subscribeLoadingState((state) => {
console.log(state.status, state.pending);
});
// Later:
unsubscribe();The mount callback covers work that begins before a view can be returned and remains attached to that view. After mount, view.loadingState exposes the current snapshot and subscribeLoadingState immediately supplies that snapshot before delivering later changes.
Cache hits and synchronous visibility, movement, reset, compatible style, removal, shape, and text changes do not create false loading transitions. Rejected promises and existing image-status events continue to report failures separately; loading describes activity, not success.
data-caddie-loading and aria-busy, and emits a bubbling caddie100:loadingstatechange event. Decorative loaders are hidden from accessibility APIs and never capture pointer or keyboard input. Disabling them does not disable any state surface.Architecture
The image and interaction stay separate.
Clean graphic
The requested WebP, PNG, or JPEG remains a normal downloadable artifact with no component overlays baked into its pixels.
Component layer
Smart Components receive only their protected display instructions: artifact-bound pixels, visible paths and arrowheads, final grid segments, visible Green measurement lines and labels, or a final RGBA layer such as the Green elevation or slope heatmap. Annotation primitives receive client-authored pixels. None exposes source measurement records, putting elevations, slopes, downhill bearings, the spatial sidecar, protected green polygon, or metric transform.