Miami University Explorer

Planted: 2022

Miami University Explorer is a web application build to explore buildings and courses at Miami University. I built this project from scratch with Remix, Tailwind, Prisma, and SQLite.

Stack
Remix.js
SQLite
Prisma
Docker, Fly.io

Stack decisions

I intended to use this project to explore Deno. My original plan was the following stack.

I started this project with exploring Deno, with an SQLite module and starting writing my own ORM before it became more complex and less interoperable than I wanted it to be. I enjoy the flexibility and experience of Prisma, but Deno support was not there. I had imagined the steps being the following:

Deno and SQLite would index the courses and buildings. Hugo would quickly build every page I wanted upfront. Tufte.css would handle all styling through semantic HTML. And Autocomplete.js would enable searching for courses with a text input.

But, as it turns out, Hugo cannot build pages from a data source and Prisma had yet to support Deno.

I spun out a few of the Types and functions I had written into a small Deno script, a Miami University Enrollment Checker that is available on Github .

I knew I wanted to use JSX to template, Tailwind to style, and Prisma for the ORM. I choose to learn more about Remix, “focused on web standards and modern web app UX”.

Lessons

I explored the Miami APIs and created all the API functions in TypeScript with Deno. This exploration gave a great deal of learnings as Deno is webby—it implements standard web APIs, so, when you get better at Deno, you get better at the web. And I learned about:

Transport Layer Security

Trying to fetch the academic terms endpoint in Deno threw an HandshakeFailure error. I found out, Deno does not support weak ciphers. And this server is using an old insecure TLS version that Deno refuses to accept.

I don’t know anything about TLS handshakes or ciphers. But running

curl -v https://ws.miamioh.edu/api/academic/banner/v2/academicTerms/current
gave this message

	
        // SSL connection using TLSv1.2 / AES256-SHA256
        // ALPN, server did not agree to a protocol
    

I came across SSL Labs and ran a test for the server

The server used an old insecure TLS version that Deno refuses to accept. So fetching had to be done over insecure HTTP.

Stream API

Streaming seemed like an optimal solution to load large data in chunks as it comes in. I didn’t know where to start to learn about how to do this, so I started digging into the Fetch whatwg spec and crawling for solutions before coming across a series of stream experiments by Dean Hume that helped tremendously in implementing a streaming solution that I ultimately did not use.

Transfer-Encoding HTTP Headers

I learned about JSON streaming through newline-delimiters. When the Miami API would get over ~5Kb, it would stop sending Content-Length headers and instead send `Transfer-Encoding: chunked` alongside newline-delimited JSON.

The Transfer-Encoding headers are:

The “chunked” directive:

Data is sent in a series of chunks. The Content-Length header is omitted in this case and at the beginning of each chunk you need to add the length of the current chunk in hexadecimal format, followed by '\r\n' and then the chunk itself, followed by another '\r\n'. The terminating chunk is a regular chunk, with the exception that its length is zero. It is followed by the trailer, which consists of a (possibly empty) sequence of header fields. (MDN)