How to include static assets in an Elixir application
Published: 2022-05-11 11:20:19

## tl;dr

- Put your static assets in the `/priv` directory.
- Identify the atom for your app in `mix.exs`. In this example, we’ll use `:my_app`.
- Get the file path by using `Application.app_dir/2`.
- Read the file according to your project’s needs. One way is with `File.stream!/3`.

Example:

```elixir
def get_my_file_stream() do
  Application.app_dir(:my_app, "/priv/my_file.txt")
  |> File.stream!()
end
```

## Diving deeper

If the above info solved your problem, great! You can go ahead and close this page.

But if you want to learn more about this topic, keep reading.

### The legacy of OTP

The Elixir programming language is built on top of Erlang/OTP. If you don’t know about Erlang/OTP, check out [this page from the Erlang FAQ](https://www.erlang.org/faq/introduction.html).

Within Erlang/OTP applications, there is a standard directory structure, which looks like this:

```
─ ${application}
	├── doc
	│   ├── internal
	│   ├── examples
	│   └── src
	├── include
	├── priv
	├── src
	│   └── ${application}.app.src
	└── test
```

The proper directory for storing static assets in these applications is `/priv`, and Elixir inherits this structure.

If you’d like to see more details on Erlang/OTP applications, [check out this page in the OTP Design Principles User’s Guide](https://www.erlang.org/doc/design_principles/applications.html#directory-structure-guidelines-for-a-development-environment).

### Leveraging the Erlang :code module

Although we used `Application.app_dir` above, that’s not the only way to get the file path.

Another approach would be to use the Erlang `:code` module, which you can call directly from your Elixir code (docs [here](https://www.erlang.org/doc/man/code.html)).

The `:code` module has a function called `priv_dir/1` which will return the path to the priv directory for the given application (docs [here](https://www.erlang.org/doc/man/code.html#priv_dir-1)). Then, you can get the complete path for your file using `Path.join/2`.

```elixir
def get_my_file_stream() do
  :code.prive_dir(:my_app)
  |> Path.join("my_file.txt")
  |> File.stream!()
end
```

## More content

If you liked this, you might also like some of my other posts. If you want to be notified of my new posts, [follow me on Dev](https://dev.to/brewinstallbuzzwords) or subscribe to my [brief monthly newsletter](https://mailchi.mp/89dc077154c7/brewinstallbuzzwords).

* [Reading the Elixir source code to learn how if blocks work](https://www.brewinstallbuzzwords.com/posts/elixir-if-block-source-code/)
* [I published my first Elixir package to hex!](https://www.brewinstallbuzzwords.com/posts/my-first-hex-package/)
* [What's the best questions you've been asked in a job interview?](https://dev.to/brewinstallbuzzwords/whats-the-best-question-youve-been-asked-in-a-job-interview-4a1j)
* [What was the first program you wrote?](https://dev.to/brewinstallbuzzwords/what-was-the-first-program-you-wrote-1gjp)
* [The weird quirk of JavaScript arrays (that you should never use)](https://www.brewinstallbuzzwords.com/posts/js-arrays-are-objects/)
* [Does Elixir have for loops?](https://www.brewinstallbuzzwords.com/posts/does-elixir-have-for-loops/)
* [Learn Elixir with me!](https://www.brewinstallbuzzwords.com/posts/learn-elixir-with-me/)
* [Project Tours: Bread Ratio Calculator](https://www.brewinstallbuzzwords.com/posts/bread-ratio-calculator/)
* [Changing Emoji Skin Tones Programmatically](https://www.brewinstallbuzzwords.com/posts/emoji-skin-tone/)
* [I made my first svg animation!](https://dev.to/brewinstallbuzzwords/i-made-my-first-svg-animation-29j3)
* [5 tips for publishing your first npm package](https://www.brewinstallbuzzwords.com/posts/tips-for-first-npm-package/)
* [4 Hugo Beginner Mistakes](https://www.brewinstallbuzzwords.com/posts/hugo-beginner-mistakes/)