Hacker News new | past | comments | ask | show | jobs | submit login
Windows 10 Hosted App Model (windows.com)
168 points by ComputerGuru on April 3, 2020 | hide | past | favorite | 109 comments



The most interesting part to me:

> We are working with the new Microsoft Edge browser to take advantage of the Hosted App Model for Progressive Web Apps (PWAs) – converting the web app manifest into an app manifest, package the additional web content into an MSIX package and register it. In this model, a PWA is its own independent app registered to the system even though it is being hosted by Edge.

Can a shared, system-wide Electron runtime be far behind?


Thats probably why they switched Edge to chromium. Instead of each electron app running its own copy of node and chrome, those components can be build into the os, which is much better for battery life.

Even their flagship app, teams, is running its own copy at the moment.


They got in trouble for embedding IE4 into Windows and supposedly eliminating user "choice". Now nobody will care if they do it again.


Chromium is open source, so there's no chance they can be called a monopoly.


My understanding is that monopoly by itself is not illegal but it is the abuse of one’s market position in one thing to gain advantage in another. Not saying this is correct, just, or legal, just saying that’s what I think is how things are at least in the US.

If it wasn’t obvious: I anal.


What does open source have to do with choice?


As has always been the case, you can use whatever browser you want on whatever OS you want. This has never been more true than right now.


I don't think using the open-core model gets them off the hook.


Can a shared, system-wide Electron runtime be far behind?

MS had a similar technology over a decade before Electron existed:

https://en.wikipedia.org/wiki/HTML_Application


HTA still exists. For new apps? No thank you.


Indeed. HTA showed a lot of promise before MS deliberately crippled it in fear of "web technologies" overtaking desktop apps. A very interesting read: https://www.joelonsoftware.com/2004/06/13/how-microsoft-lost...


Microsoft has already updated Window's native web-view to Edge, from IE. There are already some projects that take advantage of this and enable multi-platform app creation, with executables much lighter than Electron. A good example is https://github.com/zserge/webview. I have tried its Rust binding, and it works very nicely.


The Chromium-based Edge has its own separate webview API (called WebView2) which is still only in preview right now: https://docs.microsoft.com/en-us/microsoft-edge/hosting/webv...


How is a shared runtime much lighter than electron? While you can share some memory, I doubt it's most of it.

If I check the dozens of Chrome processes on my machine, the largest part of their working sets is private, which is evidence against significant memory sharing.


One aspect of "lightness" is transfer & disk: initial download duration, storage size per app (often over 100 MB for apps with embedded Chromium), and the size of each app update which often needs to update the embedded Chromium too, if they're being responsible. There is no "LTS" version of Chromium.


I don't know much about Chrome's architecture, but are you sure each tab/window/origin has a separate set of all processes?

It seems reasonable to only run the security sensitive parts in a dedicated process per origin and run other tasks in a central process for all web pages.

From what I understand, Chrome's processes communicate a lot via message-passing. You probably don't need large amounts of shared memory for that.


The weight of a bunch of DLLs, type information etc for chromium is actually pretty sizable. An electron app spins up 6 processes on average last time I checked, more sometimes. The v8 team has had to invest a lot into reducing bloat from per-process duplication of data and also found ways to minimize startup time.

The largest part being private doesn't mean saving 10-20mb per process is insignificant. With a few electron apps open I'm easily losing a few hundred megs to electron overhead and many machines don't have that much RAM, especially laptops.

Each electron app also needs its own copy of centralized services like the i/o process, where a single chrome instance can share that across all tabs. An OS-level PWA implementation could share it across all PWAs and electron apps too.


I can recommend trying this out with the Spotify web app.

It is genuinely difficult to spot that it’s actually “just” a website.

When you lock windows while it’s playing it shows up with media details like album art, play/pause etc.

It is additionally “registered” in the start menu, and correct icons and windows taskbar behaviour is used, making it virtually indistinguishable from a native app.


To be pedantic, that is using a precursor to this model, with a UWP app hosting nothing but a web view. This would be similar but conceptually simpler and with less boilerplate.


Its a terrible app though


Compared to what? What’s the best Desktop media player?


foobar2000 + media player classic HC


exactly what I use as well


WinAmp


It really whips the llama's ass!


Given the efforts behind https://dotnet.microsoft.com/apps/aspnet/web-apps/blazor I would say it is the WebAssembly based .NET runtime that counts in the long run.


Given the track record of Microsoft I'd say: That mainly depends on which team "wins".

https://commons.wikimedia.org/wiki/File:%22Org_charts%22_com...

:)


And a shared, system-wide Android runtime. This sounds like a great path towards continuity across the Surface product line from desktop to mobile, given the mobile Surface devices being powered by Android coming this year.


> Can a shared, system-wide Electron runtime be far behind?

I remember some people on HN already predicting exactly this back when the announcement to base Edge on Chrome was made.


That’s essentially what progressive web apps are once they’re installed. They use all the resources of the browser so they only take up as much disk space as their HTML/CSS/JS.


How is this different from the browser?


It cloud have more permissions.


Was just about to post this same quote. Really exciting stuff.


> Can a shared, system-wide Electron runtime be far behind?

This is exactly what I was thinking about.


Maybe whoosh...but.. Congratulations you’ve invented a web browser.


This was a major feature in IE9-11, that you could run basically a UI-less modifiable web application without noticing* that it's running on an embedded browser.

Electron is a similar ideal, but not on the OS level. They are just recreating the best aspects of IE for Chromium, and we will be better for it.

* noticeable for that era


Looks like python becomes a first class citizen to Windows.

Sadly I was just complaining about how "apps" these days weren't apps (especially on Linux) they were directed-acyclic-graphs of dependencies with an execution conductor at the top. This can work fine except when two of these things want a different version of a dependency n layers deep. This is especially a problem when those dependencies are managed/maintained by volunteer labor that may or may not see the wisdom of compatibility rules across minor revisions.

I know that the alternative is having the OS controlling entity be a gatekeeper over "blessed" and "not blessed" dependency layers, which bites because they can never keep up. Still the pain of having things break so badly that an entirely new meta-layer called "containers" was invented in part to partition these 'App-DAGs' in a space where they don't conflict with others. That doesn't feel like progress to me somehow.


A Linux app as a DAG of dependecies, sometimes hard to reconcile? Welcome to 25+ years ago, when dynamic linking and .lib.so stuff became the norm on Linux. That is, basically as long as Linux existed.

Monolithic static apps and stuff like Snap are relatively modern.


Yeah, I know, and I've certainly got blood on my hands here as I helped to implement dynamic linking in SunOS 4.0.

That said, there is a qualitative difference between an app as DAG where said DAG is restricted to only those nodes that are present on a given "release" which describes the entire graph, and an App which is a DAG on a set of subgraphs, each with their own notion of 'currency' and overlapping nodes with other subgraphs.


So, i'm not sure why this is needed... is it a workaround for some limitation with MSIX? Is it only for windows store/UWP/whatever-it-is-called-nowadays apps? Or it is usable by a regular Win32 desktop .exe (so, can i for example use it via Lazarus/Free Pascal by loading some API from a DLL?) and if so in what scenario?

From the description it sounds like this is for something like, e.g., some Java application appearing as something else than javaw.exe in task manager.

Let's say i'm making some sort of scripting language (which sounds like what is being described there) that is distributed from my web site as an installer made with -e.g.- InnoSetup or NSIS that registers .mylang to be launched with mylangparser.exe (or whatever)... how am i supposed to use this (especially if the parser isn't written in C or C++ but in Free Pascal or D or Rust or any other language that isn't C or C++ but still has the ability to call C calls via DLLs) and for what reason? Or am i not supposed to use this?


It's just needed if you want scripts for your runtime to be treated as separate apps by the OS. Otherwise, they'll all be treated as the same app, so any OS feature that depends on the OS understanding what's logically a separate app will be either unusable or at least sort of broken. Ranging from how they show up in task manager as you mentioned, to sandboxing and package uninstall as others mentioned, to share target, notification and background task support as the article mentions, to how they're grouped on the taskbar, etc.

The host needs to be registered as a Windows app, so it either needs to be distributed/installed as MSIX (either from your own website as explained in https://docs.microsoft.com/en-us/windows/msix/app-installer/... or from the Microsoft store) or if you can't/don't want to do that for whatever reason, there's another recently added feature called "sparse package registration" that basically lets you distribute/install in some other format and then at runtime, register a mini-MSIX that just points the OS at your already installed files: https://blogs.windows.com/windowsdeveloper/2019/10/29/identi... (this is a WinRT API so someone needs to have implemented bindings in your language for those, which exists for Rust - https://github.com/contextfree/winrt-rust - but idk about Free Pascal or D)


In the future all Windows applications will be sandboxed, MSIX was the first step merging UWP and Win32 worlds after the failed experiments with Project Centipede, Android and Cocoa integration into Windows 8.x.

The upcoming Windows 10X, uses sandboxing for everything, including Win32.

https://www.youtube.com/playlist?list=PLWZJrkeLOrbZ3CMHpbglE...

This is intended for languages that require some kind of interpreter to run, and to have OS integration out of the box as if they were "native" apps on Windows.


That doesn't really answer any question i made though. Is it something specifically about Windows 10X and MSIX limitations? How would i use it? Etc (i do not want to repeat my questions, i'd just copy/pasting them :-P).


It's a fix for a limitation of the Windows app model, i.e. to the OS's knowledge of which executables, processes, files, etc. logically belong to which apps. MSIX is how you register an app with the OS so in that sense it's about "MSIX limitations" but apps/runtimes not installed with MSIX still have the same problem.

The OS knowing what's logically the same app vs. separate apps is a prerequisite for 10X and sandboxed apps, but there are other features usable by non-sandboxed apps that depend on it too.


This is to avoid having every app bundle the same runtime over and over again. Instead, the runtime is shipped as a separate package, and then apps written in languages that require that runtime depend on that package.


What you write sounds exactly what you'd get with JRE and Python which worked ever since the Win9x days. My questions are about the differences that make this necessary.


Microsoft is moving to same security model as Android and iOS where individual applications request (and can be denied) permissions to do things. One example is triggering desktop notifications. If you get a notification you can see exactly which application sent it and then prevent that application from ever sending you another one.

What you get with JRE and Python in the Win9x days is that the executable is "java.exe" or "python.exe" which isn't helpful when the actual application is what is being run by these programs. Granting a permission to python.exe is not what you intend when you're wanting a notification from helloworld.py.


That would easily be solved with an API call that says "Hey, i'm helloworld.py". It wouldn't solve the sandboxing stuff, but TBH i do not see that working for desktop applications (in that the sandboxing wont be mandatory for backwards compatibility - the main reason people keep using Windows - and most desktop applications wont bother restricting themselves).

The whole effort reminds me of W3C doubling down on XHTML despite everyone else ignoring it (and it isn't like XHTML wasn't nice on paper, but real world has other concerns beyond doing some things the theoretically "right way").


> That would easily be solved with an API call that says "Hey, i'm helloworld.py".

That's what this is! "Hey, I'm helloworld.py and I'm a Python application". Just an API call isn't going to work because every application is potentially hostile.

Windows 10X is sandboxing Win32 application through a virtualization layer.


Win9x didn't have the app store with a sandbox, one click to install, and auto-updates. If you installed a Python or a Java app without having the corresponding runtime, it just didn't work. If you had the runtime installed - which had to be done separately - and then later the user tried to uninstall them, they wouldn't get any warnings, but all apps relying on them would be broken. Not to mention versioning.

Think of it more as a Windows version of apt-get.


Hmm, others are pointing towards PWAs, but to me this looks more like a way to "install" scripts (python, ruby, PHP, powershell etc).

I guess this is trying to open the Windows Store to more devs, giving them an option other than UWP - which is certainly a laudable notion. But I really wish the article was clearer about what the end goal is.

This actually sounds pretty cool... but I'm not sure who it's aimed at; scripts are typically for command line tools, not GUIs. And for those au fait with the command line, I'm not sure what the benefit is, beyond signing the package (which, technically, could already be done if you packaged your script in an MSI/MSIX installer).


Windows store is already more than UWP, nowadays Win32 is also part of the store and after Windows 10X the models will be even more so.


There are plenty of GUI apps written in Python running on Linux using PyGtk or PySide. There's no reason why there couldn't be Python apps running on WinRT, especially since it can be projected very nicely onto Python.


My big takeaway from this is that Progressive Web Apps (PWAs) will become more like first-class apps on Windows.

Installing a PWA on Windows will make it show up as its own process in Task Manager, listed in start menu and taskbar, listed as its own entry in Add/Remove programs, etc.

This is made possible in part by this Hosted App Model.


They were already with Edge.

https://docs.microsoft.com/en-us/microsoft-edge/progressive-...

This is like the evolution after migrating to Chrome.

Also Google does the same with PWAs on Android and ChromeOS.

If they are signed and distributed via the store, you can access OS APIs from the browser directly.

https://developers.google.com/web/android/trusted-web-activi...


Absolutely. With frontend logic powered by C#/.NET courtesy of Blazor.


Are you suggesting XAML/C# to WebAssembly/PWA to Desktop app?

Why not just XAML/C#/Desktop App?


Not suggesting using it myself, merely saying this is where Microsoft is going with it. They don’t have a cross-platform XAML render. They’re trying to abstract away the OS in .NET Core, and XAML no longer fits the bill.


Sure it does, Xamarin alongside React Native and PWAs are the official SDKs for Surface Duo.

Also WinUI, is the only Windows UI toolkit that is actually being developed, instead of getting only bug fixes like the other ones.


Xamarin is mobile and macOS only.


Yeah, then what I have here on Windows 10 is a mirage.

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/platf...


PWA are multiplatforms while C# still hasn't a first party multiplatform GUI toolkit. Which is shame, because the dev experience in XAML+C# is really good, and Silverlight out of Browser was exactly that.



Avalonia is not first party (Microsoft). It’s also still in development and not production ready.


Xamarin.


No. Xamarin focuses on mobile apps, not desktop. Also, you have to chose between Forms which is ugly everywhere, and Native which require a non trivial understanding of each underlying platform.


WinUI and UWP seem like desktop to me, plus there are plenty of other ones,

https://github.com/xamarin/Xamarin.Forms/wiki/Platform-Suppo...

Just like with Qt, Flutter, wxWidgets, Gtk+, Swing and JavaFX, Forms is only ugly when one cannot bother having designers on the team.


Very nice but they should unify things a little on Windows. There are so many types of apps and it's not clear when you should use which. For example, Windows Store apps can not snapshot the screen...


This was an early limitation, which was fixed in Windows 1803 with the release of the Windows.Graphics.Capture API. [1]

That being said, your general point that there's so many ways to develop an app for Windows, and that not all of them support the same features, is definitely true. I think the general advice these days is that if you _can_ build your app as a UWP, do that. Otherwise, use the Win32 APIs as sparingly as possible, defaulting to the UWP APIs. Legacy apps are a bit trickier, and that's where Microsoft is investing in things like the Desktop Bridge (run Win32 apps in a UWP container) and XAML Islands (host UWP controls in a Win32 app).

[1] https://docs.microsoft.com/en-us/windows/uwp/audio-video-cam...


This sounds like a feature, at least as a user. Sandboxing that is fantastic. I wonder if they also block the app from reaching into the copy/paste buffer.

If they successfully sandboxed to that level, that is basically mobile device level of app severity. Fantastic!


The problem is that it’s increasingly difficult to figure out how to start. Let’s say you have a Store app andafter a while you realize that screenshots would be a good feature. You should be able to add this without having to rewrite the whole thing. That’s why a lot of people stick to WPF because it’s predictable and you don’t have the risk that some Store rule will trip you up later.


Unless you are a user who wants to snapshot the screen or copy/paste between different applications :-P.

(though i guess you were sarcastic :-P)


The app being able to snap the screen is different than the user.


Sure, you can always pull out your camera and take a photo of your monitor, but usually what you want is to use a program to grab a screenshot - so that program is what needs to be able to take the screenshot in behalf of the user.


You don't need an app for taking a screenshot. Windows used to include the Snipping Tool I think since Windows 8, and nowadays in Windows 10 it's just functionality baked into the OS: press Shift+Win+S to access it.


You do not need an app for taking a screenshot, but apps can and often do provide additional functionality than the OS - the OS cannot provide by itself every single functionality you may need, its developers may not even think about all cases or consider them important to implement them.

For example while the snipping tool (and printscreen and alt+printscreen, etc) exist, there are tools like Greenshot and Snagit that provide functionality like instant saves to files, better on-screen snipping, an embedded editor for annotations, etc that can be very useful when you want to create many screenshots fast.

Another thing is that some tools may not exactly do what the OS would do (screenshots in this case) but use the mechanism for something similar but different. For example ScreenToGif uses pretty much the same mechanisms for taking screenshots to create short GIF animations from screen captures and then provides a simple timeline editor to for editing the frames, adding annotations, shapes, etc.

The OS simply has nothing like these and it is impossible for it to provide every single functionality that could ever exist.

Note that this applies to other stuff too, not just screenshots.


And yet, the way we try to control it for the former is by denying it to the latter.


Yes, let's continue the trend of dragging the desktop PC down to the level of functionality available on a cell phone. We'll be so "secure" that we can't get anything done.


I get plenty of stuff done on my phone.


Yeah, well, I don't.

And neither did the people who designed that phone.


Maybe I'm getting this wrong, or over simplifying things here but my understanding is this means windows now has an overly complicated '#!'?


It's closer to a macOS bundle than a single script with '#!'. It's at a higher level of abstraction than linking a single script file to an executable.

It would let you build, say, a Ruby interpreter which declares itself as a host, and then package a Ruby application that makes use of the interpreter, including its libraries, native code extensions, and all the related assets.

The Ruby application would behave like a native application, with its own identity in the Start Menu/Task Manager and its own sandbox/entitlements. The Ruby interpreter and the packaged applications would appear separately in the uninstaller list in Settings, and presumably could be distributed via the Microsoft Store walled garden.

The whole 'Windows app model' concept is about bringing something close to the "one icon = one app" experience from mobile to Windows, instead of depending on heuristics or uninstallers to figure out which set of files/processes are part of a single "app" from the user's point of view. This is an extension to that model.


> The Ruby application would behave like a native application, with its own identity in the Start Menu/Task Manager

You've always been able to achieve this by changing settings/properties on a .LNK file - or a .PIF file for MS-DOS based applications, as far back as Windows 3.x. (With the 'canonical' .LNK file for an app being precisely the one that's linked in the user- or system-wide Start menu). This stuff has worked just fine for the last 25+ years. Sandboxing is of course new, but MS-DOS applications linked in .PIF files used the same strategy to define sandbox-like properties, and .LNK properties could be extended for the same purpose.


A LNK/PIF doesn't give a coherent view of the whole "app" from the user's point of view, though.

If you delete the LNK, you don't uninstall the app -- you just can't access it easily any more. If you create a second shortcut to the app, then uninstall the app, the second shortcut lingers but doesn't work.

If you install an app, it might put two or three shortcuts onto the start menu -- lets say it's a video game, and it installs a shortcut for the game itself, and another for a settings tool. (If it's an old game, it'll probably install a shortcut for the uninstaller, too). Which of those shortcuts should the start menu highlight as the newly installed app, to help the user discover it?

You can make the argument that an abstraction based on files, paths, individual executables and command line arguments (which is what LNK/PIFs support) is superior, and I think a lot of people on HN would agree -- but it's not the abstraction that new computer users being trained on mobile devices are internalizing.


It should also be emphasized how game changing proper packing is in itself. Historically Windows scripts, installers, applications, etc could liberally spray the filesystem and registry with their content. Cleaning this up was rarely easy as it relies on each script (or uninstaller, etc) to do the job right.

Proper packing gives more control to the user in this regard. Changes to the filesystem or registry will (by default) be contained. It's worthwhile to make this type of packaging easier and better integrated.


> Historically Windows scripts, installers, applications, etc could liberally spray the filesystem and registry with their content.

They could do this, but suggested standards have always existed, e.g. system-wide files in a sub-directory of $PROGRAM_FILES, user-specific data in $APPLICATION_DATA and the like. Then, in principle, a general uninstalling procedure can figure out what it needs to delete. It's not clear what all the extra complexity in these newer standards is adding.


It was left up to application developer to implement, and each software house could fuck it up.

Just think about computer games, I have one that saves savegame files in app data, one that saves it to my documents, and an older one that saves them into program files.

Now the 'container' is managed by the os, and the OS can actually tell me how much space an app is taking, and update/delete it with all the residual files


Suggested standards have existed but they are routinely flouted in practice. These packaging systems make it much easier for developers to do the right thing and harder to do the wrong thing. And it gives the user confidence that they can easily remove an application in its entirety.


'#!' is implemented by associating file extension with some specific application. For example you can associate '.py' files with 'python.exe' and when you double-click on 'app.py', it'll be launched using python. So it definitely not this thing.

I, personally, didn't understand what this article is about and why would I use this mechanism when simpler one exists and works for decades.


Security: those apps are sandboxed and also cleaner to de/install. Otherwise it’s mostly MS trying hard to make its store relevant.


Neat! Now we can have the seamless .NET experience for other languages too!

.NET core, 4.x what is desktop only etc etc. It will be of course extra simple when combined with pyenv, virtualenv and node.

Seriously though, I can see one possible benefit - whatever Microsoft pushes as a version of the runtime, may be what developers expect and use.

Or maybe not, since you can depend on a "host" app you yourself publish (right?) which is your preferred Python version or whatever.


This sounds like (for now) the first step towards something like shared runtime for electron apps, would greatly solve the perf issues associated with electron. I built https://github.com/SiDevesh/Quark-Carlo a while ago to convert web apps to native apps using the installed chrome browser as a runtime, using the carlo project by google, google killed it pretty soon though. This way apps would only have to package their own node runtime (since a lot of electron apps use native modules or modified version of nodejs) and use chromium from the system. The above project by me does the same thing and the size and memory requirement is greatly reduced, (apps come at average of 40mb as compared to 120mb for electron apps).


So as best I understand it, this has 1 niche advantage over typical exe/msi/uwp. It makes it more straightforward to create a generic application, which could then easily be "branded" by customers and then resold as their own app. So in essence you become an oem app developer, and then affiliates make apps based on your product. So instead of distributing a raw api, you can distribute an app in a box. And then it also allows the affiliate app to identify as your own for api calls, but I'm not sure when that is actually useful.

I'm scratching my head trying to come up with a use case that doesn't feel so contrived, can anyone think of one?


Huh, today I learned you can convert a UUID to decimal and prepend {joint-iso-itu-t(2) uuid(25)} to get a really big OID.


Which is probably the dumbest approach to generating OIDs as getting your own subtree is simple (and in many cases you already have your own subtree without even realizing it).


It's a very useful way to generate OIDs! Odd microsoft didn't get a nicer one.


Seems like another attempt at beating a dead horse to me. Ms need to give up on the whole app store thing and start creating a decent desktop experience again. If they decoupled the app virtualisation from the app store and made it less locked down it would actually be useful.


This isn't dependent on Store at all. App virtualization has been decoupled from the store for some time now.


This feels to me, like the next best vector to compromise users.

The horror of HTA aren't forgotten, I'm hoping they handle this better.


Argh! I am reluctant to install any software in my Windows machine, be it a Pdf reader or a camera driver, because all of them install "services" to auto update their software. I have an old notebook that could be perfectly usable but crawls to a halt due to all installed software. Now everything will have their associate always running service.


IMO that's mostly the fault of Windows not having a real package manager for so long. There's no way for software to know that it needs an update unless it runs a background service to constantly check. So either your users constantly run outdated software (which is one of the reasons companies love offering their product as SaaS) or the users have to check manually (which users won't do). Some software checks when you run, but a lot of times I just need to open Excel and get to work, so I'm going to click "Skip this version" and keep going.

Honestly I don't see really any good way to handle it without some background service. It's just nicer when the OS has a way to handle it built in.


> There's no way for software to know that it needs an update unless it runs a background service to constantly check.

That is required only if you need to update the app when you are not using it. Apps can check for updates when you run them and then let you decide when to install the update/or skip it/etc.

Package manager would be good, but not possible on Windows given the amount of commercial software. Companies are not going to seed control to the Microsoft when they can potentially up-sell you via their b/g update services or do other kinds of advertising. I doubt MS would want to play rough with their partners either.


Surely they can, but tell it to Adobe, Apple, Oracle (Java), Google (Chrome), Razer,


Unfortunately, they already know this.


That's why we now have the ms strlore with an auto updater. Furthermore,you can produce a UW0 application without putting it on the store, and still use the auto-update functionality - the os will check a URL of your choosing for a new version.


Is this formalizing a way for any app to implement a scripting engine?


Please do something like this for Edge Linux too! (once it arrives)


So, it's #! for Windows, except complicated because Windows.


Read sveiss' comments above for a good explanation of what it is/does.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: