Ivy League Graduate Tutors
Full-Stack — Company Website
Full-Stack — Company Website
Ivy League Graduate Tutors https://ivyleaguegraduatetutors.com/ open_in_new is a small tutoring company based in the town where I grew up. They offer a variety of support services, from your typical subject tutoring to admissions preparation and career consulting.
I've been working with Ivy League Graduate Tutors since 2020 when I started doing web development somewhat professionally. They hired me initially to redesign their company website, which was pretty text-heavy at the time. This was actually my first time doing any serious web development, so it involved a lot of learning on the fly.
In retrospect, I think that the design and quality of the first site I built for them left a lot to be desired. The starting point I was given for the project was a partially configured Wordpress site that someone else had been working on before me. My lack of experience with Wordpress and web development as a whole naturally led me into a variety of issues that I lacked the knowledge to confidently solve. Consequently, I ended up taping over a lot of bugs with hacky CSS that had a tendency to break over time.
This screenshot should give you an idea of what I mean:
I'm obviously not the most satisfied now with the work I did then, but at the time it was the best I could figure out with the time I had. Since finishing that project, though, I've learned a lot about web development. At least, I've improved enough that Ivy League Graduate Tutors is still interested in working with me!
The project that I've been working on more recently is actually another site redesign. With all of the knowledge I've acquired and lessons I've learned since creating the last site, I'm working on a completely new design.
The new site is available at
ivyleaguegraduatetutors.com https://ivyleaguegraduatetutors.com/ open_in_new ,
or you can check it out in the preview below:
Just like any project, this site redesign comes with a few mission-critical goals. I spent a lot of time working these into my design process, and they have yielded some pretty great results.
Search Engine Optimization — Ivy League Graduate Tutors has naturally always considered SEO an important metric for establishing their presence online. When creating the last site, it wasn't something that I knew enough about to design for consciously.
Visual Efficacy — As I've already expressed, the last site design wasn't the greatest. Consequently, developing an appealing and effective design that promotes the brand identity of Ivy League Graduate Tutors has been an integral part of my process throughout this project.
Accessibility and Usability — Designing the website such that it is accessible to anyone who needs it is vital to expanding reach. Furthermore, developing a suite of layouts and components that provide genuine utility to users is necessary to keep them engaged.
Technical Extensibility — One of the biggest problems with the last site I developed for Ivy League Graduate Tutors was its maintainability. The workarounds and custom styles I had implemented had a tendency to break whenever Wordpress updated. On top of that, it was difficult to add new content without repeating my previous work constantly. Efficiency and reusability have accordingly been important factors while designing the new site's systems.
The table below summarizes the various tools I've used while working
on this project. It's not necessarily exhaustive, but it gives a good enough
overview of the most important tools that helped shape major architectural decisions.
Initially, Next.js with TypeScript was my obvious choice for building all of the user-facing elements of the site. At the time, it was the most familiar and effective framework that I was aware of.
I've never been a fan of dynamic typing, so TypeScript felt like a natural choice that brought my prior experiences with React a little bit closer to static typing.
I wanted to mention Zod here because I think it's a really useful addition to any node project where schema validation is a concern. In this instance, I built a series of generic web components with Next and designed a Zod schema to represent pages using them. As of writing this, around 27 pages on the site are generated from toml files at build time.
Here's a snippet from the SAT exam page to show you what I mean:
title = "SAT"
subtitle = "Learn about the SAT exam."
[sections.about]
title = "About the SAT"
[sections.about.sections.structure]
title = "Structure"
content = [
...
]
Page content is effectively decoupled from the direct HTML structure, so I can
freely modify Next components, even replacing them with new ones, without needing
to go through and update every. single. page.
And since I used Zod, I didn't even have to write my own parser!
On the server side of things I went for Spring. I love Kotlin, especially as a cross-compatible alternative to Java, and Spring makes a lot of API development a lot easier. So far, the combination has been a dream.
A big part of why I chose Spring has to do with my senior capstone project. For that project, my team and I elected to use Express.js to write our API. I'm not a fan of JavaScript at the best of times, but in API code I really dislike it. Early on in that project, I watched a colleague spend hours writing a ton of validation code to handle extracting relevant data from API requests. There's nothing wrong with that code, but it just felt unnecessary. Especially when alternatives like Spring handle it all for you.
The samples below shows a basic Spring API endpoint and accompanying data class:
@PostMapping
fun createMail(@RequestBody email: Email): ResponseEntity<TaskData>;
{
logger.info("Received email request")
val uuid = rateLimiter.attemptExecute<Email, UUID>;(postmanService::sendDispatched, email)
?: return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS).build()
logger.info("Email request queued with id '$uuid'")
return ResponseEntity.status(HttpStatus.ACCEPTED).body(TaskData(uuid))
}
data class Email(
val recipients: Array<String>;,
val subject: String,
val contentType: String,
val content: String
)
And that's all there is to it. No custom validation logic required just to assert that the response body conforms to a specific schema. It just works.
The frontend is deployed on Vercel. It was simple to set up, and Next.js is part of Vercel's ecosystem anyway.
On the backend, things are a little bit different. One of the most significant pain points I have experienced working with Spring is the deployment. Unlike most JavaScript tools, Spring requires a Java runtime installed to get the server running. I spent a lot of time fiddling with Docker and a few different hosting options, but nothing really worked out as cleanly as I would have hoped. It's something I need to revisit in the future. For now, the backend is deployed on Render.
Coming soon!
Coming soon!