The Frontend City

A presentation at EmberFest 2025 in September 2025 in Brussels, Belgium by Thomas Gossmann

Slide 1

Slide 1

The Frontend City Thomas Gossmann gos.si gos.si gossi

Slide 2

Slide 2

Brüssel

Slide 3

Slide 3

Brüssel 540 Unispin in front of the Basilique Nationale du Sacré-Cœur

Slide 4

Slide 4

Problem Statement We explain a technical initiative to non-tech folks We use technical language in our explanation We are not understood They approve the budget for our technical initiative They won’t - we weren’t understood Examples (Local) Refactoring Writing RFCs Change build system to Embroider/vite …

Slide 5

Slide 5

Example: Change Build System to Embroider/vite Arguments Questions It’s faster What will it cost us? It’s fancy How long will it take? Tree shaking Half a year to have the same situation as we have Smaller bundle size now? It’s modern How much features can be shipped instead? What’s the return of this investment?

Slide 6

Slide 6

Solution: Translate “ When we can explain it to my Mum, we are good. - My Manager

Slide 7

Slide 7

Task Responsibility Work on the Build System Keep the Frontend Operable

Slide 8

Slide 8

Question What would you need to do to keep the Frontend Operable?

Slide 9

Slide 9

Question 2 What would you need to do to keep a City Operable?

Slide 10

Slide 10

The Frontend City “ We built this city We built this city of rock and roll Built this city We built this city of rock and roll

  • Starship

Slide 11

Slide 11

Infrastructure City Layout Transportation Health & Security Sport & Entertainment Education City Construction

Slide 12

Slide 12

Infrastructure

Slide 13

Slide 13

Infrastructure City Software Electricity Dependency Management Water Build System Cable Release Management Garbage Collection Automated Maintenance Systems (dep upgrades) Traffic (lights) Framework infrastructure

Slide 14

Slide 14

City Layout Architecture

Slide 15

Slide 15

City Layout: Districts Hierarchical structures for managing complexity: Districts Districts to own all coherent parts of it

Slide 16

Slide 16

Architecture: System Landscape Subdomains System Components C4 Model

Slide 17

Slide 17

City Layout: Zoning American Suburbia Strict zoning (housing, commercial, industrial) Less/No mixed zoning Car dependent city Few transportation options By Avi Waxman on Unsplash By Michael Moloney on Unsplash

Slide 18

Slide 18

City Layout: Zoning Medieval Europe Zoning (housing, commercial, industrial) Mixed zoning Many transportation options By Svetlana Gumerova on Unsplash Shorter travels The “walkable city” By Matt Mutlu on Unsplash By Patrick Robert Doyle on Unsplash

Slide 19

Slide 19

Architecture: Code Organization Car dependent city = framework dependent product Your domain defines the organization of your code (never a framework) Use architectural patterns: Clean Architecture Vertical Slice Architecture Hexagonal Architecture … Prevent Tech Debt

Slide 20

Slide 20

Transportation APIs

Slide 21

Slide 21

Transportation Modalities Public Transport Private Transport Infrastructure Transport Hubs Railway network Streets Scope of traffic Local Traffic Global Traffic Public Transport Vehicles Private Transport Vehicles Bike Unicycle Tram Feet U-Bahn Car S-Bahn Bus ICE Stations Train Stations Bus Stops Stations Parking Space

Slide 22

Slide 22

Transportation: APIs Public API amongst subdomains Private API within a subdomain Use architecture lint to prevent illegal connections

Slide 23

Slide 23

Construction

Slide 24

Slide 24

Construction Houses in a City are the equivalent to Features of a Product City Software Construction workers evolve their tooling Linting - as railguards for programming languages Build houses… Formatting - to have the same syntactical look … faster (faster recognition) … safer Editor integration - For instant feedback on their … accessible fingertips … more sustainable Fixtures + Mocks Frontend Workshop

Slide 25

Slide 25

Health & Security

Slide 26

Slide 26

Health & Security: City Institutions Processes Firefighters Alarms for immediate actions Hospitals Pre-warn systems Emergency Medical Services Security checks for buildings Police Alpine Rescue Service Disaster Control …

Slide 27

Slide 27

Health & Security: Software Institutions Error Monitoring (Sentry) Processes Vulnerability management Entire app Monitoring or Subdomains Emergency changes Resource monitoring in grafana All sorts of tests from the testing pyramid Code coverage metrics Pre warn system through @embroider/try Rollback of changes Testing procedures Bug reporting Risk management

Slide 28

Slide 28

Sport & Entertainment DX

Slide 29

Slide 29

Sport & Entertainment Panem et circenses City Sport and entertainment are the most unnecessary Software DX minor matters in a city A city would function without Citizens greatly benefit from its presence Scaling Frontend: Superchar Ember Fest

Slide 30

Slide 30

Education

Slide 31

Slide 31

Education City Software Schools Onboarding Libraries Documentation Universities Diataxis: … Tutorials How-To Guides Explanation Reference Training Learning Time

Slide 32

Slide 32

The Frontend City “ Take me down to the Paradise City Where the grass is green and the girls are pretty Take me home (I want you, please, take me home) - Guns N’ Roses /gossi/the-frontend-city

Slide 33

Slide 33

Usage We do live longer in cities, than we live in code! Documentation Hub Decision Framework Structure your documentation based on the

  1. Connect an incoming request to the topic frontend city idea
  2. Decide from within that topic No onboarding needed
  3. Higher qualitative answers (connect to context & People feel “home” immediately and can navigate scope) 4. Higher confidence in your answers 5. Faster and more competent answers 6. Increase of trust in you

Slide 34

Slide 34

Example: Change Build System to Embroider/vite Task vs. Responsibility Task Responsibility Work on the Build System Keep the Frontend Operable See the task through the lens of responsibility Connect to context Reshape weight of task vs. responsibility -> Priority?

Slide 35

Slide 35

Solution Mission (Translation) Technical: Change Build System to Embroider/vite City: Change connectivity from broadband (DSL) to optical fiber

Slide 36

Slide 36

Reason: Time and Money Savings Optical fiber has lower latency, more resilient conncetions, higher bandwidth Economic Proof on Savings N umberOf Engineers ∗ ØRebuilds/Day ∗ RebuildT ime N umberOf Engineers ∗ ØBuilds/Day ∗ BuildT ime N umberOf Engineers ∗ Ext.SocialM ediaT ime/(Re)BuildDelay CIruns/Day ∗ BuildT ime Use numbers (Re)Build time numbers with classic and embroider/vite to run a comparsion Threshhold for N umberOf Engineers to savings to become significant If saving numbers are too low/insignificant, ROI/amortisation is not of interest

Slide 37

Slide 37

Solution Mission Technical: Change Build System to Embroider/vite City: Change connectivity from broadband (DSL) to optical fiber Reasons Time and Money Savings

Slide 38

Slide 38

Assessment: Technical Feasibility classic Embroider (loose mode) Can we roll out fiber in the city? Can we roll out fiber in to each district? Can we roll out fiber to each street? Can we roll out fiber to each house? Embroider (strict mode) vite

Slide 39

Slide 39

Assessment: Technical Implementation classic Embroider (loose mode) Embroider (strict mode) Preparation: Strict Imports Prepare requirements: Strict Components/Helpers/Modifiers, use @embroider/template-tag-codemod Tasks can be parallelized Can be done by product teams Great to onboard them with the new technology Iterative learning opportunity vite

Slide 40

Slide 40

Solution Mission Technical: Change Build System to Embroider/vite City: Change connectivity from broadband (DSL) to optical fiber Reasons Time and Money Savings Method Parallelize Involve product teams Incremental Delivery & Improvements

Slide 41

Slide 41

Challenge: Mindset Shift ember-cli shields engineers from build system internals vite provides much more exposure bundlers/transpilers are much more closer to engineers NPM is much closer ( imports and exports fields) CJS vs. ESM CJS ESM Align with JS Ecosystem Storybook 10 is ESM-only

Slide 42

Slide 42

Solution Mission Technical: Change Build System to Embroider/vite City: Change connectivity from broadband (DSL) to optical fiber Reasons Method Time and Money Savings Parallelize JS Ecosystem Compatibility Involve product teams More OTS Solutions (JS Ecosystem compat) Incremental Delivery & Improvements

Slide 43

Slide 43

Ecosystem Integration Internationlization ember-intl Authentication ember-simple-auth Icons ember-svg-jar ember-phosphor-icons intl-schematic openauth-js @formatjs/intl auth.js i18next better-auth linguist passport.js globalize Polyglot.js paraglide-js The solution for all of us

Slide 44

Slide 44

Integration: paraglide-js services/intl.ts export class IntlService extends Service { @tracked locale = getLocale(); setLocale = (locale: Locale) => { setLocale(locale, { reload: false }); this.locale = locale; }; t<MessageFn extends (…args: any) => string>( messageFn: MessageFn, params: Parameters<MessageFn>[0], options: Options = {} ) { return messageFn(params, { locale: this.locale, …options }); } formatNumber(value: number, options?: Intl.NumberFormatOptions) { return new Intl.NumberFormat(this.locale, options).format(value); }

Slide 45

Slide 45

Integration: paraglide-js helpers.ts function T<MessageFn extends (…args: any) => string>( messageFn: MessageFn, options?: Options | Parameters<MessageFn>[0], params?: Parameters<MessageFn>[0] ) { return resource(({ owner }) => { const intl = owner.lookup(‘service:intl’); if (params) { return intl.t(messageFn, params, options); } return intl.t(messageFn, options); }); } export const t = resourceFactory(T);

Slide 46

Slide 46

Integration: paraglide-js Usage import { m } from ‘#paraglide/messages.js’; import { formatNumber, t } from ‘ember-paraglide’; <template> {{t m.greeting name=”World”}} {{t m.greeting}} </template> Paraglide compiles messages to functions (vite/unplugin plugin) The (t) accepts a function Tree-shaking unused messages away Tooling Ecosystem (UI for messages in vscode)

Slide 47

Slide 47

Integration: better-auth They have signals Beatiful implementation for Vue and Svelte Let’s start using signals for a similar Ember implementation … That is not a smooth experience yet Community Feedback needed: RFC #1071, RFC #1079, RFC #1122

Slide 48

Slide 48

Integration: better-auth class AuthService<User extends BetterAuthUser = BetterAuthUser> extends Service { client!: AuthClient; @tracked internalData?: Data<User> = undefined; get user(): User | undefined { return this.internalData?.user; } setup = (auth: AuthClient) => { this.client = auth; if (auth.useSession.value?.data) { this.internalData = auth.useSession.value.data as unknown as { user: User; session: Session }; } this.loading = !this.internalData; auth.useSession.subscribe((payload) => { if (!payload.isPending) { if (payload.data?.user && !this.authenticated) { this.#handleSessionAuthenticated(payload.data as unknown as Data<User>); } else if (!payload.data?.user && this.authenticated) { this.#handleSessionInvalidated(); } } this.loading = payload.isPending; this.internalData = (payload.data as unknown as { user: User; session: Session } | undefined) ?? undefined; });

Slide 49

Slide 49

Integration: better-auth class AuthService<User extends BetterAuthUser = BetterAuthUser> extends Service { requireAuthentication(transition: Transition) { return new Promise((resolve) => { if (this.authenticated) { resolve(this.authenticated); } const handleAuthentication = () => { if (!this.authenticated) { this.#attemptedTransition = transition; } resolve(this.authenticated); }; const waitUntilLoadingIsComplete = () => { if (this.loading) { return next(waitUntilLoadingIsComplete); } handleAuthentication(); }; if (this.loading) { next(waitUntilLoadingIsComplete); } else { handleAuthentication(); } });

Slide 50

Slide 50

Integration: better-auth very similar to ember-simple-auth user menu protected route export default class UserMenu extends Component { @service declare auth: AuthService; export default class ProtectedRoute extends Route { @service declare auth: AuthService; <template> async beforeModel(transition: Transition) { {{#if this.auth.authenticated}} {{#let (popover position=”bottom-start”) as |p|}} const authenticated = await this.auth .requireAuthentication(transition); <Button {{p.trigger}}> {{this.auth.user.name}} if (!authenticated) { </Button> this._router.transitionTo(‘login’); }

<Menu {{p.target}} as |m|> <m.Item @href=”/user/profile”>Profile</m.Item> <m.Item @href=”/user/sessions”>Sessions</m.Item> <hr /> <m.Item @href=”/user/logout”>Logout</m.Item> </Menu> {{/let}} {{else}} <Link @href=”/login”>Login</Link> {{/if}} } }

Slide 51

Slide 51

Icons Use Iconify Configure vite.config.js import { FileSystemIconLoader } from ‘unplugin-icons/loaders’; import icons from ‘unplugin-icons/vite’; export default defineConfig({ plugins: [ // … icons({ autoInstall: true, compiler: ‘raw’, customCollections: { custom: FileSystemIconLoader(‘./assets/icons’) } }) ] }); Usage sports.gts import import import import { Icon } from ‘@hokulea/ember’; Unicycle from ‘~icons/custom/unicycle’; Activity from ‘~icons/ph/activity’; svgJar from ‘ember-svg-jar/helpers/svg-jar’; <template> Do some <Icon @icon={{Unicycle}} /> <Icon @icon={{Activity}} /> Fallback <Icon @icon={{svgJar “unicycle”}} /> <Icon @icon={{svgJar “activity”}} /> </template>

Slide 52

Slide 52

Integrations with Ember Github Organization: ember-integrations Candidates: vitest-browser-ember , ember-vitepress , … Integration code is tiny glue code

Slide 53

Slide 53

Solution Mission Technical: Change Build System to Embroider/vite City: Change connectivity from broadband (DSL) to optical fiber Reasons Method Time and Money Savings Parallelize More OTS Solutions (JS Ecosystem compat) Involve product teams Integrate with JS ecosystem Incremental Delivery & Improvements Faster and cheaper development with more functionality

Slide 54

Slide 54

Breaking Changes? Ember Ember provides a migration path Can you migrate in time to receive future updates? Relevant: Security fixes Addons Supported Ember versions are at the will of its authors When will addon authors stop supporting Ember version x? EMBER INTEGRATION ADDONS Use tsdown over rollup ESM only type=”module” No @embroider/addon-dev

Slide 55

Slide 55

Solution Mission Technical: Change Build System to Embroider/vite City: Change connectivity from broadband (DSL) to optical fiber Reasons Method Time and Money Savings Parallelize More OTS Solutions (JS Ecosystem compat) Involve product teams Faster and cheaper development with more Incremental Delivery & Improvements functionality Risk Framework Update Continuity (security fixes) OTS Adoption (limited to legacy adoptions = higher cost)

Slide 56

Slide 56

Architecture: Exploit the Degree of Freedom Strict imports (template imports): Organize code by your domain Strict resolver: RFC #1132 Don’t build a car-dependent city Ember has the best template system Router: Subject of the next Edition to also build the best Router

Slide 57

Slide 57

Solution Mission Technical: Change Build System to Embroider/vite City: Change connectivity from broadband (DSL) to optical fiber Reasons Method Time and Money Savings Parallelize More OTS Solutions (JS Ecosystem compat) Involve product teams Faster and cheaper development with more functionality Increase Architectural Freedom Architectural Freedom: Build our City Risk Framework Update Continuity (security fixes) OTS Adoption (limited to adoptions = higher cost)

Slide 58

Slide 58

Solution Mission Technical: Change Build System to Embroider/vite City: Change connectivity from broadband (DSL) to optical fiber Reasons Method Time and Money Savings Parallelize More OTS Solutions (JS Ecosystem compat) Involve product teams Faster and cheaper development with more functionality Architectural Freedom: Build our City Risk Framework Update Continuity (security fixes) OTS Adoption (limited to adoptions = higher cost)

Slide 59

Slide 59

Thank You There was something about a Translation and a City There was something with vite There was something with modern Ember on vite