reimplement as a flat(er) structure