<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Penn Labs RSS Feed]]></title><description><![CDATA[Built for students, by students. Penn Labs is the student software development organization improving life at the University of Pennsylvania.]]></description><link>https://pennlabs.org</link><generator>GatsbyJS</generator><lastBuildDate>Fri, 27 Feb 2026 22:19:40 GMT</lastBuildDate><item><title><![CDATA[Penn Clubs: Shooting Yourself in the Foot with Kubernetes]]></title><description><![CDATA[Scaling is hard]]></description><link>https://pennlabs.org/blog/penn-clubs-shooting-yourself-in-the-foot-with-kubernetes</link><guid isPermaLink="false">https://pennlabs.orgblog/penn-clubs-shooting-yourself-in-the-foot-with-kubernetes</guid><pubDate>Thu, 18 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Penn Clubs: Shooting Yourself in the Foot with Kubernetes&lt;/h1&gt;
&lt;p&gt;Every semester, hundreds of Penn students apply to dozens of Wharton Council clubs through Penn Clubs, a product of Penn Labs. It might look like a simple web app — a few forms, a few clicks — but behind the scenes, Penn Clubs must withstand one of the most intense and predictable traffic surges on campus.&lt;/p&gt;
&lt;p&gt;Here’s how we prepare for it, what went wrong this fall, and the lessons we took away to make the platform even stronger.&lt;/p&gt;
&lt;h2&gt;The Problem: Midnight Traffic Surges&lt;/h2&gt;
&lt;p&gt;For Wharton Council–affiliated organizations, the application process has a unique constraint:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;There are 68 clubs on the Wharton Council, and&lt;/li&gt;
&lt;li&gt;All must set their application deadline for the same time — midnight.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This creates a perfect storm:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Roughly 1,300 students submit applications in the one-hour window before midnight&lt;/li&gt;
&lt;li&gt;That means about 10,000 application response objects are written to the database in that single hour&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s our most intense load of the semester — and if anything fails, students lose their shot at joining clubs. With the anticipation of peak load, we take the preparations necessary to ensure the platform is ready for the surge.&lt;/p&gt;
&lt;h2&gt;Our Solution: Preparing for the Surge&lt;/h2&gt;
&lt;p&gt;Over the years, we’ve made several improvements to ensure Penn Clubs stays fast and reliable during the crunch:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Backend Query Optimization&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;We profiled and optimized our Django queries, adding missing indexes, eliminating redundant writes, and restructuring slow filters to make application submissions lightning-fast.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Aggressive Read Caching&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many students refresh the site repeatedly to confirm their submissions. We cache common reads aggressively to prevent the database from getting overwhelmed, while still keeping data fresh.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Preemptive Horizontal Scaling on EKS&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Before the deadline, we scale up our EC2 instances running on EKS (Elastic Kubernetes Service) — using non-spot instances to avoid sudden preemption — so we can handle thousands of concurrent requests with headroom to spare.&lt;/p&gt;
&lt;p&gt;This has allowed us to handle years of midnight surges with zero downtime. But in Fall 2025, we made a critical (false positive) mistake.&lt;/p&gt;
&lt;h2&gt;The War Room&lt;/h2&gt;
&lt;p&gt;The Penn Labs War Room is a tradition every semester. The team gathers — usually in a GSR — dashboards up, snacks in hand, ready to make sure Penn Clubs survives its biggest night.&lt;/p&gt;
&lt;p&gt;This semester, that watch party turned into a real firefight.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;9:00 PM — War Room Goes Live&lt;/strong&gt;
As usual, the Clubs &amp;#x26; Platform team spins up monitoring dashboards and keeps an eye on alerts. This hour is usually calm — but not tonight.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;10:00 PM — Something Feels Off&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We have 800 database connections already — why?”
This was completely abnormal for 10 PM. CPU, memory, and disk I/O were perfectly healthy — no blocking queries, no I/O saturation — just a wall of open database connections.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;10:20 PM — First Attempts&lt;/strong&gt;
We debate scaling up the RDS instance, but that would require a restart, and the midnight deadline is too close. Setting up an RDS Proxy isn’t viable either — it would take too long. We hold steady, but keep digging.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;10:50 PM — The Plot Twist&lt;/strong&gt;
Someone scrolls back through historical metrics.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Wait — this started at 5:30 PM, exactly when we scaled up our deployments.”
The room goes quiet. This wasn’t user load. &lt;strong&gt;This was us&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;11:00 PM — The Puzzle Snaps Together&lt;/strong&gt;
Julian, Clubs lead, joins and adds the missing piece:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“We also increased the number of worker threads this semester.”
The realization hits:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;tripled deployments × more workers per deployment = triple the database connections.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;We hadn’t been attacked — &lt;strong&gt;we’d accidentally DDoS’d our own database&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;11:05 PM — The Fix&lt;/strong&gt;
We scale down our deployments. Instantly, the database connection graph drops like a rock. The War Room erupts in cheers. The database is healthy, the platform is stable, and we go into the busiest hour of the semester with confidence.&lt;/p&gt;
&lt;p&gt;By 12:00 AM, the deadline passes without a single outage. Another successful application season — and a hard-earned lesson for the team.&lt;/p&gt;
&lt;p&gt;We survived the application season with the smallest RDS instance in history, with just 8GB of RAM.&lt;/p&gt;
&lt;h2&gt;Key Takeaway: Scaling is Holistic&lt;/h2&gt;
&lt;p&gt;This experience taught us that:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Scaling horizontally isn’t just about adding more servers — you must scale your database alongside them, or you risk creating the bottleneck yourself.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Connection pooling, database capacity, and worker counts all need to be considered together. Otherwise, you can overwhelm your own infrastructure before the first user request even hits.&lt;/p&gt;
&lt;h2&gt;The Future: Message Queues for Even More Reliability&lt;/h2&gt;
&lt;p&gt;For a long time, I&apos;ve had some thoughts about the next chapter of Penn Clubs: adding message queues(like Amazon SQS, Kafka, or RabbitMQ) to the Club application pipeline to improve reliability and reduce EC2 costs.&lt;/p&gt;
&lt;p&gt;Instead of writing directly to the database during peak load, we could:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Enqueue submissions and immediately acknowledge them to users&lt;/li&gt;
&lt;li&gt;Process them asynchronously, smoothing out traffic spikes&lt;/li&gt;
&lt;li&gt;Scale background workers independently of the web layer&lt;/li&gt;
&lt;li&gt;Allow delayed database writes to spread out over time&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This will improve reliability, reduce EC2 costs, and give us better observability into throughput and retries. We&apos;re hoping this will help us avoid a similar situation in the future.&lt;/p&gt;
&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;Penn Clubs isn’t just a website — it’s a platform that has to perform perfectly during one of the most stressful hours of the semester. The Fall 2025 War Room reminded us why we watch so closely: scaling isn’t about “more” — it’s about scaling &quot;everything&quot; together.&lt;/p&gt;
&lt;p&gt;With continued improvements — smarter connection pooling, better autoscaling, and message queues — we’ll keep making Penn Clubs a platform students can count on, even at 11:59 PM on deadline night.&lt;/p&gt;
&lt;p&gt;As a final remark, I want to thank the Clubs &amp;#x26; Platform team for their hard work and dedication to making Penn Clubs a success. I&apos;m proud to be a part of this team and I&apos;m looking forward to seeing what we can accomplish together in the future!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[For Students, By Students: The Role of Penn Labs in the Penn Experience]]></title><description><![CDATA[Last week, I pitched Penn Labs to students at the annual SAC Fair, our informational sessions, and other recruiting events. Like other…]]></description><link>https://pennlabs.org/blog/for-students-by-students</link><guid isPermaLink="false">https://pennlabs.orgblog/for-students-by-students</guid><pubDate>Sun, 07 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last week, I pitched Penn Labs to students at the annual SAC Fair, our informational sessions, and other recruiting events. Like other student organizations, these events are crucial touchpoints for prospective members. Though, I noticed that my conversations often started with:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: &lt;em&gt;Are you interested in joining Penn Labs?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Random Freshman&lt;/strong&gt;: &lt;em&gt;What&apos;s that?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: &lt;em&gt;Have you used Penn Course Review, Penn Course Plan, Penn Mobile, Office Hours Queue, or Penn Clubs?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Random Freshman&lt;/strong&gt;: &lt;em&gt;Yes....&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: &lt;em&gt;Those are all Penn Labs products!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Random Freshman&lt;/strong&gt;: &lt;em&gt;WOAHHH!! THAT&apos;S REALLY COOL!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Me&lt;/strong&gt;: &lt;em&gt;[insert overrehearsed sales pitch here]&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It&apos;s at this point that I realized that Penn Labs is unique in that people learn about our work before they learn about our club. This is a realization that was two years in the making and underlies some key things that I&apos;ve learned about my time at Penn Labs.&lt;/p&gt;
&lt;h2&gt;1. Product direction is a function of the &lt;em&gt;user&lt;/em&gt; and their &lt;em&gt;experiences&lt;/em&gt;&lt;/h2&gt;
&lt;p&gt;I joined Penn Labs in Spring 2024 as a member of the iOS team. This gave me the opportunity to work on Penn Mobile. After onboarding and completing an introductory project, I remember struggling to find something to work on. My team leads at the time, Jordan and Anthony, looked at me (after my intro project crashed Penn Mobile and they had fixed it) and essentially said:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Anthony and Jordan&lt;/strong&gt;: &lt;em&gt;Don&apos;t worry about it, that&apos;s normal. Just find something that you don&apos;t like and make it better.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By giving me a lot of latitude in deciding what to work on, my lens of product direction shifted from that of a prospective software engineer to that of a user. Furthermore, this opened my eyes to the motive behind Penn Labs&apos; products at large: find something that people find difficult and make it easier.&lt;/p&gt;
&lt;p&gt;Product direction has always been a challenge for me. It&apos;s a tough call deciding what things to tackle first, what problems are worth solving, what ideas are worth acting upon. However, my time in Penn Labs has taught me that it&apos;s all about the user. Building cool products is fun, exciting, and impactful largely because there&apos;s someone on the other side whose life is made better by them.&lt;/p&gt;
&lt;p&gt;As an iOS developer, it feels right to quote Steve Jobs on this one:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&quot;You&apos;ve got to start with the customer experience and work backward to the technology.&quot;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;- Steve Jobs, WWDC 1997&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So how do we decide what to work on? Simply put, we put our Penn student caps back on and think about the challenges we face. For one, degree planning is consistently a challenge here at Penn. We&apos;re working on it (I promise). But it&apos;s those types of challenges that stand out as &lt;em&gt;unbelievable&lt;/em&gt; product ideas; the allure of solving a problem that just one student faces is all too common among our talented team members.&lt;/p&gt;
&lt;h2&gt;2. Writing code isn&apos;t the entire picture&lt;/h2&gt;
&lt;p&gt;After spending a year on the iOS team, I moved up to the role of iOS team lead. I was still developing Penn Mobile, but I was interacting with many more product teams at a much deeper level. It&apos;s here where I realized that these interactions are the not-so-apparent responsibility of a team lead. Simply put, interacting with product teams, students, and other stakeholders is just as much a part of the role as is writing the code, leading your team, and solving the problem.&lt;/p&gt;
&lt;p&gt;Penn Labs is so much more than a team of software engineers. We have members whose talents are in infrastructure management (which is largely software, but also operations/cost analysis), user interface design, social media marketing, and product management. To remain in one&apos;s bubble—that is, to focus only on the software—goes against everything we do well as an organization. There&apos;s a reason that our products are discovered before our club: the efforts needed to make that product effective, easy-to-use, and well-marketed took genuine talent that is largely the result of the interaction between these different teams (and the skills of those teams themselves). Penn Labs is a melting pot of perspectives, backgrounds, and experiences so far beyond, and including, the Penn sphere.&lt;/p&gt;
&lt;p&gt;Another overlooked part of the job is the relationships. We have worked tirelessly to maintain relationships with our various stakeholders: advisory boards, Penn administrators, Penn IT, and foremost: Penn students. While writing code is paramount to show potential value, being able to speak about impact and results to those who support your work is also fundamental to the work we do and the
effect we have on the Penn experience.&lt;/p&gt;
&lt;p&gt;Writing code is not the entire picture. In fact, it&apos;s naïve to look at our organization as a group of software engineers. The products we build are a result of inter-team conversations and debates, the cultivation of productive relationships with stakeholders, and genuine talent and care by the students who volunteer to make these products for the Penn community.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I&apos;m going into my stint as the co-director of Penn Labs for the next year. I&apos;m excited further this direction and mindset, and I&apos;m also excited to bring on new members who align with this. With that, our application is open on Penn Clubs (which is cool since it&apos;s our product). So if anything I wrote here resonates with you, &lt;a href=&quot;https://pennlabs.org/apply&quot;&gt;apply&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;My experience at Penn Labs has been enlightening. It&apos;s been a ton of fun learning from the talented members around me who are excited to show me how cool the work they&apos;re doing &lt;em&gt;actually&lt;/em&gt; is.&lt;/p&gt;
&lt;p&gt;As I said, we work hard to cultivate a relationship with Penn students and other stakeholders. If you have comments about our work or ideas, reach out to us at contact@pennlabs.org.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[False Promises and Related Rabbitholes]]></title><description><![CDATA[The 19th of September, 2022 might have been an innocuous Monday for most, but
over at Penn Clubs -- things were getting rocky. The last day…]]></description><link>https://pennlabs.org/blog/false-promises</link><guid isPermaLink="false">https://pennlabs.orgblog/false-promises</guid><pubDate>Thu, 12 Jan 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The 19th of September, 2022 might have been an innocuous Monday for most, but
over at Penn Clubs -- things were getting rocky. The last day of the
&lt;a href=&quot;https://pennclubs.com/apply&quot;&gt;Wharton Council Centralised Application&lt;/a&gt;, Penn Clubs went down
for around 10 minutes in the afternoon. We quickly pinpointed database
throttling as the cause, bumped up our instance class and things were golden
again -- no other telltale issues.&lt;/p&gt;
&lt;p&gt;Fairly normal, we thought. It&apos;s the last day of applications. Of course everyone was
getting their submissions in last minute. With fairly substantial historical load (~1500
unique applicants, ~5000 applications), we brushed it off as a &quot;random&quot; failure
of the database. Everything else was green too; the usual pod, CPU, memory, node
metrics looked &lt;em&gt;great&lt;/em&gt; so I was confident that nothing worse could happen.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/c4739ae76c5467048a36d2994adb3e7d/46115/wc_text.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 9.499999999999998%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAgElEQVQI1y3JPQrCMByG8Z5EHBLbzU2sgg1U9B4ewRP40RbSFjo7eaFKRj1HMfNj/sThxwPvmxT2g6lGNjdHfnWY2rGrHKtLrJB9HWzvjrKJlV/2opa+yJs3c3Mi2T/h8JhYDh5lPVnnSQPVxgrdRosg62PVf0u7L9pO6AFmxzM/QktmxvwEbp0AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Response&quot;
        title=&quot;Response&quot;
        src=&quot;/static/c4739ae76c5467048a36d2994adb3e7d/5a190/wc_text.png&quot;
        srcset=&quot;/static/c4739ae76c5467048a36d2994adb3e7d/772e8/wc_text.png 200w,
/static/c4739ae76c5467048a36d2994adb3e7d/e17e5/wc_text.png 400w,
/static/c4739ae76c5467048a36d2994adb3e7d/5a190/wc_text.png 800w,
/static/c4739ae76c5467048a36d2994adb3e7d/c1b63/wc_text.png 1200w,
/static/c4739ae76c5467048a36d2994adb3e7d/46115/wc_text.png 1290w&quot;
        sizes=&quot;(max-width: 800px) 100vw, 800px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class = image-caption&gt;
My affirmation to the Wharton Council representative.
&lt;/p&gt;
&lt;p&gt;Famous last words.&lt;/p&gt;
&lt;p&gt;I was sipping on some &lt;a href=&quot;https://house.suntory.com/toki-whisky&quot;&gt;whisky&lt;/a&gt; and watching TV with some friends at
around 9pm when I
received the unfortunate news that Penn Clubs was down, again. Looked like the
Targaryen family feuds had to wait! &lt;a href=&quot;https://xkcd.com/705/&quot;&gt;Uptime&lt;/a&gt; was
more pressing.&lt;/p&gt;
&lt;h1&gt;Problem&lt;/h1&gt;
&lt;p&gt;After about 30 minutes of staring at metrics dashboards, the platform team, outgoing co-director Campbell, and I eventually pinpointed that it was the database (and &lt;em&gt;only&lt;/em&gt; the database) again. Somehow we were at 99.9% CPU utilization, which effectively throttled read/write performance severely. We figured there was an excess of queries running which not only slowed query speeds to a crawl but also, strangely, left behind some long-running &quot;suspended&quot; queries that were busy-waiting on the database CPU.&lt;/p&gt;
&lt;p&gt;Busy-waiting is a computer science concept which involves a stalling process being scheduled by a system (OS, database, etc) -- resulting in using 100% of available CPU. The simplest example of a busy wait is as follows:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;c&quot;&gt;&lt;pre class=&quot;language-c&quot;&gt;&lt;code class=&quot;language-c&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token function&quot;&gt;printf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Loop forever\n&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In this case, the long running queries were frozen but the database didn&apos;t know
any better to terminate them, so they hogged the majority of the CPU. Our
immediate hotfix, kudos to Campbell, was to write a script that periodically killed all long-running queries (&gt;30s runtime).&lt;/p&gt;
&lt;p&gt;However, perhaps more importantly, it didn&apos;t quite make sense to us why we had
so many queries hitting the database, and even less so why some were magically
frozen. Our database instance class was not small and our load &lt;em&gt;should have&lt;/em&gt;
been ~O(1000) qps, perfectly reasonable given our infrastructure setup. And so we jumped
down the investigative rabbithole!&lt;/p&gt;
&lt;h1&gt;Profiling Penn Clubs&lt;/h1&gt;
&lt;p&gt;Penn Clubs is probably one of our more involved products in terms of database
design. We employ a variety of models to capture the nuances of user, clubs, fairs,
applications and their relations. Crucially, as we scale, this introduces a lot
of scope for complex queries, elaborate Python logic, and Django ORM inefficiencies
-- all of which could trickle down to various database problems.&lt;/p&gt;
&lt;h2&gt;Queries, Queries, and more Queries&lt;/h2&gt;
&lt;p&gt;To dig at the root of this problem, we started with looking at which
API endpoints took the longest to respond (thanks to Peyton). To do this, we used a piece of
software called &lt;a href=&quot;https://www.datadoghq.com/&quot;&gt;Datadog&lt;/a&gt;, which hooks
into all our products and collects important monitoring data.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/1fc8d4c3ec3cafccf30a8378d87eb7ce/ee3fb/slow_query.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 34.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAHCAYAAAAIy204AAAACXBIWXMAABYlAAAWJQFJUiTwAAABFElEQVQoz22RWY6DQAxEuf8pMwnQ+8KSSKw1LodE8zGWLLfo4rnsbmIqGMYJf2PbdvgQcbu3CDEh5YLOWOz7gf/iOI4rTzQ5ecT8htZhUMDz9dJqrMOyrggpo5dzLhWlVq1sYl3AOM1f8HkKcCxBgFUdOcl726soCoQ/Mli9NFCND1qN86pl01IHTPMT67ahiTWJm6yOKGw7I05H9DIivzEItwJgQytAJh1/gG1vtOmyrGhcEocXkKPx8g10qNKZoeMLkCBjvUK63uL289Azd83xuZ6mJCfCpA7o5OPw0fXfxyKQjqgxVxJIDSfpxASn2zjyWCNyHa+FD3rBfRAyS5U96x3XwodgsrEPSd1Sx1WwOR3+AjOAE4SzznkJAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Response&quot;
        title=&quot;Response&quot;
        src=&quot;/static/1fc8d4c3ec3cafccf30a8378d87eb7ce/5a190/slow_query.png&quot;
        srcset=&quot;/static/1fc8d4c3ec3cafccf30a8378d87eb7ce/772e8/slow_query.png 200w,
/static/1fc8d4c3ec3cafccf30a8378d87eb7ce/e17e5/slow_query.png 400w,
/static/1fc8d4c3ec3cafccf30a8378d87eb7ce/5a190/slow_query.png 800w,
/static/1fc8d4c3ec3cafccf30a8378d87eb7ce/ee3fb/slow_query.png 1144w&quot;
        sizes=&quot;(max-width: 800px) 100vw, 800px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Wow! Looks like &lt;code&gt;/api/clubs&lt;/code&gt; (the homepage) could be &lt;em&gt;really slow&lt;/em&gt;. This makes
sense, since the list of clubs we load on the homepage involved a lot of SQL joins, ordering,
and computing aggregations. Importantly, for someone to get to the application
page, they were likely visiting the homepage first, then going to individual
clubs&apos; homepages, and finally clicking the Apply button. In the process, we ran
this expensive and ugly query for &lt;code&gt; /api/clubs &lt;/code&gt;, as well as one for
&lt;code&gt; /api/clubs/&amp;#x3C;club_code&gt; &lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This clearly created a lot of redundancy: each user that wanted to apply to a club would
inadvertently trigger a set of expensive database operations that were
unnecessary - the list of clubs and their related fields are mostly static.
Queries to these pages, while optimised, were still large and operated on about ~100k DB objects across tables.&lt;/p&gt;
&lt;p&gt;To solve this, we introduced a cache layer to our core backend services. This
cached the database-computed queryset with a TTL of 1 hour. We invalidated
this cache on object creation or updates (as well as updates to important
related fields). During peak traffic, this was sure to minimize load on the database and maintain
the performance of our website. Reads from Redis are very fast (we averaged 4.2ms using the
Django cache client), so we expected our API to get faster too.&lt;/p&gt;
&lt;h2&gt;Optimisation, ft. the N+1 problem&lt;/h2&gt;
&lt;p&gt;Another pain point in our code was that we had some of our more complex query logic
written in Python (using for loops and Python objects). Python is
notoriously slow at CPU intensive tasks, but at the same time the query was not
expressable using the usual set of Django ORM functions. We had to insert some &lt;a href=&quot;https://github.com/pennlabs/penn-clubs/pull/482&quot;&gt;Raw SQL&lt;/a&gt;
to transfer the heavy lifting over to the database. While this is generally
frowned upon, it is useful in cases where the ORM fails to model the desired
query exactly. This improved query performance for the same set of objects by
around ~10x.&lt;/p&gt;
&lt;p&gt;We were also a victim of the infamous &lt;a href=&quot;https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping&quot;&gt;N+1
problem&lt;/a&gt;.
Many of our serializer calls also invoked related fields&apos; serializers which
slipped through our notice but added on extra queries. The presence of multiple
many-to-many relationships meant that fixing these queries (using Django&apos;s
&lt;code&gt; Prefetch and select_related &lt;/code&gt; led to a reduction in the number of
queries hitting the database (per lookup of affected objects) by a factor of ~100!&lt;/p&gt;
&lt;p&gt;A common theme with these two problems is that they are both rooted in the
pitfalls of the Django ORM. While the ORM is certainly convenient, readable, and
intuitive to use, it requires some degree of expertise to write performant
code with. It&apos;s certainly better than writing only SQL though. We&apos;re not a
data science club.&lt;/p&gt;
&lt;h2&gt;Caching redux&lt;/h2&gt;
&lt;p&gt;At this point, we&apos;ve implemented a fairly robust cache layer and also optimised
our database logic so our endpoints do at most 5-6 queries on the DB. However,
performance wasn&apos;t quite where we wanted it to be. For some reason, some of the
heavier endpoints still took &gt;3 seconds. Our database isn&apos;t that large, so this
was puzzling. Additionally, our stack (React + Django) was not chosen for &lt;a href=&quot;https://www.reddit.com/r/rustjerk/comments/sqy221/anything_built_in_rust_is_blazingly_fast_by/&quot;&gt;blazingly
fast&lt;/a&gt;
performance, but we were still slower than expected.&lt;/p&gt;
&lt;p&gt;Digging even further, the problem seemed to lie in the serializer. For
the application submission route (optimised earlier using raw SQL), the query by itself took
less than a second, but serializing took around ~7s. It is apparently well known
that model serializers are
&lt;a href=&quot;https://hakibenita.com/django-rest-framework-slow&quot;&gt;extremely&lt;/a&gt;
&lt;a href=&quot;https://stackoverflow.com/questions/29016879/modelserializer-is-extremely-slow-in-django-rest-framework&quot;&gt;slow&lt;/a&gt;.
Caching database results was certainly useful to reduce load on the database,
but did little to improve the actual performance of the site.&lt;/p&gt;
&lt;p&gt;To combat this, we adopted a different caching strategy. Instead of just caching
database results, we cached entire JSON responses, keyed on URL. Django&apos;s handy decorator
for this (&lt;code&gt; cache_page() &lt;/code&gt;) was limited to TTL-based
invalidation, so we wrote custom caching and invalidation logic by
overriding methods on our routes. At this point, almost all our heavy-hitting
read views were served through the cache, freeing the database for writes. And all of this only took up about ~20MB in
Redis!&lt;/p&gt;
&lt;h2&gt;Results&lt;/h2&gt;
&lt;p&gt;Penn Clubs had seen complaints in the past about slow performance, especially
during peak load - it&apos;s always been on our backlog to look at our code more
closely. With average homepage load times of about 4-5 seconds, our baseline was
undeniably poor.&lt;/p&gt;
&lt;p&gt;All of our work led to big boosts in performance numbers. Across the entire Penn
Clubs API, we saw a reduction in mean response time from 700ms to 200ms. On heavy
endpoints, we saw reductions by a factor of 10. We also saw fewer spikes in the
query times, reflecting a lack of throttling despite increased traffic.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/56a18d8f1343c7473fe2d8ca269b827e/71dc1/api_times.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 31%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAGCAYAAADDl76dAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAkklEQVQY042QiwrDIAxF/f8P3diKr2rro8YsyVgpw667cNA8uMYo6zxqY9FYJ2cIEVm991OQwa8caWsNFQ70y+wDnORVI1cAeDfBtRFP16g/5G1sWErdDf+FH55THQ6g2Iz3cSU47IrvN5/2+Cj5ckgF7ZIFExNO84o6JMkzjvITxZpqT6o9/Ip3IlJtyUwVuPcFgjnZcNtH+U8AAAAASUVORK5CYII=&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Response&quot;
        title=&quot;Response&quot;
        src=&quot;/static/56a18d8f1343c7473fe2d8ca269b827e/5a190/api_times.png&quot;
        srcset=&quot;/static/56a18d8f1343c7473fe2d8ca269b827e/772e8/api_times.png 200w,
/static/56a18d8f1343c7473fe2d8ca269b827e/e17e5/api_times.png 400w,
/static/56a18d8f1343c7473fe2d8ca269b827e/5a190/api_times.png 800w,
/static/56a18d8f1343c7473fe2d8ca269b827e/c1b63/api_times.png 1200w,
/static/56a18d8f1343c7473fe2d8ca269b827e/29007/api_times.png 1600w,
/static/56a18d8f1343c7473fe2d8ca269b827e/71dc1/api_times.png 2346w&quot;
        sizes=&quot;(max-width: 800px) 100vw, 800px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p class = image-caption&gt;
Average API response times. Changes implemented on ~Jan 6.
&lt;/p&gt;
&lt;p&gt;In addition to these metrics, we saw significantly reduced load on our database, with read and
write latency improving both about 2x on average alongside reduced variance. Our
projected Redis memory usage is also around 500 MB at peak, with an average of
20MB: basically nothing! Given that our average Redis memory usage prior to this was about 1 MB, it
is safe to say we were underutilising a hidden gem in our setup.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Perhaps the key takeaway from this blog post is not to (falsely) promise 100%
availability. If even AWS can only do 99.99%
at best, we shouldn&apos;t get ahead of ourselves. This is all to say that Penn Clubs
may very well go down again during application season. In that case, you will
either find me resigning or jumping down yet another rabbit-hole - I&apos;d rather not
find out which.&lt;/p&gt;
&lt;p&gt;On a more serious note, Penn Clubs has seen a lot of important design changes and
realizations, the primary of which is due to the fact that most of the content we serve is
static. The list of clubs, applications, and application submissions (after deadline) all change
very infrequently. Given that all our products use a shared database instance,
and our applications interact with the database a lot, capitalising on this fact
seems to have had the largest positive effect on our performance.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Path@Penn Downtime Post-Mortem]]></title><description><![CDATA[Over the past month, our infrastructure has had some intermittent issues, so we wanted to drop a quick postmortem describing what the…]]></description><link>https://pennlabs.org/blog/spot-postmortem</link><guid isPermaLink="false">https://pennlabs.orgblog/spot-postmortem</guid><pubDate>Mon, 02 May 2022 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Over the past month, our infrastructure has had some intermittent issues, so we wanted to drop a quick postmortem describing what the problem was and how we fixed it so we can solve these problems more quickly in the future!&lt;/p&gt;
&lt;h2&gt;Terminology&lt;/h2&gt;
&lt;p&gt;Before starting, we should define some terminology:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pod&lt;/strong&gt; - one instance of a running application (ex. Penn Courses Backend)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Node&lt;/strong&gt; - a physical machine that our pods run on&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cluster&lt;/strong&gt; - a collection of nodes that our pods run on&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes&lt;/strong&gt; - a piece of software built to move pods among nodes such that nodes don&apos;t get overwhelmed (use too much CPU/RAM)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;For our cluster, we use &lt;a href=&quot;https://aws.amazon.com/ec2/spot/&quot;&gt;AWS Spot Nodes&lt;/a&gt;. These are machines that may, at any time, be shut down by AWS for use in other places. In exchange for this, we pay a lower price for these nodes. Nodes going down is not a problem for us since we&apos;re running in Kubernetes which will automatically move our applications to our other nodes if one goes down.&lt;/p&gt;
&lt;p&gt;When a spot node goes down, all applications (I&apos;ll use the word pods interchangeably) are moved to the other nodes. A new node is then brought up and the pods (hopefully) rebalance between the available nodes.&lt;/p&gt;
&lt;p&gt;Additionally, a few weeks ago, we switched from many smaller nodes to 3 higher-resource nodes. This gave us some cost savings as fewer high-resource nodes are cheaper than many low-resource nodes.&lt;/p&gt;
&lt;h2&gt;Symptoms&lt;/h2&gt;
&lt;p&gt;Symptoms first appeared around the time of the Path@Penn launch.&lt;/p&gt;
&lt;p&gt;We started getting reports of applications failing with no text in the browser other than &lt;code class=&quot;language-text&quot;&gt;Service Unavailable&lt;/code&gt;. This allowed us to immediately know that this was an infrastructure-wide issue for a few reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If multiple products are failing in the same way, then there cannot be a single-application code change that caused this. It must be that some part of the underlying infrastructure is broken.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;Service Unavailable&lt;/code&gt; is an error that typically only our load balancer, &lt;a href=&quot;https://traefik.io/&quot;&gt;Traefik&lt;/a&gt; will throw. It is almost never sent by actual application code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Initial Debugging&lt;/h2&gt;
&lt;p&gt;Upon looking at the cluster with &lt;code class=&quot;language-text&quot;&gt;kubectl&lt;/code&gt;, we saw that many pods were stuck in the &lt;code class=&quot;language-text&quot;&gt;ContainerCreating&lt;/code&gt; state. This means that a pod has been assigned to a node, but for some reason, the node cannot start the pod up.&lt;/p&gt;
&lt;p&gt;To debug this further, we looked at Datadog, our monitoring system. Datadog showed between 1 and 2 nodes at 100% CPU usage with the third sitting almost idle at ~10% usage.&lt;/p&gt;
&lt;p&gt;At this point, the question becomes: &lt;strong&gt;If Kubernetes is balancing pods, why are some nodes at such higher resource usage than the others?&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;Deduction&lt;/h2&gt;
&lt;p&gt;After further investigation, it looks like the following was happening:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A spot node gets scheduled to terminate&lt;/li&gt;
&lt;li&gt;All its pods are drained to the other two nodes&lt;/li&gt;
&lt;li&gt;The remaining two nodes don&apos;t have enough available resources to host all our pods and spike to 100% CPU usage&lt;/li&gt;
&lt;li&gt;100% CPU usage renders the two nodes unusable, and they stop responding to both Kubernetes and Datadog.&lt;/li&gt;
&lt;li&gt;Even when the third node comes back online, pods cannot be rebalanced to it because the other two nodes are unreachable due to load.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The underlying cause of this issue is that while 3 nodes is enough for our cluster, 2 is not. When a spot node termination happens, we don&apos;t have enough resources to handle the load, and it creates a cascading failure throughout our infrastructure.&lt;/p&gt;
&lt;h2&gt;Solution&lt;/h2&gt;
&lt;p&gt;To solve this issue, we&apos;ve scaled our cluster up to 5 nodes. This should mean that even if we lose a node due to spot lifecycle, we&apos;ve got plenty of compute to handle things.&lt;/p&gt;
&lt;h2&gt;Why did this just happen now?&lt;/h2&gt;
&lt;p&gt;This is the main question we&apos;ve been asking ourselves. Intuitively, it seems like we should have run into these issues as soon as we switched to only using 3 nodes.&lt;/p&gt;
&lt;p&gt;However, these issues are not just a symptom of having 3 nodes. &lt;strong&gt;They&apos;re a symptom of having 3 nodes while under high load&lt;/strong&gt;. The Path@Penn launch was the first time we had high load on our products since moving to 3 nodes. Therefore, while this problem existed all along, we didn&apos;t notice it until our systems were under stress.&lt;/p&gt;
&lt;h2&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;To solve these issues more quickly in the future, we should have better alerting and monitoring around application failures. Specifically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Alerting when we have a high number of &lt;code class=&quot;language-text&quot;&gt;503 Service Unavailable&lt;/code&gt; responses. These almost always indicate an infrastructure-level error.&lt;/li&gt;
&lt;li&gt;Alerting when we have high node CPU usage. While pod CPU usage hasn&apos;t been great signal for us (pods occasionally spike), high node usage almost always indicates a problem.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Reach Out&lt;/h2&gt;
&lt;p&gt;If any of this looks like it&apos;s up your alley or you wanna learn more about our mission, be sure to email us at &lt;a href=&quot;mailto:contact@pennlabs.org&quot;&gt;contact@pennlabs.org&lt;/a&gt; or &lt;a href=&quot;https://pennlabs.org/apply&quot;&gt;apply to be a part of Labs&lt;/a&gt;! We&apos;ve got some fantastic teams working on interesting problems with a direct impact on campus.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Creating a Virtual Club Fair: Redesigning & Repurposing Penn Clubs]]></title><description><![CDATA[Team: Eric W. (team lead, developer), Davis H. (developer), Daniel T. (developer), Campbell P. (developer), Lucy X. (developer), Jong Min C…]]></description><link>https://pennlabs.org/blog/virtual-club-fair</link><guid isPermaLink="false">https://pennlabs.orgblog/virtual-club-fair</guid><pubDate>Fri, 25 Sep 2020 00:00:00 GMT</pubDate><content:encoded>&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Team:&lt;/strong&gt; Eric W. (team lead, developer), Davis H. (developer), Daniel T. (developer), Campbell P. (developer), Lucy X. (developer), Jong Min C. (developer), Lanting C. (developer), Ying X. (developer), Peyton W. (platform), Armaan T. (Penn Labs director, platform), Misty L. (business developer).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;My role:&lt;/strong&gt; Product management, UI Design, Frontend development.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tools used:&lt;/strong&gt; Sketch, HTML/CSS, Typescript.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The Problem&lt;/h2&gt;
&lt;p&gt;One year ago, I joined Penn Labs, student group on campus at the University of Pennsylvania that works on a handful of products that aims at improving student life for students. From a course review tool to a central mobile application, Penn Labs is an amazing group of designers, engineers, and business developers (all undergraduates!) committed to helping students. &lt;a href=&quot;https://www.thedp.com/article/2020/08/penn-clubs-virtual-event-activities-fair&quot;&gt;Last year, Penn Labs launched pennclubs.com&lt;/a&gt;, an online directory meant to help students peruse the hundreds of clubs our university offers in a more user-friendly way than their legacy system (which was, essentially, just a list of clubs) had. At the end of the 2019–2020 school year, we secured a partnership with Penn’s official Office of Student Affairs to move the official registry of student organizations onto our platform.&lt;/p&gt;
&lt;p&gt;The wake of COVID-19 has created lots of opportunity in the realm of online connectivity: over the summer, I have seen many peers of mine pursue products that aim at filling the gap left by face-to-face experiences. One problem in particular that sparked conversation that arose in mid-July was the annual club fair. Once an exciting event that could best be categorized as exciting chaos, the fair used to take place on Locust Walk, the central, half-mile walking street that could be thought of as the &lt;em&gt;Autobahn&lt;/em&gt; or the &lt;em&gt;Route 50&lt;/em&gt; of Penn. Attended by over 500 clubs and thousands of undergraduate students, it has always been an energetic, loud, and exciting day, full of new Quakers trying to find their homes—only to be completely stripped away from the Penn experience this fall.&lt;/p&gt;
&lt;p&gt;On August 11, &lt;a href=&quot;https://www.thedp.com/article/2020/08/penn-fall-2020-move-online-remote&quot;&gt;the University of Pennsylvania revoked their previous hybrid model in favor of a fully-online one&lt;/a&gt;, changing much of what makes the red-and-blue experience would be like, especially for first-year students who haven’t met their people yet, who haven’t found their communities. We were approached with the opportunity to make sure that they could.&lt;/p&gt;
&lt;h2&gt;Goals&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Provide a platform through which new students can browse university organizations.&lt;/li&gt;
&lt;li&gt;Find a way to replicate the on-campus fair process online for a synchronous experience, through a video chatting platform.&lt;/li&gt;
&lt;li&gt;Design an asynchronous way for students in different timezones to still interact with clubs in a relatively informal and centralized location.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;The Stakeholders &amp;#x26; Users&lt;/h2&gt;
&lt;p&gt;We understood the landscape of the stakeholders we would be dealing with, given our relations with the official offices of the university, including OSA, which is responsible for student life on campus, and the Student Activities Council (SAC), which typically manages the club fair, and handles over $1 million in funding for club each school year.&lt;/p&gt;
&lt;p&gt;We identified three key types of users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;New students&lt;/strong&gt;, typically freshmen or transfer students, as well as some sophomores who want to find new clubs to join. They may know varying amounts of information on certain clubs, and will want to browse clubs in the same manner that they would if we had a live fair, on campus. There are about 2.7k new students on a given year to Penn. It is important to note that 20% of Penn students are international, and live in a wide variety of timezones.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Club officers&lt;/strong&gt;, who want to market their organizations to prospective members. They want to provide details about their organization, hold information sessions, and find new members to recruit. There are approximately 600 clubs on campus, each with between 1–3 officers on average.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;University officials,&lt;/strong&gt; including representatives from OSA and SAC (who are actually also undergraduate students). They want to be able to manage which clubs can participate in the fair, and ensure clubs are abiding by university branding guidelines. We worked with three of these officials on a daily basis.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/3022/1*OtZ-hbb9sYHJTkObxWoE8w.png&quot;&gt;&lt;/p&gt;
&lt;p&gt;These different types of users would need to have different permissions to view the sections of pennclubs.com, as well as different action items that we would need to lay out.&lt;/p&gt;
&lt;h2&gt;Existing Tools&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/2880/1*CaJmNJ9gmgJY9uj1kX5_Kg.png&quot; alt=&quot;Penn Clubs, circa August 2019.&quot;&gt;&lt;em&gt;Penn Clubs, circa August 2019.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Penn Clubs, launched in the Fall of 2019, already had some pretty awesome features. There was a great filtering and search system, a recommendations algorithm that took a student’s school (Arts &amp;#x26; Sciences, Nursing, Wharton, or Engineering) and major into account in showing relevant clubs, and the ability to subscribe to a club’s email listserv for updates. Most of these features were in place to reach goal #1 pretty seamlessly.&lt;/p&gt;
&lt;p&gt;The biggest tool we wanted to take advantage of was the school wide access to &lt;strong&gt;premium Zoom accounts&lt;/strong&gt; (Eric had actually created a plan to build a video conferencing platform from scratch, but given our tight deadline and the existing access to the system, we figured it’d be wise to just use Zoom). Key features about Zoom include the ability to create &lt;a href=&quot;https://support.zoom.us/hc/en-us/articles/206476093-Enabling-breakout-rooms&quot;&gt;breakout rooms&lt;/a&gt; for one-on-one or small group interactions, as well as the ability to use a chat feature for students who may feel too shy to come off mute and ask questions.&lt;/p&gt;
&lt;p&gt;Further research revealed that we could also leverage the existing &lt;strong&gt;&lt;a href=&quot;https://marketplace.zoom.us/docs/api-reference/zoom-api&quot;&gt;Zoom API&lt;/a&gt;&lt;/strong&gt; to make scheduling meetings for the synchronous part of the fair easier for club officers. With settings hidden behind educational accounts, three different dates, and timezone confusion, we wanted to streamline the Zoom meeting creation process by automating this process.&lt;/p&gt;
&lt;h2&gt;The Asynchronous Problem&lt;/h2&gt;
&lt;p&gt;As previously noted, there are hundreds of Penn Students that live in timezones that are completely incompatible with American timezones. We wanted to ensure that aside from the scheduled Zoom meetings, there would be opportunity for students to interact with club owners in a less formal setting than sending an email with questions.&lt;/p&gt;
&lt;p&gt;Clubs already had the ability to input a handful of information, including a description, basic contact information, a section on “how to get involved”, and select pertinent tags.&lt;/p&gt;
&lt;p&gt;We toyed with the idea of having a chat box for each club, where users could interact with club officers — but also knew that this would depend on club officers being on the platform to answer live chats. Instead, we opted for a &lt;strong&gt;Q&amp;#x26;A feature&lt;/strong&gt;, taking some inspiration from Reddit’s AMA structure, where users can ask questions (anonymously or not) to club officers, to be answered for all users to benefit from.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/4004/1*0k3_UPEaApQ-Unou0ijniQ.png&quot; alt=&quot;Clubs can provide a variety of information, including a description, contact info, a section of how to get involved, and can also answer questions!&quot;&gt;&lt;em&gt;Clubs can provide a variety of information, including a description, contact info, a section of how to get involved, and can also answer questions!&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;Executing the Project&lt;/h2&gt;
&lt;p&gt;We assembled a team of Penn Labs designers, developers, and business developers who had a couple free weeks of their summers to transform Penn Clubs from a simple database into a fully-fledged product ready to handle events, a club fair, and administrative capabilities.&lt;/p&gt;
&lt;p&gt;Three weeks, dozens of &lt;a href=&quot;https://clubhouse.io/&quot;&gt;Clubhouse&lt;/a&gt; cards, &lt;a href=&quot;https://github.com/pennlabs/penn-clubs/&quot;&gt;hundreds of git commits&lt;/a&gt;, and thousands of emails later, we launched the new-and-improved version of Penn Clubs that included dozens of new features, large and small, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the ability to browse clubs through four different &lt;strong&gt;orderings&lt;/strong&gt; (alphabetical, random, bookmarked, featured — which rewards clubs for inputting more information for prospective students),&lt;/li&gt;
&lt;li&gt;a more mature &lt;strong&gt;event creation process&lt;/strong&gt;, that included Zoom integration and the ability to upload a cover photo,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;a live events page&lt;/strong&gt;, fetching and featuring all current events created by clubs, searchable, and filterable by club tags,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;automatic event creation&lt;/strong&gt; using the Zoom API,&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;a Q&amp;#x26;A section&lt;/strong&gt; featured on each club’s homepage,&lt;/li&gt;
&lt;li&gt;two &lt;strong&gt;user guides&lt;/strong&gt; for the fair (a version for students, and a version for club officers),&lt;/li&gt;
&lt;li&gt;an &lt;strong&gt;analytics&lt;/strong&gt; page for club officers to view pertinent statistics such as page views, bookmarks, subscriptions, and the breakdown of viewers on their pages,&lt;/li&gt;
&lt;li&gt;and &lt;strong&gt;administrative&lt;/strong&gt; &lt;strong&gt;tools&lt;/strong&gt; for University officials, including approving clubs for the fair, report generation, and more.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://cdn-images-1.medium.com/max/2848/1*50-zae33skLcpvi2sbhQkA.png&quot; alt=&quot;Screenshot of Penn Clubs’s live event page&quot;&gt;&lt;em&gt;Screenshot of Penn Clubs’s live event page&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;The Impact&lt;/h2&gt;
&lt;p&gt;Aside from a slight hiccup on our first day when our servers overloaded due to a much higher attendance rate than we anticipated, the club fair ran extremely smoothly. Here are some standout statistics during the September 1–3 period:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;642 registered clubs,&lt;/li&gt;
&lt;li&gt;128,367 page views,&lt;/li&gt;
&lt;li&gt;5,284 users in 84 countries,&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;and we are still, at the time of writing this in mid-September, averaging approximately 1,000 users per day. Pretty crazy stuff!&lt;/p&gt;
&lt;h2&gt;The Future&lt;/h2&gt;
&lt;p&gt;We have several goals we, as a team, are working towards to keep improving Penn Clubs as a platform — we recognize that this platform can continue to be a hub of information for students, well past the period of the club fair. We are continuing to partner with several other offices in the administration, and are excited to welcome a couple more designers, developers, and business developers later this week to continue to mature our product!&lt;/p&gt;
&lt;p&gt;Check out the other amazing work that Penn Labs is doing at &lt;a href=&quot;https://pennlabs.org/&quot;&gt;pennlabs.org&lt;/a&gt;!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Icarus: Taming the Kubernetes Beast]]></title><description><![CDATA[Recently, we've moved our infrastructure from Dokku to Kubernetes as a platform to host and run our web applications. As a student…]]></description><link>https://pennlabs.org/blog/building-icarus</link><guid isPermaLink="false">https://pennlabs.orgblog/building-icarus</guid><pubDate>Wed, 27 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Recently, we&apos;ve moved our infrastructure from &lt;a href=&quot;http://dokku.viewdocs.io/dokku/&quot;&gt;Dokku&lt;/a&gt; to &lt;a href=&quot;https://kubernetes.io/&quot;&gt;Kubernetes&lt;/a&gt; as a platform to host and run our web applications. As a student organization (or club) we have a high member turnover rate as new members come and old ones leave. As such, we have to carefully consider the organizational impacts of moving to a technology as complex as Kubernetes. This post should serve as a bit of insight into how we dealt with that challenge and built technology to solve it.&lt;/p&gt;
&lt;h2&gt;Background&lt;/h2&gt;
&lt;p&gt;Typically when organizations decide to adopt Kubernetes, their organizational structure takes one of two patterns (or a combination of both):&lt;/p&gt;
&lt;h3&gt;Pattern 1: Embedded SREs&lt;/h3&gt;
&lt;p&gt;In this pattern, each team has one or more Site Reliability Engineers embedded in each team. These SREs are responsible for managing the deployment infrastructure and general architecture for the product. Since this model gives teams Kubernetes experts right in the teams, these teams are responsible for managing their own Kubernetes manifests and general deployment strategy.&lt;/p&gt;
&lt;p&gt;This system works great for teams with complicated application architectures whose applications might require special features like persistent volumes, cross-datacenter availability, complex scheduling requirements, etc. Think teams running Cassandra clusters, Solr clusters, or database services. In this model, SREs on each team can fit the Kubernetes configs to each team&apos;s needs. The clear drawback, however, is that your number of SREs required scales linearly with your number of teams.&lt;/p&gt;
&lt;p&gt;Because of the (relative) simplicity of Penn Labs&apos; applications and only having 2-3 SREs to service 5 teams, we determined that this pattern was not an option.&lt;/p&gt;
&lt;h3&gt;Pattern 2: Platform Team&lt;/h3&gt;
&lt;p&gt;In this pattern, there is a single team (or organization) that is responsible for building a high-level platform that other teams can use to deploy their applications. Building a platform involves significant up-front engineering work and a strong team to build the automation and interfaces required in order to create a frictionless deployment experience.&lt;/p&gt;
&lt;p&gt;This approach typically works best for applications with simple architectures. If you can restrict your applications to have similar architectures, you can build a platform that takes advantage of those shared architectures, abstracting away the common configuration.&lt;/p&gt;
&lt;p&gt;In Penn Labs, all of our web applications follow similar architectures: a single frontend (usually React) and a monolithic backend (usually Django). Since we have a common, simple architecture and we don&apos;t have the personell to man every team with an SRE, we decided to go with the platform approach. This approach fit nicely into our organizational structure since we already have a platform team that manages our &lt;a href=&quot;https://github.com/pennlabs/platform&quot;&gt;authentication system&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Platform Abstractions&lt;/h2&gt;
&lt;p&gt;There are quite a few tools that fit together to make this system work (Hashicorp Vault, Grafana, etc.), but for the purposes of this post, I&apos;m going to focus solely on the tool that developers actually use: Icarus.&lt;/p&gt;
&lt;p&gt;Kubernetes configs are hard and complicated. Kubernetes aims to be able to support any containerized application architecture possible, so it exposes every knob you could possibly want to turn. In simple setups, this leads to nothing other than repetition and confusion. For example, below is the configuration required to simply deploy our website, our simplest product:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Source: icarus/templates/services.yaml&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1
&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Service
&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;testsite-serve&apos;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ClusterIP
  &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;testsite-serve&apos;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Source: icarus/templates/deployments.yaml&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; apps/v1
&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Deployment
&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;testsite-serve&apos;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; default
  &lt;span class=&quot;token key atrule&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;testsite-serve&apos;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;replicas&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;matchLabels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;testsite-serve&apos;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;labels&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;testsite-serve&apos;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;containers&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;worker&apos;&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pennlabs/website:latest&apos;&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;imagePullPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; IfNotPresent
          &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;containerPort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
          &lt;span class=&quot;token key atrule&quot;&gt;envFrom&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;secretRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; test&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;secret
&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Source: icarus/templates/ingresses.yaml&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; networking.k8s.io/v1beta1
&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Ingress
&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; testsite&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;serve
  &lt;span class=&quot;token key atrule&quot;&gt;namespace&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; default
&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pennlabs.org&apos;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;
            &lt;span class=&quot;token key atrule&quot;&gt;backend&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;serviceName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; testsite&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;serve
              &lt;span class=&quot;token key atrule&quot;&gt;servicePort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;tls&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pennlabs.org&apos;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;secretName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pennlabs&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;org&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tls
&lt;span class=&quot;token punctuation&quot;&gt;---&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# Source: icarus/templates/certificates.yaml&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager.io/v1alpha2
&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Certificate
&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pennlabs&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;org
  &lt;span class=&quot;token key atrule&quot;&gt;annotations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;&apos;helm.sh/resource-policy&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; keep
&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;secretName&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pennlabs&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;org&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;tls
  &lt;span class=&quot;token key atrule&quot;&gt;dnsNames&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;pennlabs.org&apos;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;*.pennlabs.org&apos;&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;issuerRef&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; wildcard&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;letsencrypt&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;prod
    &lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ClusterIssuer
    &lt;span class=&quot;token key atrule&quot;&gt;group&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cert&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;manager.io&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;As mentioned earlier, in our applications we can make the following assumptions to make our lives easier:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;That application, if exposed to the world, will speak HTTP and want to be secured with HTTPS&lt;/li&gt;
&lt;li&gt;That application will use secrets synced into Kubernetes by our &lt;a href=&quot;https://www.vaultproject.io/&quot;&gt;Vault&lt;/a&gt; secret sync job&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With just these two assumptions, we can radically simplify our required configuration to the following for this example:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;deploy_version&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; 0.1.15

&lt;span class=&quot;token key atrule&quot;&gt;applications&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; serve
    &lt;span class=&quot;token key atrule&quot;&gt;image&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pennlabs/website
    &lt;span class=&quot;token key atrule&quot;&gt;secret&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; test&lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt;secret
    &lt;span class=&quot;token key atrule&quot;&gt;ingress&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;hosts&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;host&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; pennlabs.org
          &lt;span class=&quot;token key atrule&quot;&gt;paths&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&apos;/&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Let&apos;s dive into how this is possible.&lt;/p&gt;
&lt;h3&gt;Helm&lt;/h3&gt;
&lt;p&gt;At the root of the transformation from Icarus file to full Kubernetes manifest is a tool called Helm. Helm describes itself as a &quot;package manager for Kubernetes&quot;, but for the purposes of this article, think of it as a templating tool that happens to be good at deploying to Kubernetes.&lt;/p&gt;
&lt;p&gt;Helm operates off the &lt;a href=&quot;https://golang.org/pkg/text/template/&quot;&gt;Go template package&lt;/a&gt;. This package, much like Python&apos;s Jinja or Ruby&apos;s ERB, lets you define a template file, specifying where to put information the user provides. Take the example of our &lt;a href=&quot;https://github.com/pennlabs/icarus/blob/master/templates/services.yaml&quot;&gt;service template&lt;/a&gt;. This template defines a basic service with parameters:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1
&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Service
&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; $app_id &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; quote &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; .svc_type &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; .port &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; .port &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; $app_id &lt;span class=&quot;token punctuation&quot;&gt;|&lt;/span&gt; quote &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Helm lets you define default values, so in Icarus, we set &lt;code class=&quot;language-text&quot;&gt;.svc_type&lt;/code&gt; to be &lt;code class=&quot;language-text&quot;&gt;ClusterIP&lt;/code&gt; by default and &lt;code class=&quot;language-text&quot;&gt;.port&lt;/code&gt; to be 80 by default. We also set &lt;code class=&quot;language-text&quot;&gt;$app_id&lt;/code&gt; to be &lt;code class=&quot;language-text&quot;&gt;&amp;lt;repository_name&amp;gt;-&amp;lt;application_name&amp;gt;&lt;/code&gt;. Applying these rules, we get the resulting configuration that we see above:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Source: icarus/templates/services.yaml&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;apiVersion&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; v1
&lt;span class=&quot;token key atrule&quot;&gt;kind&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; Service
&lt;span class=&quot;token key atrule&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;testsite-serve&apos;&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;spec&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; ClusterIP
  &lt;span class=&quot;token key atrule&quot;&gt;ports&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;port&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;targetPort&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;
  &lt;span class=&quot;token key atrule&quot;&gt;selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&apos;testsite-serve&apos;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Icarus works simply by applying substitutions like this to create the final Kubernetes manifests, and then we use the DigitalOcean API to automate the deployment of these manifests to our actual cluster. I&apos;m glossing over a lot of detail here, but feel free to check out our &lt;a href=&quot;https://github.com/pennlabs/orb-helm-tools/blob/master/src/commands/deploy.yml&quot;&gt;deploy orb&lt;/a&gt; for the specifics.&lt;/p&gt;
&lt;h2&gt;End Result&lt;/h2&gt;
&lt;p&gt;There&apos;s been a lot of talk here about organizational philosophy and YAML templating, but let&apos;s circle back to what this system actually gives us.&lt;/p&gt;
&lt;p&gt;When one of our developers wants to create a new application, they can, completely independently, create a Git repo, add in a small CI config file, create their Icarus file, and add their proper secrets into Vault. Once that&apos;s done, they can push upstream to Github, and their application will be published to the domain they specified in their Icarus config in just a few minutes. If you ask me, that&apos;s pretty cool.&lt;/p&gt;
&lt;h2&gt;Reach Out&lt;/h2&gt;
&lt;p&gt;If any of this looks like it&apos;s up your alley or you wanna learn more about our mission, be sure to email us at &lt;a href=&quot;mailto:contact@pennlabs.org&quot;&gt;contact@pennlabs.org&lt;/a&gt; or &lt;a href=&quot;https://pennlabs.org/apply&quot;&gt;apply to be a part of Labs&lt;/a&gt;! We&apos;ve got some fantastic teams working on interesting problems with a direct impact on campus.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Year in Review: 2019-2020]]></title><description><![CDATA[Hi there! I’m Davis, the outgoing Director for Penn Labs this past school year. Recently, I’ve been thinking back on the year we’ve had, and…]]></description><link>https://pennlabs.org/blog/year-in-review-19-20</link><guid isPermaLink="false">https://pennlabs.orgblog/year-in-review-19-20</guid><pubDate>Sat, 23 May 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Hi there! I’m Davis, the outgoing Director for Penn Labs this past school year. Recently, I’ve been thinking back on the year we’ve had, and how lucky I’ve been to be able to be a part of Penn Labs during this super exciting time in the organization’s devlopment. Even with everything going on in the world right now, we’ve accomplished so much as a club this past year. I thought it would be a good time to take a more official look back and highlight the amazing things Penn Labs members have done. Hopefully, this can start a trend where the outgoing director takes a big-picture look backwards at the end of their tenure.&lt;/p&gt;
&lt;h1&gt;By the numbers&lt;/h1&gt;
&lt;p&gt;We are a technical club, and we do love data, so I thought I’d start off this review with some cold, hard numbers.&lt;/p&gt;
&lt;h2&gt;Recruitment&lt;/h2&gt;
&lt;p&gt;This club is nothing without the people that make it up. After our most intense and selective process yet, we welcomed &lt;strong&gt;thirty-six&lt;/strong&gt; new members between our Fall ’19 and Spring ’20 classes. Our fall class alone &lt;em&gt;doubled&lt;/em&gt; the size of Penn Labs.&lt;/p&gt;
&lt;p&gt;This kind of explosive growth has its challenges, but we’ve been able to take them in stride, and our new members have done amazing work for their product teams and accross the organization.&lt;/p&gt;
&lt;h2&gt;Product Growth&lt;/h2&gt;
&lt;p&gt;Alongside our team, our products have also seem super amazing growth this past year. The section below points out a few big highlights.&lt;/p&gt;
&lt;h3&gt;Penn Courses&lt;/h3&gt;
&lt;p&gt;Our course registration products are used most heavily during the registration period around when schedules are being released. During that time, two of our established course products saw pretty amazing growth.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Penn Course Alert&lt;/strong&gt; was started in Fall 2017 to help students more easily discover when courses have opened up for registration. The service’s userbase has grown steadily since then: each new freshman class brings a new opportunity for new users, who haven’t yet formed habits with other services. This year, we had a whopping 290% growth year-over-year in the days after schedules were released.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Penn Course Review&lt;/strong&gt; is the website that Penn Labs was first built around. Even though it’s been around for ten years, we’re still seeing growth among graduate students, faculty, and the undergraduate population. Usage during registration grew 24% year-over-year, which is pretty amazing for a tool that’s already ubiquitous in the student body.&lt;/p&gt;
&lt;h3&gt;Penn Mobile&lt;/h3&gt;
&lt;p&gt;Penn Mobile has always been one of our most well-known products, and this year we’ve added integration with your dining plan and an amazingly beautiful re-design on Android. On iOS, Penn Mobile has seen 70% year-over-year growth in its weekly active users, and on Android there’s been about 20% growth year-over-year!&lt;/p&gt;
&lt;h1&gt;New Things&lt;/h1&gt;
&lt;p&gt;It’s truly crazy how many new things we’ve launched this year, but I’ve tried to give space to them all. Hopefully, many of the items mentioned here will get their own blog posts some day!&lt;/p&gt;
&lt;h2&gt;Business Development Team&lt;/h2&gt;
&lt;p&gt;The BizDev, role was piloted during the 2017-2018 school year, but ultimately not continued for reasons chronicled in this &lt;a href=&quot;https://pennlabs.org/blog/its-so-fluffy&quot;&gt;article from our archives&lt;/a&gt;.
But if at first we don’t succeed, we certainly try again. BizDev was rebooted this year with a focus on outward-facing projects, encompassing everything from marketing to stakeholder relations to product management. Our BizDevs have been a core part of our success over the past year, and I’m excited to see how the role evolves in the future.&lt;/p&gt;
&lt;h2&gt;Penn Mobile Portal&lt;/h2&gt;
&lt;p&gt;The Spring of 2019 saw the indroduction of Penn Mobile’s homepage, which allowed users to see an at-a-glance view of all parts of Penn Mobile. We wondered how we could give groups around campus the ability to leverage this platform, and the Portal is our answer to that question. It’s been in beta this past year, but look for a general release in the next school year!&lt;/p&gt;
&lt;h2&gt;Deployment Infrastructure&lt;/h2&gt;
&lt;p&gt;Up until this Fall, all Penn Labs products were running on a single server. As we added more and more products that were serving more and more users, we realized that we needed a total overhaul to keep up with our growth. Our Platform team put together a really awesome system built on top of Kubernetes that will allow us to continue to scale out as we grow!&lt;/p&gt;
&lt;h2&gt;Penn Basics&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://pennbasics.com&quot;&gt;Penn Basics&lt;/a&gt; has been in the works since 2017, and finally was released in the Fall of this year. As a web-first view into all kinds of information at Penn, Basics has a real opportunity to give students tons of detail into resources around campus.&lt;/p&gt;
&lt;h2&gt;Penn Clubs&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://pennclubs.com&quot;&gt;Penn Clubs&lt;/a&gt; began as a partnership between Penn Labs, the UA and SAC to provide a way to discover clubs on campus that is much less stressful than the in-person club fair. After a crazy fun hackathon, we launched the day of the fall club fair, and ever since we’ve kept working with our stakeholders to improve the experience for students, club officers and administrators.&lt;/p&gt;
&lt;h2&gt;Penn Course Plan&lt;/h2&gt;
&lt;p&gt;Last year, we took over Penn Course Search from a graduating senior. After over a year of work, we re-designed the product from the ground-up and rebranded
as Penn Course Plan. You can read a lot more about the design process in Jess’s &lt;a href=&quot;https://pennlabs.org/blog/the-design-of-penn-course-plan-under-the-hood&quot;&gt;amazing writeup&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;Partnerships&lt;/h1&gt;
&lt;p&gt;We’ve always had a tight relationship with the University, but this year we’ve strengthened existing ties and reached out to create new ones.&lt;/p&gt;
&lt;h2&gt;OSA&lt;/h2&gt;
&lt;p&gt;The Office of Student Affairs has been an amazingly strong advocate for Penn Labs in recent years. With the development of Penn Clubs, we’ve had the opportunity to work even closer with the OSA to shape the future of how students and leaders interact with clubs on campus and the administration.&lt;/p&gt;
&lt;h2&gt;NGSS&lt;/h2&gt;
&lt;p&gt;For the first time in almost 30 years, &lt;a href=&quot;https://www.thedp.com/article/2019/10/upenn-course-registration-penn-in-touch-path&quot;&gt;the University is replacing Penn InTouch with a new system&lt;/a&gt;. Penn InTouch is most students’ main interaction with course registration and academic planning, areas in which Penn Labs is heavily involved. We’re greatful that the University has brought us to the table in discussions surrounding the Next Generation Student System, and it’ll be exciting to see where this initiative goes over the next two years.&lt;/p&gt;
&lt;h2&gt;Wharton Computing + CETS&lt;/h2&gt;
&lt;p&gt;This year, we’ve sought to reach out and strengthen connections with Penn’s various IT organizations, specifically &lt;a href=&quot;https://computing.wharton.upenn.edu/&quot;&gt;Wharton Computing&lt;/a&gt; and &lt;a href=&quot;https://cets.seas.upenn.edu/&quot;&gt;CETS&lt;/a&gt; within the Engineering school. Both of these organizations support a wide array of infrastructure that students use every day, and by opening up a line of communication, we can look for ways to better serve students while leveraging what groups have already built.&lt;/p&gt;
&lt;h2&gt;Cornell DTI&lt;/h2&gt;
&lt;p&gt;In recent months, we’ve been involved in a knowledge exchange with &lt;a href=&quot;https://www.cornelldti.org/&quot;&gt;Cornell’s Design &amp;#x26; Tech Initiative&lt;/a&gt;, an organization with a similar mission to Penn Labs. While our clubs are different, it’s been extremely illuminating to learn about how DTI designs and develops products.&lt;/p&gt;
&lt;h1&gt;Internal / Social&lt;/h1&gt;
&lt;h2&gt;First Retreat&lt;/h2&gt;
&lt;p&gt;Right after our Fall newbies joined, we went on our first ever retreat to &lt;a href=&quot;https://www.philahostel.org/&quot;&gt;Chamounix Mansion&lt;/a&gt; just north of campus! It was a really great way to get to play some boardgames (shoutout to Catan and Codenames) and get to know everyone outside of our usual environment.&lt;/p&gt;
&lt;h2&gt;First Formal&lt;/h2&gt;
&lt;p&gt;In December, we expanded our end-of-semester team dinner to a full-on formal! Labbies could bring a guest to a great evening of dinner and Dave &amp;#x26; Busters.&lt;/p&gt;
&lt;h1&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;A year is honestly a really long time, and so this post shouldn’t serve as anything more than an overview. But we’ve been able to do some amazing things for the Penn community since last May. There still are challenges ahead: we’ve grown quickly, but we’ve been able to maintain our sense of self and our sense of community. As time goes on, it’s important for us not to forget what makes Penn Labs special.&lt;/p&gt;
&lt;p&gt;I want to thank Valencia for being such an amazing mentor and partner, teaching me so much this year. I also want to thank Armaan for being an awesome co-director this past semester – I know that him and Marta are going to do amazing things this next year!&lt;/p&gt;
&lt;p&gt;Signing off, &lt;br /&gt;
– Davis&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The Design of Penn Course Plan]]></title><description><![CDATA[In 2017, Penn Labs acquired Penn Course Search, a former Penn student’s side project. At the start of 2019, we initiated a complete interface redesign, back-end rewrite, and rebrand of the product as Penn Course Plan.]]></description><link>https://pennlabs.org/blog/the-design-of-penn-course-plan-under-the-hood</link><guid isPermaLink="false">https://pennlabs.orgblog/the-design-of-penn-course-plan-under-the-hood</guid><pubDate>Tue, 04 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;h5&gt;&lt;em&gt;This article was originally posted &lt;a href=&quot;https://jesstan.me/penn-course-plan-redesign&quot;&gt;here&lt;/a&gt;.&lt;/em&gt;&lt;/h5&gt;
&lt;p&gt;&lt;strong&gt;TIMELINE&lt;/strong&gt;
Feb - Nov 2019 (10 months)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;ORGANIZATION&lt;/strong&gt;
Penn Labs&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TEAM&lt;/strong&gt;
Davis Haupt (Team Lead + Developer), Ying Xuan Eng (Developer), Daniel Like (Developer), Shaya Zarkesh (Developer), Daniel Tao (Developer), Charley Cunningham (Developer), Daniel Ng (Business Developer)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MY ROLE&lt;/strong&gt;
User Research, Experience Design, Interface Design, Visual Design&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TOOLS&lt;/strong&gt;
Sketch, Zeplin, Figma, Illustrator, HTML/CSS&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BACKGROUND&lt;/strong&gt;
Designing for the Courses team, I work closely with developers to build &lt;a href=&quot;https://penncourses.org/&quot;&gt;products&lt;/a&gt; that streamline course registration for students.&lt;/p&gt;
&lt;p&gt;In 2017, &lt;strong&gt;Penn Labs acquired Penn Course Search&lt;/strong&gt;, a former Penn student’s side project. At the start of 2019, we initiated a complete interface redesign, back-end rewrite, and rebrand of the product as Penn Course Plan. In October 2019, &lt;strong&gt;we launched Penn Course Plan&lt;/strong&gt; in time for Spring semester course registration.&lt;/p&gt;
&lt;p&gt;As the &lt;strong&gt;only designer for this project&lt;/strong&gt;, I was responsible for discovering user needs, designing the new interface, creating a style guide and component library, and handing off detailed mockups to developers.&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;The Problem&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;Course registration is a complicated and tedious process.&lt;/p&gt;
&lt;p&gt;When students plan their courses for the upcoming semester, there are many important factors to consider. However, pertinent information is &lt;strong&gt;decentralized across many resources&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The university’s course planning software Penn InTouch is &lt;strong&gt;notoriously difficult to navigate&lt;/strong&gt; and forces students to reference external tools. Penn Course Search addressed some of these shortcomings, but fell short on critical features and user friendliness.&lt;/p&gt;
&lt;p&gt;Penn undergraduates need a more comprehensive and intuitive course planning tool to simplify the complicated course registration process.&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;Approach&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1578969514913-TGD2IZSND8FLYUCERYU2/ke17ZwdGBToddI8pDm48kGMj-LAoQr-8HUYFhgjYiA8UqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dk66OfsUpYL1tkBhPbg_eXDVsoMMIaQGerMriyl50P62CjLISwBs8eEdxAxTptZAUg/process.png?format=1500w&quot; alt=&quot;process.png&quot;&gt;&lt;/p&gt;
&lt;h1&gt;&lt;strong&gt;Solution&lt;/strong&gt;&lt;/h1&gt;
&lt;p&gt;We built &lt;a href=&quot;https://penncourseplan.com&quot;&gt;Penn Course Plan&lt;/a&gt;, a web app that allows students to &lt;strong&gt;find and plan their courses&lt;/strong&gt; for the upcoming semester, combining a &lt;strong&gt;comprehensive course search&lt;/strong&gt; with a &lt;strong&gt;simple mock scheduling tool&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Penn Course Plan aims to help students feel more &lt;strong&gt;informed&lt;/strong&gt; and &lt;strong&gt;confident&lt;/strong&gt; when choosing courses, while &lt;strong&gt;efficiently&lt;/strong&gt; and &lt;strong&gt;intuitively&lt;/strong&gt; creating mock schedules.&lt;/p&gt;
&lt;h2&gt;Search for courses and create mock schedules&lt;/h2&gt;
&lt;p&gt;Look for courses to take next semester and keep your options in your course cart. Plan your schedule by adding courses from your cart to multiple mock schedules.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1578972613563-BH0UNIG4N8DTX0ZY77PR/ke17ZwdGBToddI8pDm48kNSqDleq7bHSZc-xq6aRYQt7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0h1yvUMVfVaSHKnWSjKaKj6qtUcCwJq445UTi6b1UqWCNLINrcpf3KRGeNa9K-8jVQ/desktop+2.png?format=1500w&quot; alt=&quot;desktop 2.png&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Filter and sort search results&lt;/h2&gt;
&lt;p&gt;Efficiently find classes that fulfill general education requirements and double count. Additionally, filter by quality, difficulty, course units, and type. Sort classes by difficulty and course quality.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1578972776694-SDZKR5U5SBOLH1WOISAP/ke17ZwdGBToddI8pDm48kNSqDleq7bHSZc-xq6aRYQt7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0h1yvUMVfVaSHKnWSjKaKj6qtUcCwJq445UTi6b1UqWCNLINrcpf3KRGeNa9K-8jVQ/desktop+1.png?format=1500w&quot; alt=&quot;desktop 1.png&quot;&gt;&lt;/p&gt;
&lt;h2&gt;View relevant schedule statistics&lt;/h2&gt;
&lt;p&gt;Get an overview of each mock schedule with average quality, difficulty, and workload. Manage your time with stats on total credits and hours of class time.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1578972859063-27UHBDZ5ENTPIVCB0QJJ/ke17ZwdGBToddI8pDm48kNSqDleq7bHSZc-xq6aRYQt7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0h1yvUMVfVaSHKnWSjKaKj6qtUcCwJq445UTi6b1UqWCNLINrcpf3KRGeNa9K-8jVQ/desktop+3.png?format=1500w&quot; alt=&quot;desktop 3.png&quot;&gt;&lt;/p&gt;
&lt;h1&gt;Research&lt;/h1&gt;
&lt;h2&gt;DEFINING TARGET USERS&lt;/h2&gt;
&lt;h3&gt;Who are we designing for?&lt;/h3&gt;
&lt;p&gt;Considering the immense diversity among the &lt;strong&gt;10,000 undergraduate students&lt;/strong&gt; at Penn, it was important to identify subgroups within the population to understand their unique needs, motivations, and pain points.&lt;/p&gt;
&lt;p&gt;Penn has &lt;strong&gt;four individual undergraduate schools&lt;/strong&gt;.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579247873933-ZJ5HA082Y7FNIHBO3D4Z/ke17ZwdGBToddI8pDm48kNs8p-E830a5lpFqZZw_Gw0UqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dlXcHO412CUWxsDU7HmkfGQ6d4x_Vnv_Gu3C8EJU-bzIJvwGh1qtNWvMhYKnvaKhbA/school%2Bbreakdown.jpg?format=1500w&quot; alt=&quot;school+breakdown.jpg&quot;&gt;
Coordinated and uncoordinated &lt;strong&gt;dual degree programs&lt;/strong&gt; (multiple schools) are not uncommon at Penn.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579247908945-5R3GKEN2WP1HF5ZX3MMM/ke17ZwdGBToddI8pDm48kPAuVrV5Ri5yzvNUAaabxVYUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dgrxiHTdhPS3THoNXnOOlEGesP6m2KzPk1ZdmkLWGTsrCjLISwBs8eEdxAxTptZAUg/degree+programs.png?format=1500w&quot; alt=&quot;degree programs.png&quot;&gt;
While all students choose from the same course offerings, &lt;strong&gt;each school has their own graduation requirements.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Additionally, course planning considerations vary significantly between freshmen, sophomores, juniors, and seniors.&lt;/p&gt;
&lt;h3&gt;You are not your user&lt;/h3&gt;
&lt;p&gt;At Penn Labs, products are built for students by students. While acting as everyday observers of campus life makes it easier to empathize with our target audience, it poses its own challenges.&lt;/p&gt;
&lt;p&gt;It was quick and convenient to test and gather feedback from Labs members at each step of the process, making it easy to fall into the trap of &lt;strong&gt;assuming that we are representative of the target audience&lt;/strong&gt;. This would be a dangerous assumption, since our members tend to be more tech savvy and motivated to use our products than the average user.&lt;/p&gt;
&lt;p&gt;Throughout the redesign process, I made an effort to frequently gather feedback from and conduct usability tests with a broad spectrum of users to obtain &lt;strong&gt;authentic and unbiased feedback&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;USER RESEARCH&lt;/h2&gt;
&lt;h3&gt;Talking to People&lt;/h3&gt;
&lt;p&gt;I talked to many students across several demographics, including graduation year, school, intended field of study, and familiarity with Penn Courses products.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579466824791-ACEBQC2LTELG58IO63HG/ke17ZwdGBToddI8pDm48kLFXaXK02hYMH21Yz0XPUpEUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dgZYlRD-LKrIS4b2X6tJu2RI1v_cqfer-YL7gRsGDWiyCjLISwBs8eEdxAxTptZAUg/interview.png?format=1500w&quot; alt=&quot;interview.png&quot;&gt;
The general interview protocol involved asking questions that would help me understand &lt;strong&gt;how students currently plan their courses&lt;/strong&gt; and &lt;strong&gt;what problems exist in the process&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;What factors do you consider when deciding what classes to take?&lt;/li&gt;
&lt;li&gt;What resources do you reference when you’re planning your schedule?&lt;/li&gt;
&lt;li&gt;What’s your process for creating a mock schedule?&lt;/li&gt;
&lt;li&gt;What’s your biggest challenge when planning courses for next semester?&lt;/li&gt;
&lt;li&gt;What are the most helpful and frustrating features on Penn InTouch?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579466902805-I5GXPMPDYYIPO8C5R5RQ/ke17ZwdGBToddI8pDm48kIvHkQ0RPjKieJMBDv_aX_J7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1USBgIzQzRi9Lxz_VifZkoa_3VWY6cnuZhh2or8fimZSmZDqXZYzu2fuaodM4POSZ4w/interview+quotes.png?format=1500w&quot; alt=&quot;interview quotes.png&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Synthesizing Online Data&lt;/h3&gt;
&lt;p&gt;To better understand student needs, &lt;strong&gt;I analyzed the different curriculums and graduation requirements for each undergraduate school&lt;/strong&gt; using their course planning worksheets. I synthesized the results into key findings for each school.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579467173186-VQIO6PSQUC8AA0OAFAKE/ke17ZwdGBToddI8pDm48kNdbFap9h41-5dHMTBiLuVh7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1UYF0sxsD5hxvQYFtmAAuJBO5WcTIoZL6oX7IdsoQHTlEZtJ3qR9G2BYeA0wOAaeYNg/grad+requirements.png?format=1500w&quot; alt=&quot;grad requirements.png&quot;&gt;
I also gathered comments about Penn InTouch from students who expressed their criticisms in the Daily Pennsylvanian and a published document by the Student Committee for Undergraduate Education.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579467989289-VJ7NSOCCEFB77UE0R0YO/ke17ZwdGBToddI8pDm48kJ4nw0kgrRqMk0wI_uv3Uhh7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1UQwz0RywtbPqgMoZ0h8MmYyytAXdL6bu5-JLzhING35xOpYghpI-Ha_TwZsqqmJXng/online.png?format=1500w&quot; alt=&quot;online.png&quot;&gt;
I found that students were frustrated by the &lt;strong&gt;inconvenience of navigating to multiple tabs&lt;/strong&gt; to find the information they needed. There was also** lack of trust** in the software due to the &lt;strong&gt;outdated interface and the buggy experience&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Key Findings&lt;/h3&gt;
&lt;p&gt;Taking note of the patterns that emerged from the various research methods, I identified the following pain points in the course registration process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Students take many factors into consideration when constructing their schedule, but all the information they need is spread across many different sites and tools.&lt;/li&gt;
&lt;li&gt;Penn offers thousands of classes, and students have trouble narrowing their choices.&lt;/li&gt;
&lt;li&gt;Students are unsatisfied with the current resources (Penn InTouch and university academic advising) but some are unaware that other resources exist.&lt;/li&gt;
&lt;li&gt;It’s tedious to build mock schedules on Penn InTouch because searching for courses and viewing them in mock schedules requires toggling between multiple pages.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Because of these difficulties, course planning as it stands now is &lt;strong&gt;frustrating&lt;/strong&gt; and &lt;strong&gt;stressful&lt;/strong&gt; process.&lt;/p&gt;
&lt;h2&gt;IDENTIFYING NEEDS&lt;/h2&gt;
&lt;h3&gt;Crafting User Personas&lt;/h3&gt;
&lt;p&gt;From the research, I constructed a few personas to represent target user groups and explored their needs, frustrations, and end goals.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579468137999-45UNUJLEMG1LS6DT6CJI/ke17ZwdGBToddI8pDm48kE5o8LsotPSif-EGjnnEbqh7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0lSrx5cIn5kROUr3kXNkaFl-PnpvJQ38ab7haEFrZNB1gR2GInfqks_nwFbBT5l92Q/personas.png?format=1500w&quot; alt=&quot;personas.png&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Establishing Design Goals&lt;/h3&gt;
&lt;p&gt;With the user research insights and personas in mind, I worked with my team todecide &lt;strong&gt;which user pain points and business goals to tackle before the October launch&lt;/strong&gt;. Here are the primary goals we decided upon:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Enable users to effortlessly and efficiently access the data they need to construct an informed course plan.&lt;/li&gt;
&lt;li&gt;Make it easier to find classes by designing an intuitive, unintimidating course search experience&lt;/li&gt;
&lt;li&gt;Structure the site in a way that seamlessly bridges the course search and mock schedule functionalities.&lt;/li&gt;
&lt;li&gt;Create a visual style guide and component library that dictates interactive states and technical specifications for developers.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;If the goals have been met, we can help users feel more informed and less stressed while planning out the next semester and integrate Penn Course Plan within the Penn Courses ecosystem.&lt;/strong&gt;&lt;/p&gt;
&lt;h1&gt;Ideate&lt;/h1&gt;
&lt;h2&gt;EXISTING SOLUTIONS&lt;/h2&gt;
&lt;h3&gt;Auditing the Current Version&lt;/h3&gt;
&lt;p&gt;With what I learned about our users, I determined what features from Penn Course Search to keep, improve, create, or get rid of.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579468504734-134ZQ5EZ2F9B0WZQBNHK/ke17ZwdGBToddI8pDm48kDkOjzditUMAGMM1FjUnmegUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dgt5zWzrP_VD5y_MDDujQV5JvP8ua1Zs7xWpeTm8C0CPCjLISwBs8eEdxAxTptZAUg/pcs+audit.png?format=1500w&quot; alt=&quot;pcs audit.png&quot;&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Keep layout order.&lt;/strong&gt; Search, results, then schedule is a logical order to users.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improve search filtration.&lt;/strong&gt; Filters are hidden from the default display and applied filters are not displayed upon search.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improve schedule hierarchy.&lt;/strong&gt; Organize arrangement of schedule management actions. Display courses on the calendar in an accessible manner.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Improve display of search result.&lt;/strong&gt; Make section details scannable. Find an accessible and efficient way to visualize rating values.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add more filtration capabilities.&lt;/strong&gt; Incorporate highly requested filter options (i.e. quality, difficulty, time, credits).&lt;/li&gt;
&lt;li&gt;**Add schedule statistics. **Display data visualizations of that provide statistical overviews of mock schedule difficulty, quality, workload, and time.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remove underused features.&lt;/strong&gt; Import schedule and filter by special programs required lots of technical resources and were used by less than 2% of users.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Competitive Analysis&lt;/h2&gt;
&lt;h3&gt;Penn InTouch&lt;/h3&gt;
&lt;p&gt;I first took a look at Penn InTouch, the university software that all students currently use to search for and plan their courses.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1575022032174-Z7W5MTK82L8IJSMKPLMW/ke17ZwdGBToddI8pDm48kNXLAH8BQLvZbUOUXU0Ill5Zw-zPPgdn4jUwVcJE1ZvWQUxwkmyExglNqGp0IvTJZUJFbgE-7XRK3dMEBRBhUpzCt6o-iRhrQwYBoWKfs44XLUez93aWT_VZ_t4FkEARxLu0Jgyq8_NxOgW5PXJL0lM/penn+intouch.gif?format=1500w&quot; alt=&quot;adding a course to my mock schedule on PennInTouch&quot;&gt;
adding a course to my mock schedule on PennInTouch&lt;/p&gt;
&lt;p&gt;The main pain point of building schedules in PennInTouch is the &lt;strong&gt;need to toggle between multiple pages&lt;/strong&gt; (‘Course search’ and ‘My mock schedules’) when creating the mock schedule.&lt;/p&gt;
&lt;p&gt;Users must search for courses on the search page, add the courses they would like to put in their mock schedule to the course cart, then switch to the mock schedules page to add courses from the cart to the mock schedule.&lt;/p&gt;
&lt;h3&gt;Coursicle&lt;/h3&gt;
&lt;p&gt;Because the university’s software Penn InTouch fails to address key user needs, students have turned to non-university affiliated options. &lt;strong&gt;Penn Course Plan’s direct competitor is Coursicle&lt;/strong&gt;, a site that features course catalogues and schedule builders for hundreds of universities.&lt;/p&gt;
&lt;p&gt;While Coursicle’s objective is to provide a “less stressful” and “more modern” alternative to “slow, unintuitive, and ugly online systems,” &lt;strong&gt;it falls short in delivering user-friendly interactions and comprehensive course data&lt;/strong&gt;.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579468878510-PAPYEP5E29Z571L3YRAP/ke17ZwdGBToddI8pDm48kDvjYe5ClDL6BPjsFpND_CgUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2drFNekTSzjhQfd4Vp0iAKzShDcWq4uEu1t4aC25LrfifCjLISwBs8eEdxAxTptZAUg/coursicle.png?format=1500w&quot; alt=&quot;coursicle.png&quot;&gt;
&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;sleeker interface than Penn InTouch&lt;/li&gt;
&lt;li&gt;enables efficient management of multiple mock schedules&lt;/li&gt;
&lt;li&gt;side by side placement of search results and mock schedule&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;separates course search and schedule creation onto two different pages&lt;/li&gt;
&lt;li&gt;contains two separate mechanisms for adding courses to the schedule&lt;/li&gt;
&lt;li&gt;lacks sufficient information about courses and sections&lt;/li&gt;
&lt;li&gt;missing critical course filtration functionality&lt;/li&gt;
&lt;li&gt;poor hierarchy in search results and course details&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because Coursicle services so many universities, it does not address the specific needs of Penn students. I summarized the &lt;strong&gt;main opportunity areas that Penn Course Plan can address&lt;/strong&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Search and schedule are still on separate pages, requiring the same frustrating toggling behavior as Penn InTouch.&lt;/li&gt;
&lt;li&gt;Critical information that students take into account when deciding upon courses, such as student reviews and course descriptions, are not displayed. Additionally, there are no warnings for co-requisite sections.&lt;/li&gt;
&lt;li&gt;Search filters are not comprehensive. The filters only cover general education requirements for College students, missing Engineering/Wharton/Nursing students.&lt;/li&gt;
&lt;li&gt;The search results are cluttered and do not display information students care about hierarchically.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;BRAINSTORMING&lt;/h2&gt;
&lt;h3&gt;Ideating Features&lt;/h3&gt;
&lt;p&gt;After establishing the design goals and gaps in existing solutions, I brainstormed ideas to address those gaps with my team, prioritizing based on &lt;strong&gt;importance to users **and&lt;/strong&gt; feasibility**.&lt;/p&gt;
&lt;h3&gt;Working with Constraints&lt;/h3&gt;
&lt;p&gt;By talking to developers during ideation, &lt;strong&gt;I was able to uncover technical constraints and compromise early on&lt;/strong&gt;. We determined which features were feasible to implement before our launch, which were feasible to implement eventually, and which were not feasible at all.&lt;/p&gt;
&lt;p&gt;We settled on the following &lt;strong&gt;major features for the initial redesign&lt;/strong&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;**Course search: **Search for courses by course name, department, and professor. Sort search results.&lt;/li&gt;
&lt;li&gt;**Search filters: **Keep existing filtration capabilities. Incorporate filters that rely on Penn Course Review data and compatibility with the existing schedules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Section details:&lt;/strong&gt; View course section details in scannable table cells. Add sections to the cart.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Course cart:&lt;/strong&gt; Store course sections in the cart to be added to multiple mock schedules.&lt;/li&gt;
&lt;li&gt;**Mock schedules: **View course sections in calendar format. Manage (create, copy, and delete) schedules.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Schedule statistics:&lt;/strong&gt; View relevant data that gives an overview of mock schedule parameters.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Some features that we** eventually hope to implement** include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Filter by major:&lt;/strong&gt; Major requirements are housed on each department’s website, and are not formatted consistently across departments. This makes it difficult to implement this feature without extensive manual input.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Academic worksheets:&lt;/strong&gt; Academic worksheets on Penn InTouch are customized course checklists based on a student’s chosen academic plan. However, because these checklists are based on major requirements.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;User accounts:&lt;/strong&gt; Penn Course Plan is now moving all its products towards an accounts system to save user information in their PennKey login.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These features were tricky to deal with, since I had to keep their potential entry points in mind while laying out the initial interface.&lt;/p&gt;
&lt;h1&gt;Design&lt;/h1&gt;
&lt;h2&gt;SKETCHES AND WIREFRAMES&lt;/h2&gt;
&lt;h3&gt;Crafting the Layout&lt;/h3&gt;
&lt;p&gt;I started the design process by sketching to explore the layout and placement of several features. I collected qualitative feedback from my team members and other students throughout this stage.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1575020704627-MNUWUW4ZL3KJ7UWFB563/ke17ZwdGBToddI8pDm48kPbzBuf2ArfuRhLwY5tFevt7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0lCvyAd1-5UQFnp8aARaJsXjKOFf5OJ5WgXNLk61DlM6pp3Givmz8voJ34VS-RBhTQ/FullSizeRender.jpg?format=1500w&quot; alt=&quot;FullSizeRender.jpg&quot;&gt;
After receiving feedback on these initial explorations, I made the following design decisions concerning the layout:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Keep the course search on top, but separate it from navigation, to group it visually with the sections below.&lt;/li&gt;
&lt;li&gt;Combined the search results with section details to reduce redundant information and make room for a course cart.&lt;/li&gt;
&lt;li&gt;grouped the schedule management functions with the mock schedules.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I then created mid-fidelity wireframes to finalize the layout to determine where the search filters and academic worksheets would go.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579469470633-RQO0SQOBJ97O71TRSKN2/ke17ZwdGBToddI8pDm48kLjo2pwpCNhHFi3MGDqNta0UqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnJHB7uoZmMRl-FGQ_02ONmrLi6kVZnu4f0XvBEoCM4E708ivIDv41dicd3FbaK_JIw/wireframes.png?format=1500w&quot; alt=&quot;wireframes.png&quot;&gt;
&lt;strong&gt;A&lt;/strong&gt; features a search section (filters, search results) and a schedules section (cart, mock schedules). While organized simply, I found it difficult to make responsive without dramatic changes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;B&lt;/strong&gt; is more modular, with separate search, results, cart, and schedules sections. The layout is more complex than &lt;strong&gt;A&lt;/strong&gt;, but the flow remains intuitive.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;C&lt;/strong&gt; retains the layout of &lt;strong&gt;B&lt;/strong&gt;, but features worksheets on a slide out section. While this allows users to use the worksheet while viewing the other functions, it limits the amount of space available for the worksheet features.&lt;/p&gt;
&lt;p&gt;I settled on &lt;strong&gt;B&lt;/strong&gt;, since the tabbed navigation allows for more flexible feature additions than &lt;strong&gt;C&lt;/strong&gt; and the modular layout is more responsive than &lt;strong&gt;A&lt;/strong&gt;.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579469756398-45SM6Q0IWVU7SRTWVJVU/ke17ZwdGBToddI8pDm48kNSqDleq7bHSZc-xq6aRYQt7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0h1yvUMVfVaSHKnWSjKaKj6qtUcCwJq445UTi6b1UqWCNLINrcpf3KRGeNa9K-8jVQ/layout+1.png?format=1500w&quot; alt=&quot;layout 1.png&quot;&gt;
After deciding on &lt;strong&gt;B&lt;/strong&gt;, I began exploring the individual features in more detail.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1575020755296-HTQFKOAQ8NV2E8D2P1Y1/ke17ZwdGBToddI8pDm48kPyxK6AB3zgGizbLyl3cQLF7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0hHMyhIh2kKzuOL3ydJCryA1F0gmNLmEt4Nikyd91URavr8Aoi-yShiL3L-0iJr14g/IMG_6129.jpg?format=1500w&quot; alt=&quot;IMG_6129.jpg&quot;&gt;&lt;/p&gt;
&lt;h2&gt;DEEP DIVES&lt;/h2&gt;
&lt;h3&gt;Search Filters&lt;/h3&gt;
&lt;p&gt;In the current interface, search filters are hidden from the default display and applied filters are not displayed upon search.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579470261520-LC8X9VTD5KBU62JLSABL/ke17ZwdGBToddI8pDm48kPcrQDdGRjn33VeTEAOLXuUUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnGjCs3rmYYOKaIyun3uqT6zB7H3PFGuJqYzCbh4lmGNvGr0bpppeQMJFVd3NJWMNBQ/filter+bar+old.jpg?format=1500w&quot; alt=&quot;filter bar old.jpg&quot;&gt;
By observing users, I learned that this interaction caused confusion when filters that were applied earlier yielded empty search results. This confusion led to &lt;strong&gt;frustration&lt;/strong&gt; and &lt;strong&gt;lower trust&lt;/strong&gt; in the course search feature.&lt;/p&gt;
&lt;h4&gt;Determining structure&lt;/h4&gt;
&lt;p&gt;First, I explored two ways to increase the visual prominence of the filters: a vertical sidebar and a horizontal toolbar.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579475229703-3CS48J0KX7RDSF6CRI5O/ke17ZwdGBToddI8pDm48kFbbcC-Kq3NpSe_YwDxo2u8UqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dk0pufro8FM70fikr4ziUXMy_wcLCTNKw2NI2FFK5ut4CjLISwBs8eEdxAxTptZAUg/filter+layout.png?format=1500w&quot; alt=&quot;filter layout.png&quot;&gt;
&lt;strong&gt;A&lt;/strong&gt; is easier to skim and unrestricted by page width. However, I found that seeing all the filter options at once is not helpful enough to users to justify the amount of space the sidebar requires.&lt;/p&gt;
&lt;p&gt;I decided on &lt;strong&gt;B&lt;/strong&gt;, since it increases visibility of filter options in a compact and easily discoverable manner.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579475395096-AXD9OHPCAIKJPKM02NGG/ke17ZwdGBToddI8pDm48kF5UX9sv3qnorMvfeWsQcRkUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnOaBWGfNSIFSZT-DifuX7fYK8uz5PaI1fEvlSwsciJPNUzGH5iPj_X_jWLQv88aWoQ/horizontal.png?format=1500w&quot; alt=&quot;horizontal.png&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Defining interactions&lt;/h4&gt;
&lt;p&gt;I studied the way products like AirBnB and Google Fonts handle search filtration interactions. I found that distinctive interaction states were essential for creating an intuitive search experience.&lt;/p&gt;
&lt;p&gt;AirBnB replaces category labels with selected values. With this design, users can see exactly which filter values are selected. I experimented with this approach for Penn Course Plan’s filters.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579475624768-MQC7BFSMLK06IIBUMYQV/ke17ZwdGBToddI8pDm48kDvjYe5ClDL6BPjsFpND_CgUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2drFNekTSzjhQfd4Vp0iAKzShDcWq4uEu1t4aC25LrfifCjLISwBs8eEdxAxTptZAUg/image-asset.png?format=1500w&quot;&gt;
AirBnB replaces category labels with selected values. With this design, users can see exactly which filter values are selected. I experimented with this approach for Penn Course Plan’s filters.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579475886533-ICY5A09RSXD3JN5ULMH2/ke17ZwdGBToddI8pDm48kEKJwit1Puqdr_r65LSKdMYUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnCCjcGrwyqpflYGBdsBIsxxTikOVtpbjsPXNgimzPigxbLgUMR4A_MCEBwDwJCq08g/filter+sample.png?format=1500w&quot; alt=&quot;filter sample.png&quot;&gt;
However, I learned that this would not work for several edge cases, such as multiple long category values and categories with the same value types.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579475911063-CO15ROHJS2EQ27QA26DJ/ke17ZwdGBToddI8pDm48kLz6o3K-fEHESwHBApaESnYUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnIFVVuGDNp_E69mIpPVpRR2DSySenlKfMgmppau_orlrc42OLw2bwu88hR-6Drr8dg/filter+edge.png?format=1500w&quot; alt=&quot;filter edge.png&quot;&gt;
Google Fonts replaces category labels when one value is selected, but not multiple. In all cases, changing in the filter background color and addition of the X button make it clear to the user which filters have been applied. I explored a similar approach for Penn Course Plan’s filters.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579475968903-ESGN6UQBK6ZXERT3DTSG/ke17ZwdGBToddI8pDm48kEKJwit1Puqdr_r65LSKdMYUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnCCjcGrwyqpflYGBdsBIsxxTikOVtpbjsPXNgimzPigxbLgUMR4A_MCEBwDwJCq08g/filter+final.png?format=1500w&quot; alt=&quot;filter final.png&quot;&gt;
This design resolves the usability issues from the previous iteration. Although selected filter values are not readily displayed in this design, users found the distinct interactive states sufficient for conveying this information.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579476418985-BI2NWZ1F4AJX0HOTZG29/ke17ZwdGBToddI8pDm48kOpRmX73zeyxPeIV4KIc2MEUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2ds-BpdfBoAwdkQFZIcBL4kNSj10mfLxEAdwISRD2ljpZCjLISwBs8eEdxAxTptZAUg/filter+states.png?format=1500w&quot; alt=&quot;filter states.png&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Filter category dropdowns&lt;/h4&gt;
&lt;p&gt;I designed dropdowns for the current filter categories: school requirements, section type, and course units. I added filters for course difficulty and quality ranges, based on Penn Course Review data.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579476901050-OR7SS5AOWFIC85IFIAKW/ke17ZwdGBToddI8pDm48kA7upsajumz_cbkfS7QP-Ld7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1USRGw2vV19SCeZbkvd9sFMkg2zBXIIvmu6wDivcNUgFIMW9u6oXQZQicHHG1WEE6fg/categories.png?format=1500w&quot; alt=&quot;categories.png&quot;&gt;
Additional filters I considered including were time range, open/closed status, and compatibility with the selected mock schedule. These were not technically feasible to implement before launch.&lt;/p&gt;
&lt;h4&gt;Clarifying the empty state&lt;/h4&gt;
&lt;p&gt;I also designed an empty state for when applied filters cause the search query to return no results. The distinct illustration and guiding copy clarify the situation.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580674350707-VLGF9NOFXY7G9UMNE9KI/ke17ZwdGBToddI8pDm48kNSqDleq7bHSZc-xq6aRYQt7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0h1yvUMVfVaSHKnWSjKaKj6qtUcCwJq445UTi6b1UqWCNLINrcpf3KRGeNa9K-8jVQ/empty+state+filters.png?format=1500w&quot; alt=&quot;empty state filters.png&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Course and Section Information&lt;/h3&gt;
&lt;p&gt;Displaying the details for each course was the biggest challenge in the redesign. From user research, I learned about the many factors students take into consideration while choosing their courses.&lt;/p&gt;
&lt;p&gt;On &lt;strong&gt;Penn InTouch&lt;/strong&gt;, section details are displayed in a dense horizontal table with modals for additional information.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579478776268-ITR57XNLDQJGQIXN5UGZ/ke17ZwdGBToddI8pDm48kOwxqLam4WP37WmjfuO_Og0UqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dmzn7wSQ6zEl16uZ2-L93g2syfcAj9-uvHmQPVz6N4mgCjLISwBs8eEdxAxTptZAUg/details+pit.png?format=1500w&quot; alt=&quot;details pit.png&quot;&gt;
On &lt;strong&gt;Penn Course Search&lt;/strong&gt;, the course and section information are displayed in two separate panels. The section panel contains a table with a row for each section, showing additional details when clicked.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579478817234-6RDTTIEKPR18BG95BY52/ke17ZwdGBToddI8pDm48kNWBK1t-9L96B9fwvDxOcZAUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dqP_SSzd8krbGFpvEtuz1h7NEYhKL1TexwN6THeCJVrZCjLISwBs8eEdxAxTptZAUg/details+pcs.png?format=1500w&quot; alt=&quot;details pcs.png&quot;&gt;
For both Penn InTouch and Penn Course Search, it takes at least three clicks across two different areas to uncover all the details students use to make an informed decisions about courses.&lt;/p&gt;
&lt;p&gt;My strategy was to &lt;strong&gt;condense course information into simple table cells while maintaining pertinent details&lt;/strong&gt;. I focused on establishing visual hierarchy and scanability.&lt;/p&gt;
&lt;h4&gt;Course search flow&lt;/h4&gt;
&lt;p&gt;For each course at Penn, there are several associated sections (i.e. lectures, labs, and recitations) that students can choose from.&lt;/p&gt;
&lt;p&gt;When users enter a &lt;strong&gt;general search term&lt;/strong&gt; (i.e. “CHEM” or “algorithms”) the search results will include summarizing parameters relevant to all sections of the course.&lt;/p&gt;
&lt;p&gt;When users click on a general search result, or if they enter a &lt;strong&gt;specific search term&lt;/strong&gt; (i.e. “CHEM 101” or “Introduction to Algorithms”) they will be shown more details about the course, as well as information on the individual sections.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579480057599-BO99FLLC0F3WWXMEZB9A/ke17ZwdGBToddI8pDm48kL41QpzrlVe6KRwdd9SmRxt7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0jAoOkRmPE63FUjiJOEKAz5eQqLOXTawWlDNor16sPB1rbAJnZhF-tEAToVFZ1xAVw/flow+sketch.jpg?format=1500w&quot; alt=&quot;flow sketch.jpg&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Course summary view&lt;/h4&gt;
&lt;p&gt;I started by designing the general search results, which display information relevant to all sections of the course: course number, course title, quality, difficulty.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579481248400-GZRFCJ8MY0NKD2P75NCM/ke17ZwdGBToddI8pDm48kFykgoVIAvN21zI7e3ZvRtN7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1UUFFISoLU0OLmOOl3H8mgJSAyHwo5EUI-hEXq-oQKGbz7zs2yPjc1ECvpa5Zm_kMqw/results+wireframe.png?format=1500w&quot; alt=&quot;results wireframe.png&quot;&gt;
A key design decision I made was to change the visualization of the quality and difficulty metrics to be consistent with Penn Course Review’s color system.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579485077094-E143SWKQ6C60HAZSA5R1/ke17ZwdGBToddI8pDm48kMw2n72zKJFDf9B1PBOBI5J7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0nPyVNphCkITW9LFG_i7IoT2_ZDoK6EVsZjh1Q7Bz5FJDWs0kFi7g_2tYwvGoR-xog/results+exploration.png?format=1500w&quot; alt=&quot;results exploration.png&quot;&gt;
&lt;strong&gt;A&lt;/strong&gt; is based on Penn Course Search’s system, which uses opacity to denote quality and difficulty levels (low rating = low opacity, high rating = high opacity).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;B&lt;/strong&gt; is based on Penn Course Review’s system, which uses three discrete colors to represent three levels (low, medium, and high).&lt;/p&gt;
&lt;p&gt;In &lt;strong&gt;C&lt;/strong&gt;, I considered using green for high quality/low difficulty and red for low quality/high difficulty, since many students are actively looking for good and easy courses. However, I was told that the University administration took issue when PCR considered doing this in the past, since they were concerned that users would associate green with good and red with bad.&lt;/p&gt;
&lt;p&gt;I went with &lt;strong&gt;B&lt;/strong&gt;, since I found that users could more easily distinguish between the different colors used by PCR than the different opacities used by PCS. To account for this tradeoff made by forgoing** C**, one of the developers implemented a “good and easy” sort to rank the results by descending quality and ascending difficulty.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579485301451-JSOA8DE7TIRJ1HP4PW52/ke17ZwdGBToddI8pDm48kFykgoVIAvN21zI7e3ZvRtN7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1UUFFISoLU0OLmOOl3H8mgJSAyHwo5EUI-hEXq-oQKGbz7zs2yPjc1ECvpa5Zm_kMqw/results+final.png?format=1500w&quot; alt=&quot;results final.png&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Section details view&lt;/h4&gt;
&lt;p&gt;I then designed the section details display. This view contains the entry point for additions to the course cart.&lt;/p&gt;
&lt;p&gt;I first divided the section information methodologically based on whether the parameters were relevant to all sections or if they were specific to individual sections.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;all sections:&lt;/strong&gt; course quality, course difficulty, requirements fulfilled, instructor quality, prerequisites, cross-listings, course description&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;individual sections:&lt;/strong&gt; section number, section instructor, instructor difficulty, meeting time, meeting location, open/closed status&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I chose to display the information for &lt;strong&gt;all sections&lt;/strong&gt; at the top.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579490946533-M42V5VMH68Q4XUOGDR6V/ke17ZwdGBToddI8pDm48kPzB9dY1J7dPXg53oEKYDSYUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnJbATwfeW1gHCeZ8_dfMRcTQTOYHd4AkDsV1bwwOcjh3OYZBCYhU1Ab3_GxFlgFZlA/details+exploration.png?format=1500w&quot; alt=&quot;details exploration.png&quot;&gt;
&lt;strong&gt;B **includes the course quality and difficulty metrics missing from **A&lt;/strong&gt; and has a visual style more consistent with the rest of the product.&lt;/p&gt;
&lt;p&gt;I noticed that users did not realize the prerequisites and cross-listings were clickable in &lt;strong&gt;B&lt;/strong&gt;, so I transformed them into links in &lt;strong&gt;C&lt;/strong&gt;. Since quality, difficulty, and requirements fulfilled are not clickable, I transformed them into tags. I also added a link to the course’s Penn Course Review page and a collapsed course description below.&lt;/p&gt;
&lt;p&gt;Information for &lt;strong&gt;individual sections&lt;/strong&gt; is displayed below the information for all sections. I explored two alternatives for this table.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579491683123-SQMLISCNFWOX0BBBZKV8/ke17ZwdGBToddI8pDm48kBExbrOQmZl2srw--jhzZZEUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnI61oPTiDSKcU2aVIc63nsZwzm2rWHsK5j87IvA5fymdAIr7hVx9mD1MsogOimfAJQ/table+explorations.png?format=1500w&quot; alt=&quot;table explorations.png&quot;&gt;
&lt;strong&gt;A&lt;/strong&gt; displays most of the section details in a single line table, with additional information (i.e. section instructor, meeting location) displayed when a section is clicked.&lt;/p&gt;
&lt;p&gt;**B **displays all the section details in a two-line table. Section number and instructor are highlighted in the first row and all other details are placed below.&lt;/p&gt;
&lt;p&gt;From user testing, I learned that people found the extra click view additional section information in &lt;strong&gt;A&lt;/strong&gt; to be a nuisance. They preferred seeing the expanded view for all sections as the default in &lt;strong&gt;B&lt;/strong&gt;.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579492331685-O064VLNXXH0KK00ZBW01/ke17ZwdGBToddI8pDm48kFykgoVIAvN21zI7e3ZvRtN7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1UUFFISoLU0OLmOOl3H8mgJSAyHwo5EUI-hEXq-oQKGbz7zs2yPjc1ECvpa5Zm_kMqw/table+1.png?format=1500w&quot; alt=&quot;table 1.png&quot;&gt;
In this view, section number and instructor are emphasized. However, referring back to what I learned from users, many other factors (meeting time, section type), were just as—if not more—important to them.&lt;/p&gt;
&lt;p&gt;I was also surprised to learn that users found it difficult to locate instructor name, although it was the most visually emphasized parameter. To resolve this confusion, I added icons to label each parameter. Additionally, I moved the instructor quality badge next to instructor name and moved meeting time next to meeting place.&lt;/p&gt;
&lt;p&gt;I adjusted the table to display the full course code (not just the section number) in bold, since users enter the full code when they register for courses on Penn InTouch.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1579492403968-E60ICEBVH6ERNVCMNNS6/ke17ZwdGBToddI8pDm48kFykgoVIAvN21zI7e3ZvRtN7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1UUFFISoLU0OLmOOl3H8mgJSAyHwo5EUI-hEXq-oQKGbz7zs2yPjc1ECvpa5Zm_kMqw/table+2.png?format=1500w&quot; alt=&quot;table 2.png&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Mock Schedules&lt;/h3&gt;
&lt;p&gt;After users add course sections to the cart, they can then build mock schedules with the added sections.&lt;/p&gt;
&lt;h4&gt;Mock schedule management&lt;/h4&gt;
&lt;p&gt;In the current interface, all of the mock schedule functionalities are collectively hidden in a dropdown in the navigation bar.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580232120219-1VQ7ANXFLRGBBHNZNXF5/ke17ZwdGBToddI8pDm48kOkyplAM1q1BXV9tbDhLPoFZw-zPPgdn4jUwVcJE1ZvWQUxwkmyExglNqGp0IvTJZamWLI2zvYWH8K3-s_4yszcp2ryTI0HqTOaaUohrI8PIs0dcfHBkwnby0Ryt2yBQh_4J59-c0RtA_dnuCJYjJik/schedule+opt+old.png?format=1500w&quot; alt=&quot;schedule opt old.png&quot;&gt;
To increase the visual prominence and accessibility of these options, I first experimented with displaying all the functionalities across the top of the schedule.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580234311877-3JAMJTFC3A1EOMZJJ833/ke17ZwdGBToddI8pDm48kLfA37Wbyn-WA3XEf2_wcG0UqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dvotuuaJLFmnXCbIuM-VsWKqbr_0XeixLVzdW8iqEBZXCjLISwBs8eEdxAxTptZAUg/mock+1.png?format=1500w&quot; alt=&quot;mock 1.png&quot;&gt;
However, I found it overwhelming and unhelpful see all the features all the time. I decided that a dropdown of some sort would be necessary to organize the features.&lt;/p&gt;
&lt;p&gt;To better organize the mock schedule features, I categorized them based on their use cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Clear **/&lt;/strong&gt; import &lt;strong&gt;/&lt;/strong&gt; download** (used during or after the creation of new mock schedules) are placed above the current mock schedule, displayed while the user is viewing the schedule in view.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;New **/&lt;/strong&gt; rename &lt;strong&gt;/&lt;/strong&gt; duplicate &lt;strong&gt;/&lt;/strong&gt; delete** (used while editing or creating mock schedules) are condensed in a dropdown, displayed when the user hovers over a specific schedule.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580238692566-D7KBG0Z44RC8J8F0D06E/ke17ZwdGBToddI8pDm48kLfA37Wbyn-WA3XEf2_wcG0UqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dvotuuaJLFmnXCbIuM-VsWKqbr_0XeixLVzdW8iqEBZXCjLISwBs8eEdxAxTptZAUg/mock+2.png?format=1500w&quot; alt=&quot;mock 2.png&quot;&gt;
From user testing, I learned that many users did not know how to make multiple mock schedules in this design, since the action was nested in a small arrow next to the title of the mock schedule.&lt;/p&gt;
&lt;p&gt;Instead of using the mock schedule name as the section header, I decided to use “Mock Schedule” as the default header. I increased the size and prominence of the dropdown by placing the mock schedule name beside it. I also added a new schedule button outside this dropdown.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580238746408-H5EDUC2YPGXYCXXIV2GP/ke17ZwdGBToddI8pDm48kLfA37Wbyn-WA3XEf2_wcG0UqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dvotuuaJLFmnXCbIuM-VsWKqbr_0XeixLVzdW8iqEBZXCjLISwBs8eEdxAxTptZAUg/mock+3.png?format=1500w&quot; alt=&quot;mock 3.png&quot;&gt;
We plan to do A/B testing to see whether this design will increase creation of multiple mock schedules.&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Schedule statistics&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;The team lead and two developers were working on implementing relevant statistics for each mock schedule. I decided how to best visualize this data.&lt;/p&gt;
&lt;p&gt;For the course review metrics (course quality, course difficulty, instructor quality, average workload), I explored two alternatives.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580238828292-9XX692SKSGNV0YDUK4ZJ/ke17ZwdGBToddI8pDm48kGNJtdcY41qO1m4aS9Xrr6AUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dp5A3VPg13TzyTLLQsYdAcaCE3zxEF-tMFyVHkqj5CWJCjLISwBs8eEdxAxTptZAUg/stat+exploration.png?format=1500w&quot; alt=&quot;stat exploration.png&quot;&gt;
&lt;strong&gt;A&lt;/strong&gt; shows the number only, with arrows to reflect changes. **B **shows the number with a circular progress wheel. At first, I thought the wheel might be providing redundant information, but I learned that users found it helpful to see changes in the wheel after adding/removing sections from their schedule.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580238992415-SLOGE8BECTEKR7CXRI2I/ke17ZwdGBToddI8pDm48kAhbipYCPi3TlrBi397t6doUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2dti914ZaVCK5HhXwhiyT68dXc2IoKSydTSOvGghEEPhVCjLISwBs8eEdxAxTptZAUg/stats.png?format=1500w&quot; alt=&quot;stats.png&quot;&gt;&lt;/p&gt;
&lt;h2&gt;&lt;/h2&gt;
&lt;p&gt;REFINING THE DETAILS&lt;/p&gt;
&lt;h3&gt;Integration with the Penn Courses ecosystem&lt;/h3&gt;
&lt;p&gt;One of the key business goals for this redesign was to better integrate Penn Course Plan with the rest of the Penn Course products.&lt;/p&gt;
&lt;h4&gt;Penn Course Alert&lt;/h4&gt;
&lt;p&gt;Penn Course Alert allows users to sign up for email and text alerts for closed sections. In the redesign, the bell symbol in the section details view indicates the section is closed.&lt;/p&gt;
&lt;p&gt;Clicking the bell redirects users to Penn Course Alert, with the fields auto-populated with the section information. A blue bell indicates that a section is closed and the user is currently already signed up for alerts.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580240709385-FQ2ASQ5ECGHCYL1C2CCB/ke17ZwdGBToddI8pDm48kNstFJImlE69zZ6yUBxutEIUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnAzMMODFWJ5wXI4pSYaR00hjBN0agi9nXXq6JgF1RZnu0u9nFcJfNwnsT6GPNjVPDg/pca+flow.png?format=1500w&quot; alt=&quot;pca flow.png&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Penn Course Review&lt;/h4&gt;
&lt;p&gt;Penn Course Review provides extensive student rating data throughout the years. Because this data did not fit within the space and technical constraints of Penn Course Plan, the Penn Labs directors made the executive decision to keep the two products separate.&lt;/p&gt;
&lt;p&gt;I added a button inside the course overview as an entry point for the corresponding Penn Course Review page.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580240754912-VSBZHYZ18SL0F7E13Y4U/ke17ZwdGBToddI8pDm48kNstFJImlE69zZ6yUBxutEIUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnAzMMODFWJ5wXI4pSYaR00hjBN0agi9nXXq6JgF1RZnu0u9nFcJfNwnsT6GPNjVPDg/pcr+flow.png?format=1500w&quot; alt=&quot;pcr flow.png&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Improving clarity&lt;/h2&gt;
&lt;h3&gt;&lt;strong&gt;Empty states&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;I created branded empty state illustrations for each section and provided instructional cues. The copy encourages engagement with the product and reduces confusion.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580677783778-FOUIB8EKZ9MEV4151M3W/ke17ZwdGBToddI8pDm48kNSqDleq7bHSZc-xq6aRYQt7gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z4YTzHvnKhyp6Da-NYroOW3ZGjoBKy3azqku80C789l0h1yvUMVfVaSHKnWSjKaKj6qtUcCwJq445UTi6b1UqWCNLINrcpf3KRGeNa9K-8jVQ/empty+state.png?format=1500w&quot; alt=&quot;empty state.png&quot;&gt;&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580677835267-5D5RZMZCZ64R16MO2J7K/ke17ZwdGBToddI8pDm48kCLEc37XOlu54GKfsaPT_9oUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYy7Mythp_T-mtop-vrsUOmeInPi9iDjx9w8K4ZfjXt2di8oWEKbt9nUzEOU0CDGnrZgvr_Ajy2F6VsaDmqNVjDZCjLISwBs8eEdxAxTptZAUg/illos.png?format=1500w&quot; alt=&quot;illos.png&quot;&gt;&lt;/p&gt;
&lt;h3&gt;&lt;strong&gt;Tool tips&lt;/strong&gt;&lt;/h3&gt;
&lt;p&gt;In addition to empty states, providing guiding information through tool tips clarifies any ambiguities and informs users of any errors.&lt;/p&gt;
&lt;p&gt;For example, to ensure users add all the required sections for a course to their schedule, there is a warning icon with a tooltip to let users know if they’re missing the co-requisite section.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580678517521-CR53H62E9RKVSMGUK5ZV/ke17ZwdGBToddI8pDm48kLBpvNp0fn8PZILsmLsDTz17gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1UZo_9xHDcN894amj1VDBYYGiJBiLXbDPrLqg2VFqjfhEMW9u6oXQZQicHHG1WEE6fg/tooltip.png?format=1500w&quot; alt=&quot;tooltip.png&quot;&gt;
When the tool tip is clicked, users have the option to add missing sections in the cart directly to the schedule. If the section is not yet in the cart, the section gets added to both the cart and the schedule.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580678549126-VWCHXT31BZQVC3AVC7QB/ke17ZwdGBToddI8pDm48kLBpvNp0fn8PZILsmLsDTz17gQa3H78H3Y0txjaiv_0fDoOvxcdMmMKkDsyUqMSsMWxHk725yiiHCCLfrh8O1z5QPOohDIaIeljMHgDF5CVlOqpeNLcJ80NK65_fV7S1UZo_9xHDcN894amj1VDBYYGiJBiLXbDPrLqg2VFqjfhEMW9u6oXQZQicHHG1WEE6fg/tooltip2.png?format=1500w&quot; alt=&quot;tooltip2.png&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Making it responsive&lt;/h2&gt;
&lt;p&gt;I designed mobile and tablet layouts to make searching and planning accessible on devices and windows of all sizes. I decided that a tabbed navigation would be the best way to navigate through the search, cart, and schedule on smaller browser windows.
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580678659668-50EOZ0A9MWQD7IER1JT9/ke17ZwdGBToddI8pDm48kBOpWS5gX6INY-PUGzxr2FIUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnGZIEpBabk_LqqiIQbmBMLjD-FIRsvB4suMknYKStT68oFoAC5Ip_lNIcer8VrtvQw/mobile.png?format=1500w&quot; alt=&quot;mobile.png&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h1&gt;Reflect&lt;/h1&gt;
&lt;h2&gt;IMPACT&lt;/h2&gt;
&lt;h3&gt;By the numbers&lt;/h3&gt;
&lt;p&gt;We successfully launched this redesign late October 2019, prior to the advanced course registration deadline at Penn.&lt;/p&gt;
&lt;p&gt;The product garnered nearly &lt;strong&gt;2,000 unique users&lt;/strong&gt; within a week of launching, with nearly all users reporting that Penn Course Plan is more user friendly than PennInTouch, the current course registration software.&lt;/p&gt;
&lt;p&gt;Throughout the spring course registration process, there have been &lt;strong&gt;8,000 users&lt;/strong&gt;, many participating in multiple sessions.&lt;/p&gt;
&lt;h3&gt;Testimonials&lt;/h3&gt;
&lt;p&gt;My team and I received many personal messages from friends, expressing their gratitude to Penn Labs for making this product. We also received several testimonials from our anonymous feedback form at the bottom of the site:
&lt;img src=&quot;https://images.squarespace-cdn.com/content/v1/5c7d57619d414911f2272819/1580232871132-V9AQHS354O7UOL5DYQGL/ke17ZwdGBToddI8pDm48kPMdyJQtZHBJrv45QVVu4BgUqsxRUqqbr1mOJYKfIPR7LoDQ9mXPOjoJoqy81S2I8N_N4V1vUb5AoIIIbLZhVYwL8IeDg6_3B-BRuF4nNrNcQkVuAT7tdErd0wQFEGFSnLeKVsCGoBW-oUGIeKkDdra_MdKqDJykL_R8WOmsPLDyZUlGeT2JugDEtEr0r_f-Gw/testimonials.jpg?format=1500w&quot; alt=&quot;testimonials.jpg&quot;&gt;&lt;/p&gt;
&lt;h2&gt;LEARNINGS&lt;/h2&gt;
&lt;h3&gt;Challenges&lt;/h3&gt;
&lt;p&gt;This was my first major product design project, and I definitely learned a lot while working with my team to execute the design. A few of the key challenges I faced include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;setting aside my own assumptions about user behavior and needs&lt;/li&gt;
&lt;li&gt;making significant alterations based on recurring user feedback&lt;/li&gt;
&lt;li&gt;fitting a large amount of information within a single page, no-scroll app&lt;/li&gt;
&lt;li&gt;accounting for the many potential edge cases&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Next Steps&lt;/h2&gt;
&lt;p&gt;As new technical constraints, user concerns, and business goals are uncovered, we’re continuing to fix bugs, enhance functionality, and identify areas of improvement. Some of the next steps the team and I have planned include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;conduct further user research to understand the full course planning cycle and timeline&lt;/li&gt;
&lt;li&gt;use A/B testing to see what designs increase the creation of multiple schedules&lt;/li&gt;
&lt;li&gt;modify the course cart deletion process to reduce confusion&lt;/li&gt;
&lt;li&gt;make it easier to compare metrics across schedules&lt;/li&gt;
&lt;li&gt;add course planning worksheets and 4 year academic planner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Moving forward, we will be iterating off feedback and making informed design decisions based on user data. We will be expanding to include new features that allow for long-term planning. I’m looking forward to diving deeper into the course planning problems students at Penn face and working with my team to address those pain points.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Designing for Penn Labs has been an extremely rewarding and educational experience. As a student designing a product for other students, I had the opportunity to learn about the course planning pain points and experiences for a wide variety of students.&lt;/p&gt;
&lt;p&gt;Working closely with several software engineers and business developers taught me how to design based on user insights, technical constraints, and business goals.&lt;/p&gt;
&lt;p&gt;This redesign project was my first time working through the entire product cycle, from ideation to delivery. I can’t wait to continue improving and expanding Penn Course Plan as we continue to hear feedback from the Penn community!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Penn Course Review Technicalities]]></title><description><![CDATA[This article was written by Brandon Lin. This article is a continuation of a previous article about Penn Course Review’s new redesign. See…]]></description><link>https://pennlabs.org/blog/pcr-tech-18</link><guid isPermaLink="false">https://pennlabs.orgblog/pcr-tech-18</guid><pubDate>Tue, 28 Aug 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This article was written by &lt;a href=&quot;https://github.com/esqu1&quot;&gt;Brandon Lin&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This article is a continuation of a previous article about Penn Course Review’s new redesign. See &lt;a href=&quot;/blog/pcr-makeover-18&quot;&gt;here&lt;/a&gt; for that article.&lt;/p&gt;
&lt;h2&gt;&lt;strong&gt;A monolithic project&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt;Maintaining Penn Course Review was never an easy task. Being one of Penn Labs’ most well-known products and having one of our largest codebases, working on the project was a massive undertaking. Nevertheless, the fantastic developers at Penn Labs helped make the new makeover possible.&lt;/p&gt;
&lt;p&gt;This article serves to highlight some of the technicalities of the new makeover.&lt;/p&gt;
&lt;h2&gt;About Penn Course Review&lt;/h2&gt;
&lt;p&gt;Penn Course Review is primarily written in Python, using the Django framework. Both the front end and the back end rely on this framework, while all of the data is stored in a MySQL database.&lt;/p&gt;
&lt;p&gt;We’ll go over the front end and the back end components separately here.&lt;/p&gt;
&lt;h2&gt;Front End&lt;/h2&gt;
&lt;p&gt;We’re redesigning the Penn Course Review experience to make it easier and faster for you to find the courses you need.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/b4d83a9c9cd764ec04a03a8ae5e17f1d/bef84/pcr18-cis120.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 41%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAICAIAAAB2/0i6AAAACXBIWXMAAAsTAAALEwEAmpwYAAAA60lEQVQY03VR7UrEMBDs+7+NL+C/+ysIIigIInfSKtemX5tks5vcbCpycnUYAtvsTmcnDQXKWVSziILMKcZEMcWEKuv/TJya43F8+xiicqkQkRC5n6aZ1hB/4L1X1fIXOefm8YnvDu/t8rXVODWX87mfxlEkMXMIJlJuYMPPr3T/8tDO30VL2iA6ODcvi/eBvCcy1iXyNVE3zrnT6bOt6LpuGHpmWVYNAf2SKrEhPF3TMsKw5aQ1LGuyxfDnaVq9j/AMw7C9rbNj+/YCIkSrQlMFS0Ci7MGG7T1y+SWk8IUIkZtfBGAZ7D0V2i4a4NS4I53d2wAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;pcr18 cis120&quot;
        title=&quot;pcr18 cis120&quot;
        src=&quot;/static/b4d83a9c9cd764ec04a03a8ae5e17f1d/5a190/pcr18-cis120.png&quot;
        srcset=&quot;/static/b4d83a9c9cd764ec04a03a8ae5e17f1d/772e8/pcr18-cis120.png 200w,
/static/b4d83a9c9cd764ec04a03a8ae5e17f1d/e17e5/pcr18-cis120.png 400w,
/static/b4d83a9c9cd764ec04a03a8ae5e17f1d/5a190/pcr18-cis120.png 800w,
/static/b4d83a9c9cd764ec04a03a8ae5e17f1d/c1b63/pcr18-cis120.png 1200w,
/static/b4d83a9c9cd764ec04a03a8ae5e17f1d/29007/pcr18-cis120.png 1600w,
/static/b4d83a9c9cd764ec04a03a8ae5e17f1d/bef84/pcr18-cis120.png 2535w&quot;
        sizes=&quot;(max-width: 800px) 100vw, 800px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;Page Size&lt;/h3&gt;
&lt;p&gt;We thought about how inconvenient it was to scroll through a really long page to find a professor. With jQuery DataTables, we were able to condense most of the information down into a simple, intuitive format that lets you scroll through professors with ease.&lt;/p&gt;
&lt;p&gt;This also led us to put the individual ratings and comments in a separate card, so that you don’t have to constantly scroll in order to view different ratings between professors and courses.&lt;/p&gt;
&lt;h2&gt;Back End&lt;/h2&gt;
&lt;p&gt;Regarding the back end side, most of our work involved cleaning up legacy code that ran on an old version of Django and providing more documentation to the existing API endpoints. We also introduced Sentry error logging to make it easier for future developers of the project to work on it more easily.&lt;/p&gt;
&lt;h3&gt;API Refactor&lt;/h3&gt;
&lt;p&gt;We refactored the majority of the API to conform to Django standards and make the API more RESTful. With the new Django update, we had to conform to these new standards with new endpoints and better code style. Previously, many endpoints were nonintuitive and didn’t follow these standards. We added several endpoints that, for example, allow you to fetch all history about a course.&lt;/p&gt;
&lt;h3&gt;DigitalOcean Migration&lt;/h3&gt;
&lt;p&gt;We moved all of our production code to DigitalOcean from an old server that sat in the STWing area in King’s Court. We wanted to make our service more reliable and migrating everything to DigitalOcean gave us the scalability and control that we needed. The old server suffered from a majority of outages and disk breakages that would render the server inaccessible, and we decided that moving to DigitalOcean would be the best bet.&lt;/p&gt;
&lt;h3&gt;Massive Data&lt;/h3&gt;
&lt;p&gt;The big challenge that Penn Course Review has faced over the years is how to deal with the massive dataset containing course and professor ratings/comments. With a ton of ratings, loading a single webpage and compiling all results from the database for that webpage would take quite some time.&lt;/p&gt;
&lt;p&gt;Traditionally, the solution has been to generate static webpages for each course and professor separately (in a process that takes about 9 hours), so when users fetch a webpage, it’s as simple as getting a pre-generated HTML file.&lt;/p&gt;
&lt;p&gt;Obviously this wasn’t very storage friendly and severely non-scalable if we ever want to make any quick changes/bug changes to the website. We were looking for a way to allow for easy website changes while keeping the user experience as fast as it was previously.&lt;/p&gt;
&lt;p&gt;The best way to mitigate between these to was to configure our server to cache the page generation whenever a new page request comes in; this way, we don’t hog server space and we can still deliver pages quickly for very popular courses (such as MATH 114). The cache is set to reset every day. This way, we can seamlessly make changes to the site while being able to give the same user experience.&lt;/p&gt;
&lt;h3&gt;Shibboleth&lt;/h3&gt;
&lt;p&gt;We also transitioned over from Penn’s old authentication system, Cosign, to their new system, Shibboleth.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Thanks so much to the Penn Course Review team and all of the developers and PM’s at Labs for making this revamp possible; special shoutout to Tiffany Chang and Josh Doman for being fantastic directors and mentors for this project.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The Course Review Got A Makeover]]></title><description><![CDATA[This article was written by Tiffany Chang. Meet the new Penn Course Review. 🚶‍Down memory lane The student-run Penn Course Review has…]]></description><link>https://pennlabs.org/blog/pcr-makeover-18</link><guid isPermaLink="false">https://pennlabs.orgblog/pcr-makeover-18</guid><pubDate>Mon, 27 Aug 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;em&gt;This article was written by &lt;a href=&quot;http://tifchang.com&quot;&gt;Tiffany Chang&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Meet the new Penn Course Review.&lt;/p&gt;
&lt;h3&gt;🚶‍Down memory lane&lt;/h3&gt;
&lt;p&gt;The student-run &lt;a href=&quot;http://penncoursereview.com&quot;&gt;Penn Course Review&lt;/a&gt; has served as a valuable guide for course selection since the 1960s. From paper book to web app, it continues to provide course statistics to better inform students during course selection. Penn Course Review was a student club motivating insight-driven course selection. With even more energy, Penn Course Review is now developed and managed by us, &lt;a href=&quot;http://pennlabs.org&quot;&gt;Penn Labs&lt;/a&gt;, a group of students passionate about solving problems at Penn through technology.&lt;/p&gt;
&lt;p&gt;In 2010, Penn Course Review was launched with a sleek, simple, and sexy design. How sexy was it? Let’s take a look at how we’ve been using it.&lt;/p&gt;
&lt;h3&gt;📊 Quick stats&lt;/h3&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 800px; &quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/5a5971d1f86feafa61107e7357a5fb83/d6853/pcr18-stats.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 51.5%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAIAAAA7N+mxAAAACXBIWXMAAAsTAAALEwEAmpwYAAABDElEQVQoz41QXW/CMAzk//+4Pe5hTEWgDtaStknTJk78kbnAGJPKtHuwHNtnX25TviEiGRmSQCJmQuKUS0YtMxFpgih8wZ2yKT+Qj1PY7uK50za7EV7f/KkNzAiQt5XXrq5ZJ2t1DpAysxSd0WsAgFnfrNchxnu+TpY8FKgFPpmiMV3f9xqHYei6zlrXtq0miLhC1pWz3bvmBf27MOwPh6qq6rq21ipHFzVNY4x5SlbDEqpJi+zyD/wiA8TJj9Pk5YrLD5fv8GKBsNAfhuloZY9IVI+tT8Gl6ehNJtzZkw5oCzCVVcOUqR73wSGhDT5kmHN0cUqYu8nq6n52mstTMlG56bxKlpvsh/go+wt6GUmeX1Yx7QAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;pcr18 stats&quot;
        title=&quot;pcr18 stats&quot;
        src=&quot;/static/5a5971d1f86feafa61107e7357a5fb83/5a190/pcr18-stats.png&quot;
        srcset=&quot;/static/5a5971d1f86feafa61107e7357a5fb83/772e8/pcr18-stats.png 200w,
/static/5a5971d1f86feafa61107e7357a5fb83/e17e5/pcr18-stats.png 400w,
/static/5a5971d1f86feafa61107e7357a5fb83/5a190/pcr18-stats.png 800w,
/static/5a5971d1f86feafa61107e7357a5fb83/c1b63/pcr18-stats.png 1200w,
/static/5a5971d1f86feafa61107e7357a5fb83/29007/pcr18-stats.png 1600w,
/static/5a5971d1f86feafa61107e7357a5fb83/d6853/pcr18-stats.png 3070w&quot;
        sizes=&quot;(max-width: 800px) 100vw, 800px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h3&gt;🤷‍ But it’s not perfect&lt;/h3&gt;
&lt;p&gt;As time passed, we received comments, critiques, and complaints. No worries, we heard you, and we’re so glad you took the time to tell us what you wanted. After reviewing years of feedback, hearing your complaints in Van Pelt, and watching friends struggle with clunky excel sheets to optimize course load, we realized there was a lot of work to do. We decided to focus 2017 on building a better experience around you.&lt;/p&gt;
&lt;h3&gt;👋 Meet the new Penn Course Review&lt;/h3&gt;
&lt;p&gt;We’re so excited to finally announce the new Penn Course Review, a new experience with the same promise. With added features, simplified views, and (for our technically savvy folks) a new stack for performance and efficiency optimization, we hope you enjoy it as much as we enjoyed building it for you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;✨ New UI:&lt;/strong&gt; We’ve recently updated our design guide and have begun syncing our product designs across the board while maintaining key Penn Course Review interactions. We hope you enjoy the simple, sweet, and complete interface.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🛒 Course cart:&lt;/strong&gt; Add courses to your cart, compare, contrast, and get insights on your entire semester’s course load. Include and exclude classes to see how your ratings change with and without a course.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🔍 Search within course or professor:&lt;/strong&gt; We’ve added a search bar within the course table to help you find the specific course/professor/anything you’re looking for.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;👩‍🏫 Department view:&lt;/strong&gt; Trying to decide which FNAR course to take? Take a look at the department view and get a cross-section of all FNAR courses. Use our handy quick course comparer to see your options side-by-side.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🚨 Get alerts:&lt;/strong&gt; It’s easier than ever to stay updated on a course’s status. Penn Course Alert is now connected with Penn Course Review in just one click. Check if a course is open, and if not, be the first to know when it opens.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;🎨 Color calibration:&lt;/strong&gt; Ratings are color coded.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;💛: &amp;#x3C; 2&lt;/li&gt;
&lt;li&gt;💜: &amp;#x3C; 3&lt;/li&gt;
&lt;li&gt;💚: ≥ 3&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;☁️ Cloud:&lt;/strong&gt; We’ve migrated Penn Course Review from a physical server to the cloud to optimize speed and performance.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;For a technical deep-dive on the update, see this &lt;a href=&quot;/blog/pcr-tech-18&quot;&gt;article&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;🙏 Special thanks to the team&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;V.2018&lt;/strong&gt;: &lt;a href=&quot;https://github.com/esqu1&quot;&gt;Brandon Lin&lt;/a&gt; (PM/Backend Developer), &lt;a href=&quot;https://github.com/orgs/pennlabs/people/cassandrali&quot;&gt;Cassandra Li&lt;/a&gt; (Frontend Developer), &lt;a href=&quot;https://github.com/ezwang&quot;&gt;Eric Wang&lt;/a&gt; (Fullstack Developer),&lt;a href=&quot;https://github.com/VinaiRachakonda&quot;&gt; &lt;/a&gt;&lt;a href=&quot;https://github.com/joshdoman&quot;&gt;Josh Doman&lt;/a&gt; (Director), &lt;a href=&quot;https://github.com/sknop8&quot;&gt;Suzanne Knop&lt;/a&gt; (Frontend Developer), &lt;a href=&quot;http://tifchang.com&quot;&gt;Tiffany Chang&lt;/a&gt; (Director/Designer), &lt;a href=&quot;https://github.com/VinaiRachakonda&quot;&gt;Vinai Rachakonda&lt;/a&gt; (Backend Developer), &lt;a href=&quot;https://github.com/ymann&quot;&gt;Yonah Mann&lt;/a&gt; (Backend Developer).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Our legacy&lt;/strong&gt;: &lt;a href=&quot;https://github.com/adelq&quot;&gt;Adel Qalieh&lt;/a&gt;, &lt;a href=&quot;https://github.com/adamdom&quot;&gt;Adam Domingoes&lt;/a&gt;, &lt;a href=&quot;https://github.com/AlexeyMK&quot;&gt;Alexey Komissarouk&lt;/a&gt;, &lt;a href=&quot;https://github.com/Ceasar&quot;&gt;Ceasar Bautista&lt;/a&gt;, &lt;a href=&quot;https://github.com/dlakata&quot;&gt;David Lakata&lt;/a&gt;, &lt;a href=&quot;https://github.com/derekjobst&quot;&gt;Derek Jobst&lt;/a&gt;, &lt;a href=&quot;http://Greg%20Terrono&quot;&gt;Greg Terrono&lt;/a&gt;, &lt;a href=&quot;https://github.com/kylehg&quot;&gt;Kyle Hardgrave&lt;/a&gt;, &lt;a href=&quot;https://github.com/mattparmett&quot;&gt;Matt Parmett&lt;/a&gt;, &lt;a href=&quot;https://github.com/nopjia&quot;&gt;Nop Jiarathanakul&lt;/a&gt;, &lt;a href=&quot;https://github.com/pbjr23&quot;&gt;Prakhar Bhandari&lt;/a&gt;, &lt;a href=&quot;http://www.reikayoshino.com/&quot;&gt;Reika Yoshino&lt;/a&gt;, &lt;a href=&quot;https://github.com/sumitshyamsukha&quot;&gt;Sumit Shyamsukha&lt;/a&gt;, &lt;a href=&quot;https://github.com/VivekPanyam&quot;&gt;Vivek Panyam&lt;/a&gt;, &lt;a href=&quot;https://github.com/yefim&quot;&gt;Yefim Vedernikoff&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[It's so FLUFFY.]]></title><description><![CDATA[X  is an integrated services provider for an elite university in the  United States. Formed originally as a conglomerate of various  individuals working on independent projects to enhance the lives of  university students, the group began to formally affiliate itself with  the school name in 2010.]]></description><link>https://pennlabs.org/blog/its-so-fluffy</link><guid isPermaLink="false">https://pennlabs.orgblog/its-so-fluffy</guid><pubDate>Sat, 24 Mar 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Background—&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;X  is an integrated services provider for an elite university in the  United States. Formed originally as a conglomerate of various  individuals working on independent projects to enhance the lives of  university students, the group began to formally affiliate itself with  the school name in 2010.&lt;/p&gt;
&lt;p&gt;For  much of its founding years, X sustained 10 or so employees. Directors  were sourced externally to not interfere with the technical work. At the  time, the developers themselves were more interested in creating new  projects in an effort to jump start a new organization off its feet as  opposed to considering the various management details of sustaining an  established one.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Near collapse —&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;A  year ago, a sudden drop in participation shoved X to the brink of  survival, and the task fell on the shoulders of the remaining members to  keep the organization running.&lt;/p&gt;
&lt;p&gt;Faced  with the prospects of having to completely disband, they broke down the  most prominent concerns that had beleaguered their beloved group.&lt;/p&gt;
&lt;p&gt;The  biggest problems that had arisen was a disconnect between products and  their purposes. Since X was founded by students joining together to work  on their common, university-related side projects, the organization had  been a place for developers to spend their free time experimenting.  However, as the key members left, the flow of new project ideas slowed  and along with it, focus and motivation.&lt;/p&gt;
&lt;p&gt;Finally,  there was one more major problem: employee pay. Paying developers had  created a budget limit to bring in talent. Furthermore, their work had  resulted in a culture of working-for-pay, which at times clashed with  working for the benefit of students.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Growth —&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Since  the organization needed people — and a lot more of them — two members  decided to channel their revival efforts at first through recruitment.  They knew that more labor didn’t always lead to better results so they  were meticulous in the people they brought on board the following  semester.&lt;/p&gt;
&lt;p&gt;Members  were chosen by specific skill sets and passion for improving the Penn  community. Employee pay was abolished. Once hired, new members were  placed onto the product teams where those exact skill sets were most  needed. Each team would have its own set of back-end, front-end  developers and designers. The back-end worked on the API and functions  of the product while front-end and designers worked closely together to  bring about an engaging user experience. The two co-directors each led  their own product teams as well as played the director role of making  sure each project progressed steadily.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Looking beyond —&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;With  several well-established products on their way and respective teams  established, co-directors A and B once again looked to enhance the labor  force of the group. Traditionally, members had always been technical in  nature and purely focused on product creation. Thus, one of the  problems that the organization has faced from its outset was a lack of  marketing and commercialization. Products were often inconspicuously  released without any promotion or advertising and the organization was  dormant on social media. Many students remained unaware that X is  responsible for the applications and services they used daily.&lt;/p&gt;
&lt;p&gt;Realizing  they had access to an abundance of consumer-minded talent for  operational decision making and marketing, the co-directors decided  boldly to recruit the organization’s inaugural Business Development (BD)  team.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fall of BD —&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;However, as they soon found out, merely &lt;em&gt;having&lt;/em&gt; a Business Development team is not enough. Throughout the semester,  they watched as the BD team struggled time after time to integrate with  the other product teams and find purpose. The isolated nature of the  product teams along with fuzzy launch deadlines created an awkward,  out-of-place and out-of-work situation for the BD group even though  there was actually so much for them to do. Marketing endeavors that BD  tried to take on turned out uncoordinated and sloppy. In fact, members  within the organization itself were even unclear of the BD role.  Something needed to change …&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;So, this “X” — a Crunchbase startup looking to scale? Not quite (yet). PennLabs? Yes.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Perhaps  a little ashamed of the fact, but I think it would be fair to say that I  have always been easily annoyed with “management-like” readings (which  is quite frequent given I attend a business school). I had my two  reasons: 1) It seemed as if in an odd way, everything I read *I already knew *and  2) I didn’t think management could be “learned” — it comes with  experience, and innate intuition. Those that are more perceptive might  find it comes naturally, and well those that are less so might have to  stumble over a few extra hurdles. But, two incidents this winter break  changed my view of the “fluffy” stuff, as it is so often called,  beginning with Sheryl Sandberg’s &lt;em&gt;Lean In.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Though  incredibly fond of Sheryl Sandberg, I was skeptical of her book at  first. The turning point for me in the book came when she describes the  differences between how men and women take praise. I know that if I am  to congratulate one of my girl friends on their accomplishments, 9 out  of 10 times I can be sure of them to rebut and instead attribute their  success to some external factor like “luck” or “a generous curve.” The  other 1 out of 10 times is a short “thanks” followed by reciprocal  praise of one of my own accomplishments. But, compliment a guy friend  similarly, and I generally expect a confident response along the lines  of “I better do well. I worked so dang hard on that.”&lt;/p&gt;
&lt;p&gt;It  dawned on me that up until the moment Sheryl Sandberg literally put  this problem in front of my face in black and white (size 10, Garamond  font I think?), I may have subconsciously &lt;em&gt;knew&lt;/em&gt; this was happening, but had never truly *recognized *it.  In fact, as Sandberg points out in the book, I had actually  internalized these actions as a societal norm and became a perpetrator  myself! If I complimented a girl on a good grade and she replied along  the lines of “Thanks, I feel like my work paid off ” I probably would  have even thought “wow, how cocky.” While literature on organizational  behavior may at times appear to be “common sense”, we need an extra push  from others to externalize the common sense — hence, we borrow upon &lt;strong&gt;&lt;em&gt;others’&lt;/em&gt;&lt;/strong&gt; incredible insights and experience through&lt;strong&gt;_ reading_&lt;/strong&gt;to reveal to us something once hidden.&lt;/p&gt;
&lt;p&gt;The  second incident occurred on my way back to Penn. I happened to be on  the same flight as Josh Doman, one of the co-directors previously  described. We are in the same management class together this semester,  and neither of us had done the assigned readings yet. We both planned to  do it on the plane.&lt;/p&gt;
&lt;p&gt;I fell asleep.&lt;/p&gt;
&lt;p&gt;Josh didn’t.&lt;/p&gt;
&lt;p&gt;Immediately  coming off the plane, he launched into a passionate rant on how the  readings had inspired him to entirely question the sustainability of  PennLabs: What were our core competencies? How are we sourcing new  ideas? How do we go from innovation to commercialization? What kind of  culture are we perpetrating?&lt;/p&gt;
&lt;p&gt;Standing  there half-awake watching the baggage claim conveyor belt go  round-and-round with Josh buzzing beside me, I realized that there was  no way I could deny the teachability of management. Just four hours  previously, those readings had only been downloaded pdfs, homework to be  done. Four hours later, they came to life and became Josh’s source of  attack to question the entire structure of an organization that he had  worked endlessly to bring back to life.&lt;/p&gt;
&lt;p&gt;As students of management, our job is to find the &lt;em&gt;application&lt;/em&gt;.  The value of the readings isn’t in the text itself, but how they can be  drawn away from the pages to provide a framework for making decisions  in the real-world — it’s this exact intangibility that causes us to term  management as “fluffy.” Akin to studying history or understanding chess  combinations, I can see studying management as a form of what I  consider &lt;em&gt;situational training.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;By  studying others’ experiences and becoming cognizant of certain response  patterns, you can create a competitive advantage for yourself from the  crowd when similar problems arise.&lt;/p&gt;
&lt;p&gt;So yes, the fluffy stuff is important to &lt;em&gt;learn.&lt;/em&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;Moving forward —&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Since  that plane ride, Josh has completely rethought the organization of  Labs. He and Tiffany Chang (the other co-director!) together have began  implementing significant structural changes to Labs.&lt;/p&gt;
&lt;p&gt;Starting  this semester, Labs will consist of a Board of Directors with 6 seats,  made up of two co-directors and directors of internal, external,  finance, and marketing. Though initially the four director positions  will be filled by the to-be dissolved BD team, in the future, those  positions will go to internal technical designers or product developers.  Such a vertical and promotional structure is to encourage developers to  take on more leadership and responsibility in hopes of laying the  foundation for a sustainable management culture where decision-making  didn’t fall entirely on the co-directors.&lt;/p&gt;
&lt;p&gt;Teams  themselves will no longer be strictly organized around products, but  rather functionally, with a back-end API team and a team of designers.  This structure allows for two meaningful improvements: 1) In flexibility  — members will be able to work on a diverse array of projects and  interact with different people, increasing club cohesiveness and culture  2) In efficiency —many projects use similar API’s and design logos so a  centralized system of API development and design works to eliminate  repetitive work.&lt;/p&gt;
&lt;p&gt;In  2014, Facebook changed its motto from “Move Fast and Break Things” to  “Move Fast with Stable Infra(structure)” (A quick Google search will  reveal why ‘structure’ is in parenthesis). One could say we are  undergoing a similar change. Though Zuckerberg used infrastructure to  describe the stability and “bug-free-ness” of code, in the context of  Labs, I like to think of infrastructure as *organizational *infrastructure. We are rebuilding — to prevent against another sudden collapse and so that we are officially &lt;em&gt;ready&lt;/em&gt; to take on more quantity and complexity, in terms of both projects and people.&lt;/p&gt;
&lt;p&gt;We  joke around nostalgically that we’ve gone “corporate” but the truth is  no organization wanting to grow stays a small, flat structure of people  forever. The idealistic notion of tech groups as being made up of a few  geeky, chill friends coding for fun must give way to some notion of a  corporation structure at some point.&lt;/p&gt;
&lt;p&gt;Though  it will most likely be messy this next year since we are clearly no  experts in growing an organization, or even running one for that matter,  I am excited for the changes to come. And so should the Penn community.  A more efficient Labs only means better and more services for students.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;On another note …&lt;/p&gt;
&lt;p&gt;This. Scene. Was. ICONIC.
Look at that &lt;strong&gt;fluffy unicorn&lt;/strong&gt;. (Multiple puns intended?)
Disclaimer:  this post is merely a reflection of thoughts from my 19-year old self. I  have no intention nor the expertise to impose my perspectives on  anyone.&lt;/p&gt;
&lt;p&gt;*&lt;em&gt;photo credits: _[&lt;/em&gt;&lt;a href=&quot;http://www.managers.org.uk/insights/news/2017/june/a-management-manifesto-for-the-uk-fixing-the-84bn-productivity-gap_&quot;&gt;http://www.managers.org.uk/insights/news/2017/june/a-management-manifesto-for-the-uk-fixing-the-84bn-productivity-gap_&lt;/a&gt;](&lt;a href=&quot;http://www.managers.org.uk/insights/news/2017/june/a-management-manifesto-for-the-uk-fixing-the-84bn-productivity-gap&quot;&gt;http://www.managers.org.uk/insights/news/2017/june/a-management-manifesto-for-the-uk-fixing-the-84bn-productivity-gap&lt;/a&gt;)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The Problem with Problems and what Penn Labs is all About]]></title><description><![CDATA[I don’t know how often everyone here cooks but think about what happens when you pour oil into a pan. Due to a stubborn property of gravity, there’s always that extra drop that flows down the side of the container.]]></description><link>https://pennlabs.org/blog/the-problem-with-problems</link><guid isPermaLink="false">https://pennlabs.orgblog/the-problem-with-problems</guid><pubDate>Thu, 02 Nov 2017 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I don’t know how often everyone here cooks but think about what happens when you pour oil into a pan. Due to a stubborn property of gravity, there’s always that extra drop that flows down the side of the container. At my house, we actually always keep a designated paper towel next to the oil jar solely for the purpose of catching this drip.&lt;/p&gt;
&lt;p&gt;You’re probably wondering what this inconsequential concern has to do with anything — but it’s the mindset that I want to note. Before I pointed it out, had you ever considered this dripping as a problem at all? Maybe you’ve never even noticed it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;**Failure to recognize problems is what inhibits society **— not the problems inherently themselves.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Not recognizing problems is called &lt;em&gt;complacency&lt;/em&gt;. Seeing a problem and choosing to ignore is called &lt;em&gt;laziness&lt;/em&gt;. Both are equally detrimental.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Innovation&lt;/strong&gt; is at the same time both the most jaded and the most ambiguous term in society today. We listen to TED Talks to learn from innovators; we use high tech gadgets to better innovate; we are put into diverse work groups to promote innovation— but what is it, really?&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;“Innovation simply put, is the child of problem and solution.”&lt;/h2&gt;
&lt;hr&gt;
&lt;p&gt;Imagine if everyone, at any given moment, was racking their brains for ways to solve some sort of a problem. At a world population of 7.6 billion, that’s a whole lot of &lt;strong&gt;innovation.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Nowadays, we either view problem solving as this one-time achievement (hence the all-too-familiar “tell me about a time you solved a problem” interview question), or as some quantifiable skill. So much so that companies explicitly list it in their job postings, along with “teamwork”, “hardworking” and the other plethora of traits sure to distinguish the most unique applicants. Rather, &lt;em&gt;problem solving is just a *&lt;strong&gt;*constant**&lt;/strong&gt; drive for improvement.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;In fact, it has been proven time and again that the difference between the highly successful and the average population is in nothing other than what what they &lt;strong&gt;think&lt;/strong&gt; about. There’s a reason that people like Steve Jobs and Mark Zuckerberg have multiple pairs of the same shirts, pants, shoes — it’s so they can maximize the time they devote to thinking about &lt;em&gt;improving&lt;/em&gt; their work and not on trivial matters like “what should I wear today?”&lt;/p&gt;
&lt;p&gt;That’s what drew me to be a part of PennLabs — we’re really just a problem solving organization dedicated to innovate and improve student life at Penn. Sitting in our weekly work meetings, you hear discussions from “is this really a problem that students struggle with?” to “what segment of the student population will even find this product useful?” The problems we try to tackle range from housing to dining to studying issues. Some resolutions to date:&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Problem:&lt;/em&gt; students carrying their laundry up three floors only to find all the machines are in use. &lt;em&gt;Solution:&lt;/em&gt;collect real-time laundry machine usage data and display it in &lt;strong&gt;Penn Mobile.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Problem:&lt;/em&gt; students want information on class and professor difficulty to make better course selection decisions. *Solution: *aggregate course and professor reviews on &lt;strong&gt;Penn Course Review.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;*Problem: *students struggle to research and reach out to all possible funding opportunities on campus for their club or activity. *Solution: *a one-stop tool that sends funding requests to multiple sources at once through &lt;strong&gt;The Common Funding Application.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These are just a select few of the many problems that we at Labs ponder over day and night, and what &lt;em&gt;drives&lt;/em&gt; them to build. It’s an obsession for solving the overlooked inefficiencies manifested in campus life, a passion for finding ways to make their friends’ time at Penn more enjoyable, and an overarching desire to &lt;strong&gt;bring Penn closer together as a community&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;For those on campus and unaware that the services I listed above were available, take a minute to check out some of the cool solutions that Labs has developed. Download PennMobile from the AppStore to start exploring its features. Follow us on Facebook and Instagram for product updates. Follow us here to read more technological musings tangentially related to what we’re working on at Labs. And if you have any ideas of your own, feel free to suggest them to us at any point. Just as there are no dumb questions, there are &lt;strong&gt;no dumb innovations.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;For example, don’t read too much into my narcissism here, but I would like to point out that the “inconsequential” oil drip problem we dismissed earlier now has an entire market dedicated to it. Isn’t pouring olive oil out of something like this the new bougie thing to do?
&lt;img src=&quot;https://s3.amazonaws.com/ghost-labs-static/2020/02/p2.png&quot;&gt;Tablecraft H9085 Olive Oil Dispenser 8 oz, available at Amazon.com
As a matter of fact, search some variation of “no drip spout” on Amazon and you will find a wide array designs, sizes, shapes of bottle spouts all dedicated to getting rid of the dripping. Clearly this problem extends further than a mere personal pet peeve.&lt;/p&gt;
&lt;p&gt;But hey, look at the number of innovations it led to.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;“*&lt;strong&gt;*Innovation**&lt;/strong&gt; comes from people meeting up in the hallways or calling each other at 10:30 at night with a *&lt;strong&gt;*new idea**&lt;/strong&gt;, or because they realized something that shoots holes in how we’ve been thinking about a *&lt;strong&gt;*problem**&lt;/strong&gt;.” ~ Steve Jobs&lt;/em&gt;&lt;/p&gt;</content:encoded></item></channel></rss>