I made a @uatp organisation on npm. (I mean, why not? But also to get the command above to work, the package has to be on the npm registry.) I will post about this on Slack and add everyone who wants to be added.
How to review this PR?!
Obviously, the code changes associated with this PR are slightly ridiculous and virtually impossible to review. I would like to suggest that you not evaluate it based on the code, but rather the effect ('try this out' section above).
Write a script that runs an interactive prompt, copies the template package to wherever the user wants, and modifies the code inside it to include/remove languages. This script is itself part of a package, called @uatp/create-web (essentially, when you run npm create @uatp/web, npm searches for this package and runs its main script).
I renamed the three packages respectively to all be @uatp/...; the library is now components, the template is template, and the web creation script is create-web.
I published two of the packages to npm so that they could be tested. One is the create-web one, of course: https://www.npmjs.com/package/@uatp/create-web
The other is components. Why does components need to be published at this stage? See below.
As part of this PR, I've also removed some of Dustin's backend-loading code; I've replaced it with something I understood a bit better. Sorry!! For example the loading screen I think no longer appears and the initialisation calls are rather more dumbed down. My hope is that it is not too hard to add these back in as part of a separate PR.
Everything below this...
... is just finer detail. You don't really have to read it unless it interests you, or if you want to review this PR in more depth than 'works as expected'.
What does the repository reorganisation imply?
This PR will change how we view this repository. The repository contains the template, but the repository is not the template itself; it is code which generates the template.
Thus, most files will have to be considered from both a developer and a user standpoint. Take the simple example of a license. If we add a MIT license to the top level directory, this indicates that the entire repo structure is MIT-licensed. It does not mean that when someone runs npm create @uatp/web they will get a MIT license in their project: that is determined by the license file we put inside the template. This logic extends to other things, like documentation, as well as package.json.
From a workflow perspective, what this means is that you would only git clone this repository if you were a developer of the template. If you were just using the template, you'd just run npm create @uatp/web and be done.
I've documented some of these in the top-level repo README. I'm sure it can be more detailed, though.
This was a seriously difficult challenge because we want to accomplish several things:
Retain the functionality of the template itself, so that local development on the template isn't prohibitively difficult. If the template cannot be built as a package itself and run with pnpm dev, it's going to be very hard to iterate on it.
Avoid excessive code duplication. For example, we could simply have three different template repos, one for Python, one for Rust, and one with neither. The script would then just copy the appropriate directory. While this would work, it's not good as changes to Svelte code (for example) have to be made three times.
A middle ground between generality and complexity. We want to be able to work on the template and somehow use comments to indicate "this bit of code needs to go into the Rust part". We don't want to write a script that excises specific line numbers in specific files because that will break (not general enough). On the other hand, I'm also not keen on reimplementing a whole templating language like Jinja (too general; and besides, Jinja code isn't valid HTML, see (1)).
Yes, in the ci.yml GitHub Action workflow I've added tests which generate new web apps with Rust/Python/no backend and test that they build correctly.
Why didn't you use TypeScript for create-web?
Because then npm create @uatp/web has to needlessly pull in more dependencies before running, and we'd also have to add more bloat like tsconfig, eslint, etc.. For a script which is quite small and honestly isn't too hard to follow, I thought this was overkill. (As you can see in the commit messages, I started with TS and then ditched it.)
Why publish @uatp/components now to npm?
In this monorepo structure, our template app depends on the local version of components. This is specified using workspace: * in its package.json. This is exactly what we want for testing because we always want to test our local version of the template against the local version of the components.
When somebody sets up a new app using this template, they aren't going to have a workspace complete with the source code of the components library. (I mean, they could, in the sense that we could make the create-web script set that up for them — but it would be terrible practice because it would mean that every UA web app would bundle its own copy of the library.)
Thus, when setting up a new app for them, the create-web script has to modify package.json and specify an actual version of components to depend on. In general, we should assume that each version of the template app has a specific, known, version of components which it can reliably be built against. It will then be the user's responsibility to upgrade the version dependency if they want newer updates. (Note that this is true of every dependency in the template; components is not special in this regard.)
So, when a new user runs npm create @uatp/web, they will get a package.json that points to some version of @uatp/components, and if we don't publish components to npm now, they'll get an error when they try to pnpm i.
Does @uatp/template need to be published as well?
I don't think so, no.
But @uatp/create-web is published?
Yes, it's published so that npm create @uatp/web works correctly.
Closes #17
Test this out!!
Select Rust, Python, or none. Then
cd
to wherever you set it up, and:and view on http://localhost:5173.
Overall thoughts
Readme
I've updated quite a few parts of the readme, so maybe it's a good starting point of what the repo looks like now.
https://github.com/Urban-Analytics-Technology-Platform/web-app-template/blob/create-template/README.md
@uatp
on npmI made a
@uatp
organisation on npm. (I mean, why not? But also to get the command above to work, the package has to be on the npm registry.) I will post about this on Slack and add everyone who wants to be added.How to review this PR?!
Obviously, the code changes associated with this PR are slightly ridiculous and virtually impossible to review. I would like to suggest that you not evaluate it based on the code, but rather the effect ('try this out' section above).
Roughly, the steps I've had to do are:
Reorganise the repository. I modelled this after SvelteKit's example: https://github.com/sveltejs/kit/tree/main.
Write a script that runs an interactive prompt, copies the template package to wherever the user wants, and modifies the code inside it to include/remove languages. This script is itself part of a package, called
@uatp/create-web
(essentially, when you runnpm create @uatp/web
, npm searches for this package and runs its main script).I renamed the three packages respectively to all be
@uatp/...
; the library is nowcomponents
, the template istemplate
, and the web creation script iscreate-web
.I published two of the packages to npm so that they could be tested. One is the
create-web
one, of course: https://www.npmjs.com/package/@uatp/create-web The other iscomponents
. Why does components need to be published at this stage? See below.As part of this PR, I've also removed some of Dustin's backend-loading code; I've replaced it with something I understood a bit better. Sorry!! For example the loading screen I think no longer appears and the initialisation calls are rather more dumbed down. My hope is that it is not too hard to add these back in as part of a separate PR.
Everything below this...
... is just finer detail. You don't really have to read it unless it interests you, or if you want to review this PR in more depth than 'works as expected'.
What does the repository reorganisation imply?
This PR will change how we view this repository. The repository contains the template, but the repository is not the template itself; it is code which generates the template.
Thus, most files will have to be considered from both a developer and a user standpoint. Take the simple example of a license. If we add a MIT license to the top level directory, this indicates that the entire repo structure is MIT-licensed. It does not mean that when someone runs
npm create @uatp/web
they will get a MIT license in their project: that is determined by the license file we put inside the template. This logic extends to other things, like documentation, as well aspackage.json
.From a workflow perspective, what this means is that you would only git clone this repository if you were a developer of the template. If you were just using the template, you'd just run
npm create @uatp/web
and be done.I've documented some of these in the top-level repo README. I'm sure it can be more detailed, though.
The
create-web
script modifies the code?Yes, that was really fun. You can see the script in
packages/create-web/bin.js
andpackages/create-web/index.js
.This was a seriously difficult challenge because we want to accomplish several things:
pnpm dev
, it's going to be very hard to iterate on it.I've written up notes on how I did this, and added them as documentation accompanying this PR: https://github.com/Urban-Analytics-Technology-Platform/web-app-template/blob/create-template/packages/create-web/DEVELOPER_NOTES.md
Did you write tests?
Yes, in the
ci.yml
GitHub Action workflow I've added tests which generate new web apps with Rust/Python/no backend and test that they build correctly.Why didn't you use TypeScript for
create-web
?Because then
npm create @uatp/web
has to needlessly pull in more dependencies before running, and we'd also have to add more bloat like tsconfig, eslint, etc.. For a script which is quite small and honestly isn't too hard to follow, I thought this was overkill. (As you can see in the commit messages, I started with TS and then ditched it.)Why publish
@uatp/components
now to npm?In this monorepo structure, our template app depends on the local version of components. This is specified using
workspace: *
in itspackage.json
. This is exactly what we want for testing because we always want to test our local version of the template against the local version of the components.When somebody sets up a new app using this template, they aren't going to have a workspace complete with the source code of the
components
library. (I mean, they could, in the sense that we could make thecreate-web
script set that up for them — but it would be terrible practice because it would mean that every UA web app would bundle its own copy of the library.)Thus, when setting up a new app for them, the
create-web
script has to modifypackage.json
and specify an actual version ofcomponents
to depend on. In general, we should assume that each version of the template app has a specific, known, version ofcomponents
which it can reliably be built against. It will then be the user's responsibility to upgrade the version dependency if they want newer updates. (Note that this is true of every dependency in the template;components
is not special in this regard.)So, when a new user runs
npm create @uatp/web
, they will get apackage.json
that points to some version of@uatp/components
, and if we don't publish components to npm now, they'll get an error when they try topnpm i
.Does
@uatp/template
need to be published as well?I don't think so, no.
But
@uatp/create-web
is published?Yes, it's published so that
npm create @uatp/web
works correctly.