Composition of nested components

I’m currently wrapping my head around proper ways to structure my LiveView application in a reusable fashion. I have a strong React background and I’m used to react-router. I have an application that looks like this:

My structure so far (in terms of routes):

  • ‘projects/:id’ with :show action → ‘About’
  • 'projects/:id/edit with :edit action → ‘Settings’

I’ve basically used mix phx.gen.live ... to get that setup, so it’s one LiveView for these two actions.
Of course, I could implement the missing routes like this:

  • ‘projects/:id/posts’ with :show_posts action → ‘Posts’
  • ‘projects/:id/files’ with :show_files action → ‘Files’

By doing this I would keep it all in one LiveView, hence one template. I wouldn’t need to think about reusing/extracting common parts like the subpage navigation (light-grey box). But as soon as I were to introduce edit actions, e.g. ‘projects/:id/posts/:post_id/edit’ with :show_posts the LiveView would quickly get too big.

In React, with react-router I would do something like this (of course this is mock code):

const Router = (
    <>
        <Header />
        <Route path="/projects/:id" component={Project}></Route>
    </>
)

const Project = (
    <div>
        <LightGreyBox />
        <Route path='/projects/:id/posts' component={Posts}></Route>
        <Route path='/projects/:id/files' component={Files}></Route>
    </div>
)

const Posts = (
    <div>
        <PostsList/>
        <Route path='/projects/:id/posts/:postId/edit' component={PostEditModal}></Route>
    </div>
)

So basically it’s a nesting of routes in routed components. My first intuition is to now extract the light grey box into a LiveComponent. I would create a dedicated LiveView for ‘About’, ‘Posts’, ‘Files’, ‘Settings’ so that one “resource” (and its actions) are scoped to one LiveView. Then I would include the extracted LiveComponent in every of the new LiveViews. But for some reason, it doesn’t really feel DRY to me. Maybe it’s because of my React background.

I appreciate any tips and discussion regarding my problem :slight_smile: