Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
.
├── actions
├── stores
├── views
│   ├── Anonymous
│   │   ├── __tests__
│   │   ├── views
│   │   │   ├── Home
│   │   │   │   ├── __tests__
│   │   │   │   └── Handler.js
│   │   │   └── Login
│   │   │   ├── __tests__
│   │   │   └── Handler.js
│   │   └── Handler.js
│   └── SignedIn
│   ├── __tests__
│   ├── lib
│   │   └── components
│   │   ├── __tests__
│   │   └── Avatar.js
│   ├── views
│   │   ├── Courses
│   │   │   ├── __tests__
│   │   │   ├── views
│   │   │   │   ├── Assignments
│   │   │   │   │   ├── __tests__
│   │   │   │   │   └── Handler.js
│   │   │   │   ├── Default
│   │   │   │   │   ├── __tests__
│   │   │   │   │   └── Handler.js
│   │   │   │   ├── Grades
│   │   │   │   │   ├── __tests__
│   │   │   │   │   └── Handler.js
│   │   │   │   └── Users
│   │   │   │   ├── __tests__
│   │   │   │   └── Handler.js
│   │   │   └── Handler.js
│   │   └── Dashboard
│   │   ├── __tests__
│   │   ├── components
│   │   │   ├── __tests__
│   │   │   ├── Stream.js
│   │   │   ├── StreamItem.js
│   │   │   ├── TodoItem.js
│   │   │   └── TodoList.js
│   │   └── Handler.js
│   └── Handler.js
└── main.js
@ryanflorence

This comment has been minimized.

Copy link
Owner Author

@ryanflorence ryanflorence commented Jan 12, 2015

Traditionally an app has several root folders that files get organized into. Folders like tests and components get enormous and terrifying, they also don't make it clear which components are reused, and which are only used in one view.

This new structure in the gist turns the your app into, quite literally, a bunch of mini apps, each with their own set of "root" folders like tests, components, views, stores, actions, etc.

If a module is shared among child views, it moves into the parent's lib folder. It might make its way all the way to the root lib folder.

Its just a big recursive structure because that's what an app is. Let's embrace it in our file system.

  • Teams can own a folder
  • CI knows to only run tests for the folder(s) that code changed in
  • Build scripts can code split easily

Etc.

@kentcdodds

This comment has been minimized.

Copy link

@kentcdodds kentcdodds commented Jan 12, 2015

My folder structure is similar to this and I totally agree with the philosophy. One difference I have is instead of a __tests__ folder, I put the test file next to what it's testing (like TodoList.test.js). Totally love the idea of mini-standalone apps inside of a bigger app. I feel like it allows you to be more flexible.

@phaedryx

This comment has been minimized.

Copy link

@phaedryx phaedryx commented Jan 12, 2015

Curious what all of these "Handler.js" files look like.

@joelhooks

This comment has been minimized.

Copy link

@joelhooks joelhooks commented Jan 12, 2015

+1 to @kentcdodds's "tests next to unit being tested". This encourages looking at tests and makes them harder to ignore. Also easily filtered at build-time.

@ryanflorence

This comment has been minimized.

Copy link
Owner Author

@ryanflorence ryanflorence commented Jan 12, 2015

@phaedryx they're React Router RouteHandlers. Its a react component, but it represents the "entry" point into the app at that level.

@nb

This comment has been minimized.

Copy link

@nb nb commented Jan 12, 2015

Cool, I love the recursive structure. Few things I am curious about:

  • How closely does the directory structure match your URL structure?
  • Is Default a semi-special name meaning the index page, or in this case it’s a domain-specific name we just don’t know about.
  • Do I understand correctly that components in views/Section/components/ should be used only in views/Section/Handler.js or in other components in the same directory?
  • Do handlers have UI-specific markup or usually just delegate to other components?
  • Where would be place components used by the whole system (imagine you needed Avatar.js in Anonymous/Home). Would it be in /lib/components/ (outside of /views), or in /views/lib/components (usually in views we don't have anything except dirs)?

Thanks!

@bsbeeks

This comment has been minimized.

Copy link

@bsbeeks bsbeeks commented Jan 12, 2015

+1 on @nb's last point. How would you structure global components that would be used in to both Anonymous and SignedIn? I'm guessing a root 'lib' directory with a 'components' directory within that?

@mzabriskie

This comment has been minimized.

Copy link

@mzabriskie mzabriskie commented Jan 13, 2015

@nb @bsbeeks shared stuff goes under /shared:

app
├── shared
│ ├── actions
│ ├── components
│ ├── lib
│ ├── stores
│ └── utils

@mrtnbroder

This comment has been minimized.

Copy link

@mrtnbroder mrtnbroder commented Jan 14, 2015

Nice structure, I really like it!

What I don't like is that you call every component Handler.js that kinda makes file search a pain. That's why I give every component a proper name. Take a look at my fork if you like.

I also added an assets folder, where I would put static stuff like images, css and so on.

@irvinebroque

This comment has been minimized.

Copy link

@irvinebroque irvinebroque commented Jan 14, 2015

This is rad.

I've also been splitting up views and components that render differently based on device type into separate entry points:

    ├── views
    │   ├── Navigation
    │   │   ├── __tests__
    │   │   ├── components
    │   │   │   ├── mobile.js
    │   │   │   ├── desktop.js
    │   │   │   │   ├── __tests__
    │   │   └── Handler.js

This makes it much easier to generate separate bundles for desktop vs mobile, and a lot more clarity within views (fewer ternary and if else statements based on environment -- just put them in Handler.js). Handler ends up behaving more like a controller -- it fetches data, checks permissions, etc., while the components handle the UI rendering.

I've found this really helps when views start growing past a few hundred lines of code, which happens fast when you write css in js.

@mrtnbroder

This comment has been minimized.

Copy link

@mrtnbroder mrtnbroder commented Jan 14, 2015

Why don't you put the styles in a seperate file then @irvinebroque?
Also it's bad practice to separate desktop and mobile stuff. Better find a responsive solution.

No hating here, just a friendly tipp :)

@lesterzone

This comment has been minimized.

Copy link

@lesterzone lesterzone commented Feb 12, 2015

What about structure by feature, LIFT principle:

.
├── app.js
├── categories
│   ├── categoryActions.js
│   ├── categoryStore.js
│   ├── categoryUtils.js
│   └── components
│       ├── form.js
│       └── list.js
├── core
│   └── dispatcher.js
├── router.js
├── routes.js

No more than 3 levels

@srph

This comment has been minimized.

Copy link

@srph srph commented Apr 13, 2015

├── app
  ├── lib
  ├── components
  ├── handlers
    ├── home/
      ├── components/
        ├── ...
      ├── HomeView.jsx
      ├── styles.less
    ├── about
    ├── login
    ├── logout
  ├── index.js
  ├── routes.js
├── core
  ├── actions
  ├── stores
  ├── utils
  ├── config.js
├── dashboard
├── public
├── style

the app directory is basically similar to the dashboard directory. We're currently implementing this structure (having the app and dashboard in the same repo), and them have separate builds for them 😄

@samuelazran

This comment has been minimized.

Copy link

@samuelazran samuelazran commented Aug 26, 2015

+1 to @kentcdodds

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment