Refactor: use state machine in template interface