Absolutely! Here’s a **minimal, complete Cowboy application** in Erlang that serves static files from `./public/` and provides a directory index (listing) when a directory is requested.

This example uses **Cowboy 2.x** and **rebar3** as the build tool.

---

## 1. **Project Structure**

```
cowboy_dirindex/
├── rebar.config
├── src/
│   ├── cowboy_dirindex_app.erl
│   ├── cowboy_dirindex_sup.erl
│   └── dir_index_handler.erl
└── public/
    ├── index.html
    └── (other files and folders)
```

---

## 2. **rebar.config**

```erlang
{erl_opts, [debug_info]}.

{deps, [
    {cowboy, {hex, cowboy, "2.10.0"}}
]}.

{shell, [
    {apps, [cowboy_dirindex]}
]}.
```

---

## 3. **Application Module (`src/cowboy_dirindex_app.erl`)**

```erlang
-module(cowboy_dirindex_app).
-behaviour(application).

-export([start/2, stop/1]).

start(_Type, _Args) ->
    cowboy_dirindex_sup:start_link().

stop(_State) ->
    ok.
```

---

## 4. **Supervisor (`src/cowboy_dirindex_sup.erl`)**

```erlang
-module(cowboy_dirindex_sup).
-behaviour(supervisor).

-export([start_link/0]).
-export([init/1]).

start_link() ->
    supervisor:start_link({local, ?MODULE}, ?MODULE, []).

init([]) ->
    Dispatch = cowboy_router:compile([
        {'_', [
            {"/[...]", dir_index_handler, []}
        ]}
    ]),
    {ok, _} = cowboy:start_clear(http_listener, [{port, 8080}],
        #{env => #{dispatch => Dispatch}}
    ),
    {ok, {{one_for_one, 10, 10}, []}}.
```

---

## 5. **Directory Index Handler (`src/dir_index_handler.erl`)**

```erlang
-module(dir_index_handler).
-behaviour(cowboy_handler).

-export([init/2]).

-define(PUBLIC_DIR, "public").

init(Req, _State) ->
    {PathInfo, Req2} = cowboy_req:binding('...', Req),
    RelPath = filename:join([?PUBLIC_DIR | PathInfo]),
    case file:read_file_info(RelPath) of
        {ok, #file_info{type = directory}} ->
            case file:list_dir(RelPath) of
                {ok, Files} ->
                    Body = render_dir_listing(PathInfo, Files),
                    {ok, cowboy_req:reply(200, #{<<"content-type">> => <<"text/html">>}, Body, Req2), state};
                {error, _} ->
                    {ok, cowboy_req:reply(403, #{}, <<"Forbidden">>, Req2), state}
            end;
        {ok, #file_info{type = regular}} ->
            case file:read_file(RelPath) of
                {ok, Bin} ->
                    Mime = guess_mime(RelPath),
                    {ok, cowboy_req:reply(200, #{<<"content-type">> => Mime}, Bin, Req2), state};
                {error, _} ->
                    {ok, cowboy_req:reply(404, #{}, <<"Not found">>, Req2), state}
            end;
        _ ->
            {ok, cowboy_req:reply(404, #{}, <<"Not found">>, Req2), state}
    end.

render_dir_listing(PathInfo, Files) ->
    Path = "/" ++ string:join([unicode:characters_to_list(P) || P <- PathInfo], "/"),
    Parent = case PathInfo of
        [] -> "";
        _ -> "<li><a href=\"../\">../</a></li>"
    end,
    FileLinks = [io_lib:format("<li><a href=\"~s/\">~s/</a></li>", [F, F]) || F <- Files, is_dir(PathInfo, F)] ++
                [io_lib:format("<li><a href=\"~s\">~s</a></li>", [F, F]) || F <- Files, not is_dir(PathInfo, F)],
    List = string:join([Parent | [lists:flatten(L) || L <- FileLinks]], "\n"),
    lists:flatten(io_lib:format(
        "<html><head><title>Index of ~s</title></head><body><h1>Index of ~s</h1><ul>~s</ul></body></html>",
        [Path, Path, List]
    )).

is_dir(PathInfo, F) ->
    FullPath = filename:join([?PUBLIC_DIR | PathInfo] ++ [F]),
    case file:read_file_info(FullPath) of
        {ok, #file_info{type = directory}} -> true;
        _ -> false
    end.

guess_mime(Filename) ->
    case filename:extension(Filename) of
        ".html" -> <<"text/html">>;
        ".htm"  -> <<"text/html">>;
        ".txt"  -> <<"text/plain">>;
        ".jpg"  -> <<"image/jpeg">>;
        ".jpeg" -> <<"image/jpeg">>;
        ".png"  -> <<"image/png">>;
        ".gif"  -> <<"image/gif">>;
        ".css"  -> <<"text/css">>;
        ".js"   -> <<"application/javascript">>;
        _       -> <<"application/octet-stream">>
    end.
```

---

## 6. **Create the `public/` Directory**

Add some files and subdirectories to `public/` for testing, e.g.:

```
public/
├── index.html
├── hello.txt
└── subdir/
    └── foo.txt
```

---

## 7. **Build and Run**

**Install rebar3** if you don’t have it:  
https://www.rebar3.org/docs/getting-started/

```sh
# Get dependencies and compile
rebar3 get-deps
rebar3 compile

# Run the application
rebar3 shell
```

---

## 8. **Test**

Open your browser to [http://localhost:8080/](http://localhost:8080/)

- You should see a directory listing of `public/`.
- Clicking on files will download or display them.
- Clicking on directories will show their contents.

---

## 9. **Notes**

- This is a **minimal** implementation. For production, you’d want to sanitize paths, handle errors more gracefully, and possibly use a MIME library.
- The handler does not support range requests, caching, or other advanced features.
- The code assumes all requests are relative to the `public/` directory.