Here's a solution which I think comes pretty close to what you want. It is not perfect, but it is hard for me, at least, to see the imperfections. Rather than nice empty nodes and sn edges, this uses pretty nice empty nodes because the empty nodes are not entirely nice, but they are pretty close.
This answer has two versions. The first is for version 2 of forest. The second is for version 1. If you use this code, please be sure to choose the appropriate version as neither will work with both versions of the package.
Forest v2
Rather than shape=coordinate, we set inner sep=0pt. We then alter the edge path so that child anchor=children. This avoids a tiny gap between the end of one edge and the start of the next. We also set parent anchor=children and calign=fixed edge angles for the tree but, crucially, we don't use child anchor=parent which causes things to go all over the place. (I'm not sure why, but it does.)
[For a south-growing tree, the parent anchor is north and the children anchor is south. But if you change the direction of growth, these will adapt accordingly. So these anchors are more flexible than hard-coding the direction as was required in version 1 of the package.]
This means that the lines are not quite straight when there is an empty node. But they are very nearly almost straight.
Here's the result:

Here's the complete example:
\documentclass[tikz,border=10pt,multi]{standalone} \usepackage{forest} \useforestlibrary{linguistics} \standaloneenv{forest} \forestset{ rectangle tree/.style={ draw tree stage/.style={ for root'={ draw tree box=0, draw tree, TeX={ \tikz{\node {\box0};} }, } } }, pretty nice empty nodes/.style={ for tree={ calign=fixed edge angles, parent anchor=children, delay={if content={}{ inner sep=0pt, edge path={\noexpand\path [\forestoption{edge}] (!u.parent anchor) -- (.children)\forestoption{edge label};} }{}} } } } \begin{document} \begin{forest} baseline, rectangle tree, where n children=0{ tier=word }{}, pretty nice empty nodes [VP$_1$ [read] [NP$_1$, [the] [ [note] [PP$_1$ [on the table, roof] ] ] ] ] \end{forest} \end{document}
Forest v1
Rather than shape=coordinate, we set inner sep=0pt. We then alter the edge path so that child anchor=south. This avoids a tiny gap between the end of one edge and the start of the next. We also set parent anchor=south and calign=fixed edge angles for the tree but, crucially, we don't use child anchor=north which causes things to go all over the place. (I'm not sure why, but it does.)
This means that the lines are not quite straight when there is an empty node. But they are very nearly almost straight.
Here's the result:

Here's the complete example:
\documentclass[tikz,border=10pt]{standalone} \usepackage{forest} \standaloneenv{forest} \forestset{ rectangle tree/.style={ draw tree stage/.style={ for root'={ draw tree box=0, draw tree, TeX={ \tikz{\node {\box0};} }, } } }, pretty nice empty nodes/.style={ for tree={ calign=fixed edge angles, parent anchor=south, delay={if content={}{ inner sep=0pt, edge path={\noexpand\path [\forestoption{edge}] (!u.parent anchor) -- (.south)\forestoption{edge label};} }{}} } } } \begin{document} \begin{forest} baseline, rectangle tree, where n children=0{ tier=word }{}, pretty nice empty nodes [VP$_1$ [read] [NP$_1$, [the] [ [note] [PP$_1$ [on the table, triangle] ] ] ] ] \end{forest} \end{document}
tier....may not always work. Although I would have thought it would here. Nonetheless, forest seems to get extremely confused no matter what I try. Your results are actually pretty good compared with what it seems to want to do in slightly variant cases!nice empty nodes/.style={ delay={where content={}{shape=coordinate}{}} }doesn't give such a nice final effect for the children of empty nodes, but at leasttierworks as expected.\begin{forest} baseline, sn edges, rectangle tree, where n children=0{tier=word}{}, [VP$_1$, nice empty nodes/.style={ delay={where content={} {shape=coordinate}{}} }, [read] [NP$_1$, [the] [ [note] [PP$_1$ [on the table, triangle]]]]] \end{forest}\documentclass{article} \usepackage{forest} \forestset{ sn edges/.style={for tree={parent anchor=south, child anchor=north}}, rectangle tree/.style={ draw tree stage/.style={ for root'={ draw tree box=0, draw tree, TeX={\tikz{\node {\box0};}}, }}}, nice empty nodes/.style={ delay={where content={}{shape=coordinate}{}} } } \begin{document} \begin{forest} baseline, sn edges, rectangle tree, where n children=0{tier=word}{}, [VP$_1$, nice empty nodes, [read] [NP$_1$, [the] [ [note] [PP$_1$ [on the table, triangle]]]]] \end{forest} \end{document}tieralignment when I was developingfixed (edge) anglescalign method: it is the latter process that destroys the tier alignment. I'll see what I can do to fix this: the problem is harder than it seems ...