client-side functionality