Skip to content

Latest commit

 

History

History

web

Slow Reader Web Client

See the full architecture guide first.

Project Structure

We use Svelte as the UI framework and Vite as the builder.

  • main/: app entry point and global things like design tokens.
  • pages/: Svelte components for pages.
  • ui/: shared components between different pages. Some people call it “UI kit”.
  • public/: static files like favicon and manifests.
  • stores/: web client’s own smart stores. For instance, router on top of URL using Nano Stores Router.
  • postcss/: PostCSS plugins to check CSS and optimize it. Check the plugin’s descriptions for more information.
  • stories/: visual tests for pages and UI components by Storybook. The main way to test web client.
  • scripts/: scripts to check for popular errors, optimize files after Vite build, and deploy. Check the script’s descriptions for further details.
  • test/: unit tests for some parts of the web client.
  • dist/: pnpm build will build the result here for deployment.
  • .storybook/: visual tests tool config.
  • index.html: builder entry point. It also contains styles for the app loading state.
  • Dockerfile and nginx.conf: web server to serve web client for staging and pull request preview servers.
  • .browserslistrc: browsers, which we support. See actual browsers list.
  • .size-limit.json: budget for JS bundles and whole webpage size. Don’t be afraid to tune the limit. We put it so tight that it makes you feel a small pain every time you add a significant amount of code.

Tools

  • Storybook to check styles for popular mistakes and keep CSS code style formatting.
  • Size Limit to prevent accidental bloat of JS bundle size, for instance, by adding a big dependency.
  • Browserslist is the single config with target browsers for team and all tools.
  • KeyUX implements keyboard hotkeys and focus management around aria- attributes.

Scripts

  • cd web && pnpm test: run all web client tests.
  • cd web && pnpm visual: run visual test server.
  • cd web && pnpm production: start web client production build locally.
  • cd web && pnpm build: build production files in web/dist/.
  • cd web && pnpm size: check the JS bundle size of the production build.

Design System

All colors must be declared in main/colors.css. We are using Harmony Color Palette and oklch() format.

Sizes and paddings should use --padding-s--padding-xl tokens from main/common.css.

Fonts are declared in main/common.css. We are using system font to support all possible writing systems in posts.

For icons, we use Material Design Icons and <Icon> component.

<script lang="ts">
  import { mdiAccount } from '@mdi/js'
</script>

<Icon path={mdiAccount} />

Test Strategy

Since clients don’t have much logic (we moved logic to the client core), we don’t need to use unit tests.

We can use only visual tests to test web clients UI. We are using Storybook and Chromatic snapshots.

Since we use a free plan, we run Chromatic on CI only daily.

We deploy the latest Storybook of main branch to staging: dev.slowreader.app/ui/

You can check Storybook of pull request by adding /ui/ to the preview deploy URL: like https://preview-100---staging-3ryqvfpd5q-ew.a.run.app/ui/

But those visuals can be very complex. We do not just test buttons in different states. We test whole pages by mocking network requests and stores states. We use small JS in stories to test animations or some JS code.

You can use <Scene> to change core stores and mock HTTP.

Deploy

  1. Pull request preview: the CI will publish a View deployment link to pull request events in 2 minutes.
  2. Staging: main branch is on dev.slowreader.app.

To return app HTML on app’s routes, we export RegExp of all routes from web client to routes.regexp file and use it in nginx.conf or Logux HTTP sever.

Both preview and staging have Storybook at /ui/ route.

In staging and production are using Google Cloud Run to run Nginx server with assets of web client. For pull request preview and self-hosted we use Logux sever to serve assets.

All Google Cloud settings are documented in script.