refactored for cleaner API