As a front-end developer at AltSchool, I help build web-based software for educators, students, parents, and internal users. With EmberConf 2016 upon us, I’m inspired by other people sharing their experiences, so I’m writing a series of posts about how we use Ember at AltSchool: what we do with it, what’s great about it, where have we struggled, and what we’ve learned in the last three and a half years.

AltSchool is both a technology start-up and a network of small schools. We have a new approach for how to start and run schools based on personalization to individual students. To achieve our goal of enabling all children to unlock their full potential we are building an operating system for 21st century schools: including software, a knowledge-base, recommended curricula, and more.

Our users are the students working hard in the classroom everyday, the teachers who create lessons and track student progress, and the parents who are monitoring their child’s education and communicating with teachers. We’ve built half a dozen Ember apps for these three very different use cases.

Our Apps

Our biggest app includes different surfaces for students, teachers, and parents. Everything from a visualization of a student’s mastery of K-12 mathematics concepts, to a student’s list of assignments, to a UI for scheduling absences. This app has 131 routes, 777 js files in the app directory, and over a thousand automated tests. Over the last year, we upgraded this to ember-cli and 1.13 from ember 1.10, resulting in improved rendering performance, and now we’re almost ready for Ember 2.0.

This mockup shows how Progression allows teachers to see what a student is working on or has already mastered.

We recently added a new application for communicating with parents . Written in Ember 1.13 from the start, it has 8 routes, 290 automated tests, and 114 js files in `app/`. The app modernizes communication between teachers and parents; instead of printed permission slips and report cards, parents see social media-like posts from teachers with actual student work. This was our first app to use pods, and it makes extensive use of components rather than dozens of routes.

. Written in Ember 1.13 from the start, it has 8 routes, 290 automated tests, and 114 js files in `app/`. The app modernizes communication between teachers and parents; instead of printed permission slips and report cards, parents see social media-like posts from teachers with actual student work. This was our first app to use pods, and it makes extensive use of components rather than dozens of routes. An internal app for managing admissions . It’s pretty big, with 32 routes. Our admissions team uses this custom-built application to manage the entire workflow from a student’s initial application, through classroom composition and accepting enrollment. This app gets very high-intensity usage from expert users, which means the UI doesn’t have to be self-explanatory, but it does have to be powerful enough to support complex workflows.

. It’s pretty big, with 32 routes. Our admissions team uses this custom-built application to manage the entire workflow from a student’s initial application, through classroom composition and accepting enrollment. This app gets very high-intensity usage from expert users, which means the UI doesn’t have to be self-explanatory, but it does have to be powerful enough to support complex workflows. A mobile app for taking attendance . Keeping accurate attendance is crucial to the safety of our students, and must run effectively despite spotty curbside connectivity; this is a problem the team continues to grapple with, but we’re excited about using service workers or operational transforms to solve it.

. Keeping accurate attendance is crucial to the safety of our students, and must run effectively despite spotty curbside connectivity; this is a problem the team continues to grapple with, but we’re excited about using service workers or operational transforms to solve it. A mobile app that enables teachers to create new student activities and attach documentation to existing activities from their phones. This one is super-cool; it’s an Ember 2.2 app delivered to teachers’ phones as a hybrid Cordova app, with plugins for authentication, error reporting, and interaction with native components.

In order to share code between those apps, we’ve written several add-ons:

Slate. Our interactive style guide and component library. The site itself is public, although the code is private, but you can check out my favorite component, the card thumbnail.

The {{card-thumbnail}} component

A card is the basic unit of student work; it may be an assignment to write an essay, instruction to do an exercise at an external website, or a representation of a class field trip. This single component actually uses five sub-components, so it brings performance challenges when we’ve got fifty of them on a page. We’re eager to get to Glimmer 2, to take advantage of its improved rendering performance for component-heavy apps.

Shared models . We hit the same Django back-end from all of our front-ends, so we have moved the DS.Model declarations into a common repository. This includes adapters and serializers, too. Our shared models are built upon the RESTful resource pattern encouraged by ember-data, and we’ve extended this pattern to support dynamic loading and filtering of our resource graph. Check out our open-source back-end library.

. We hit the same Django back-end from all of our front-ends, so we have moved the DS.Model declarations into a common repository. This includes adapters and serializers, too. Our shared models are built upon the RESTful resource pattern encouraged by ember-data, and we’ve extended this pattern to support dynamic loading and filtering of our resource graph. Check out our open-source back-end library. ember-query-expressions : A library to compose and cache custom queries for our back-end. This works beautifully with Dynamic REST and shared models.

: A library to compose and cache custom queries for our back-end. This works beautifully with Dynamic REST and shared models. Test helpers : We got really good at writing acceptance tests — probably because we wrote too many of them — so we made an add-on to share our favorite test helpers. The most important one, setupUser, creates a big set of related fixtures, representing a coherent database state. In new code, we are not relying so much on fixtures, but that is a work in progress.

: We got really good at writing acceptance tests — probably because we wrote too many of them — so we made an add-on to share our favorite test helpers. The most important one, setupUser, creates a big set of related fixtures, representing a coherent database state. In new code, we are not relying so much on fixtures, but that is a work in progress. table-view : Teachers need gradebooks, right? Our table-view add-on started as a performant way to display tabular data with shared styling and custom cell types. With Glimmer, we were able to refactor away our performance optimizations, but preserve the performance. Now it’s a useful standard approach to building tabular displays, combining styling and behavior.

: Teachers need gradebooks, right? Our table-view add-on started as a performant way to display tabular data with shared styling and custom cell types. With Glimmer, we were able to refactor away our performance optimizations, but preserve the performance. Now it’s a useful standard approach to building tabular displays, combining styling and behavior. Shared analytics library: the nested route pattern in Ember means that no individual call site has access to all of the application state. Our ember-as-analytics library accumulates application state from levels of the route hierarchy (including components), sending it to our analytics services. It also provides hooks and identification for anonymous and known users.

We have ten engineers working full-time on Ember apps, and about a thousand users who rely on our Ember-based applications for their education or to do their jobs. In the rest of this series, I’ll describe why Ember is a good match for us, some problems we’ve had with it, our upgrade woes and triumphs, performance challenges, monorepo vs add-ons, and changes in our testing strategy as we scale. Want to know more? Mention @bshine on Twitter, or leave a comment below.

We’re hiring! If you’re interested in helping with the work I’ve described here — even if you’re not an Emberist yet — apply here.