Simple React SPA for ajanottaja
  • TypeScript 98.1%
  • HTML 1.1%
  • CSS 0.6%
  • JavaScript 0.2%
Find a file
2026-01-18 19:38:33 +01:00
src chore: Deprecate project 2026-01-18 19:34:35 +01:00
.editorconfig Minimal viable frontend in vitejs + react 2021-08-03 20:34:31 +02:00
.gitignore Minimal viable frontend in vitejs + react 2021-08-03 20:34:31 +02:00
.npmrc Initial supabase-backed frontend setup (#12) 2022-08-21 13:03:56 +02:00
.prettierrc Work in progress improved API and config setup 2021-08-18 22:01:17 +02:00
bun.lockb feat: Punch card chart 2025-02-27 21:52:24 +01:00
index.html feat: New loading screen 2025-02-06 22:54:26 +01:00
LICENSE Initial commit 2021-07-31 13:08:19 +02:00
package-lock.json fix: Broken lockfile 2026-01-18 19:38:33 +01:00
package.json build: Use Vite with rolldown 2025-06-02 15:57:45 +02:00
README.md chore: Update README to reflect migration to Supabase backend 2025-02-06 22:33:04 +01:00
tsconfig.json feat: complete design overhaul and port to tailwindcss (#20) 2025-02-04 23:02:23 +01:00
tsconfig.node.json feat: complete design overhaul and port to tailwindcss (#20) 2025-02-04 23:02:23 +01:00
vite.config.ts feat: complete design overhaul and port to tailwindcss (#20) 2025-02-04 23:02:23 +01:00
windi.config.js chore: format all files based on prettier config (#15) 2022-11-06 11:05:32 +01:00

Ajanottaja - A simple time keeping tool

This is the frontend of the Ajanottaja time keeping tool. It is implemented in React.js using Vite as a build tool. The frontend runs on top of the Supabase backend.

Development

First clone the repository and create a local configuration file .env.local with the following content:

VITE_SUPABASE_URL=<your-supabase-url>
VITE_SUPABASE_ANON_KEY=<your-supabase-anon-key>

Then install dependencies and run the development script:

bun install
bun run dev

Testing

Tests are run using Jest. To run tests once off or in watch mode:

bun run test
bun run test -- --watch

Building

To build production build and bake in the configuration in the static output first set the configuration values and then run build command:

VITE_SUPABASE_URL=<your-supabase-url>
VITE_SUPABASE_ANON_KEY=<your-supabase-anon-key>
bun run build

Docker (WIP)

A Docker file and image will eventually be provided.

Hosting

As Ajanottaja's frontend is a simple single page app with static files you can host it in various ways.

Edge network (Cloudflare Pages)

The "official" instance of Ajanottaja is hosted using Cloudflare Pages. It is a service that allows you to build and host sites at Cloudflare's edge network. This gives users of Ajanottaja.app low latency access to the client side app assets world wide. Further more Cloudflare Pages scales effortlessly to as many users as needed. To host Ajanottaja's frontend with Cloudflare Pages consider mirroring the repository and connect it to your Cloudflare Pages account.

Another great edge network hosting option is Vercel.

Reverse proxies

You can build the static files and stick the /dist folder behind a reverse proxy. A few good options include:

License

Licensed under AGPLv3, see License.

In short this means you can:

  1. Copy, run, and redistribute the code for free
  2. Modify the code and run a public service, in which case source code MUST be released
  3. Modify the code and run a private service (e.g. for yourself or your family) without releasing source code, but it is nice if you do
  4. You must retain the copyright in any modified work

The AGPLv3 license was chosen to keep the project and any forks open for the public good.

Rationale and philosophy

Initially the Ajanottaja frontend was to be built using ClojureScript. This would facilitate code-sharing between the backend and frontend. Especially shared schema models and routing library would have been a boon. It turned out however that Figwheel's file watcher did not support the latest MacOS. While interop is reasonably simple in ClojureScript, that too presents a bit of overhead.

In the end Vite with its modern and fast developer experience and TypeScript won out. The end result is a slightly smaller bundle size and access to the latest functionality in React.

The code is built with a few main goals in mind:

Validate and coerce or transform values at the edges.

Using the superstruct library it is possible to validate and coerce values. When done at the edges, i.e. were you receive responses from the API, the rest of the app can use the values safely.

Provide meaningful abstractions

Code wraps hooks like useSWR in meaninful abstractions to make code more readable. Pages should not care how http calls are made or how data is validated. Combining useSWR, the fetch function, and superstruct's validation provide a cohesive whole for fetching data.

Only test meaningful application logic

Testing React virtual dom rendering is mostly wasteful. It is better to test the functions that operate on or change data. When the UI becomes more stable E2E browser tests can have value.