Demo project, showing the use of Svelte, TypeScript, and Express to build a weather forecast web app, powered by the AccuWeather API
This is a demo full-stack web application, which uses the AccuWeather API to power a multi-day forecast, with selectable location.
It uses Svelte, TypeScript, HTML, CSS, and other web technologies.
There are a few values that are configurable for the backend and frontend.
Configuration for the backend can be done through either:
- Setting the values via environmental variables
- Example (Windows):
set port=3002 && npm run serve
- Example (Windows):
- Copying
/backend/.env.example.json
to/backend/.env.json
and filling in the values
🚨 In order to run this app you MUST provide a valid value for
accuWeatherKey
(which should be your API key), through either of the above methods.
For the full list of values you can configure for the backend, refer to the example .env.json
file.
For the front-end, the only real configuration value is BACKEND_BASE
, which can be used to decouple the serving of the API from the static files (see "Static Serving" section for details).
Although you can cd
to either /backend
or /frontend
and run each part of the app individually from its directory, all commands are exposed through the root package.json
of this project for convenience.
From the root directory, here is a sample workflow for if you just cloned this repository:
npm install
:- Installs all shared dependencies, and then for each part of the app separately (through
postinstall
hook)
- Installs all shared dependencies, and then for each part of the app separately (through
- Now that dependencies are installed, you can pick how to run or work on the app:
npm run dev
- This runs both parts in dev mode, and watches for changes across the entire codebase and reloads if it sees any
npm run build
- Builds both the frontend and backend. For Svelte, this means producing an optimized static HTML / JS / CSS output for hosting. For the backend, this means transpiling TypeScript to JS.
npm run serve
- This serves both the server (internal API) and frontend.
- Important: Having run
npm run build
is a pre-requisite to this command -serve
is expecting that there is already build output ready to serve or execute. - Alternatively, you can run
npm run start
, which runsbuild
and thenserve
- Reminder: The API requires a valid AccuWeather API Key to run, passed via
accuWeatherKey
. See "Configuration" for details.
Many commands also have optional suffixes if you don't want to work on both parts of the app at the same time. For example, you can use
npm run dev:backend
instead ofnpm run dev
, if you just want to work on the API without touching the frontend.
This is a mono-repo, which contains both the frontend, backend, and commands to run both.
- Front-end is built with Svelte, TypeScript, and lots of HTML and CSS.
- Vite is used for tooling; bundling, local HMR, production builds, etc.
- The Halfmoon CSS Framework is used, but mostly for some utility classes and default styling
- CSS variables are used liberally to make theming and tweaking easier
- Back-end is using NodeJS, Express, and TypeScript
- Since I don't need much in the way of a backend for this (mostly just proxying AccuWeather requests and static file serving), I kept things simple. For a more robust application, I would probably pick and use a full-fledged NodeJS framework, like NestJS or Hapi.
- If I knew that this app was never going to be scaled beyond what it currently is, I would strongly consider serverless as a contender - the entire back-end could realistically be built out as one or two functions (and deployed on something like Netlify Functions, AWS Lambda, or GCP Cloud Functions).
- There is some basic CSRF protection built-in, backed by cookies
- There are some TypeScript types that are shared between the two parts
- Some of the "extra" scripts in
package.json
are specific to DigitalOcean deployment settings
By default, this project will serve both the API and the frontend from the same Express server. However, I also made it configurable so that you can decouple them easily.
To decouple, before running build:frontend
, set an environmental variable for BACKEND_BASE
to point to the hosted Express endpoint. Then run build:frontend
, and after it finishes, you can now take the optimized /dist
and serve anywhere that lets you serve static files; Netlify, various CDNs, shared hosting, etc.
The "automatic location" feature, based on IP address, uses AccuWeather's IP-to-geolocation service, which doesn't always return the most accurate results. To counter this, users are asked whether or not the "guessed" location is good enough for them, or if they would like to manually select a location, before forecasting data is fetched.
Responsive
If I had more time to work on this, here are the things I would focus on as top priority:
- Localization
- Tests!
- Client-side caching of certain values (such as last location used)
- Also pushing to browser location history and setting / restoring via query string for shareable URLs.
- Server-side caching, to the extent that makes sense
- For example, per location forecasts could be cached for a short duration. Although a small tweak, if this was scaled up to serve millions of users, a tweak like that could avoid thousands of duplicate requests for popular zip codes.
- Get better graphical assets (such as the weather icons)