Docs / Language Manual / ProjectStructure

Project Structure

These are the existing, non-codified community practices that are currently propagated through informal agreement. We might remove some of them at one point, and enforce some others. Right now, they're just recommendations for ease of newcomers.

File Casing

Capitalized file names (aka first letter upper-cased).

Justification: Module names can only be capitalized. Newcomers often ask how a file maps to a module, and why draw.res maps to the module Draw, and sometimes try to refer to a module through uncapitalized identifiers. Using Draw.res makes this mapping more straightforward. It also helps certain file names that'd be awkward in uncapitalized form: uRI.res.

Ignore .merlin File

This is generated by the build system and you should not have to manually edit it. Don't check it into the repo.

Justification: .merlin is for editor tooling. The file contains absolute paths, which are also not cross-platform (e.g. Windows paths are different).


Try not to have too many nested folders. Keep your project flat, and have fewer files (reminder: you can use nested modules).

Justification: The file system is a tree, but your code's dependencies are a graph. Because of that, any file & folder organization is usually imperfect. While it's still valuable to group related files together in a folder, the time wasted debating & getting decision paralysis over these far outweight their benefits. We'll always recommend you to Get Work Done instead of debating about these issues.

Third-party Dependencies

Keep them to a minimum.

Justification: A compiled, statically typed language cannot model its dependencies easily by muddling along like in a dynamic language, especially when we're still piggy-backing on NPM/Yarn (to reduce learning overhead in the medium-term). Keeping dependencies simple & lean helps reduce possibility of conflicts (e.g. two diamond dependencies, or clashing interfaces).


Have them. Spend more effort making them great (examples, pitfalls) and professional rather than just fancy-looking. Do use examples, and avoid using names such as foo and bar. There's always more concrete names (it's an example, no need to be abstract/generalized just yet. The API docs will do this plentily). For blog posts, don't repeat the docs themselves, describe the transition from old to new, and why (e.g. "it was a component, now it's a function, because ...").

Justification: It's hard for newcomers to distinguish between a simple/decent library and one that's fancy-looking. For the sake of the community, don't try too hard to one-up each other's libraries. Do spread the words, but use your judgement too.

PPX & Other Meta-tools

Keep them to a minimum. PPX, unless used in renown cases (printer, accessors and serializer/deserializer generation), can cause big learning churn for newcomers; on top of the syntax, semantics, types, build tool & FFI that they already have to learn, learning per-library custom transformations of the code is an extra step. More invasive macros makes the code itself less semantically meaningful too, since the essence would be hiding somewhere else.


Don't abuse overly fancy features. Do leave some breathing room for future APIs but don't over-architect things.

Justification: Simple code helps newcomers understand and potentially contribute to your code. Contributing is the best way for them to learn. The extra help you receive might also surpass the gain of using a slightly more clever language trick. But do try new language tricks in some of more casual projects! You might discover new ways of architecting code.


If it's a wrapper for a JS library, don't publish the JS artifacts. If it's a legit library, publish the artifacts in lib/js if you think JS consumers might use it. This is especially the case when you gradually convert a JS lib to ReScript while not breaking existing JS consumers.

Do put the keywords "rescript" in your package.json keywords field. This allows us to find the library much more easily for future purposes.

Justification: Be nice to JS consumers of your library. They're your future ReScripters.