The carefree-board project, or cfb for short, is a lightweight, modular, and
easy-to-use board library.
boardcan be thought of 'drawboard' / 'canvas' / '2D graphics world' / ..., depending on what you want to build with it (e.g., a drawing app, an infinite canvas, a 2D game, ...).
carefree-board needs deno 2.x to run. After you have installed
deno, a web-native demo can be launched by:
deno task run:webThis will start the demo at http://localhost:1245, and you can play with the cfb.
Currently this demo only supports:
- Display some contents on the screen, namely:
- Two squares.
- A 'Hello, World!' text.
- Respond to pointer events - you can drag the contents around!
- Undo / Redo the dragging actions by clicking the corresponding 'buttons'.
This demo can run on both desktop and mobile browsers, but there are some additional features that are only available on desktop browsers:
- Undo / Redo by pressing the
Ctrl+z/Ctrl+Shift+zkeys. - Zoom in / out by rolling the mouse wheel while pressing the
Ctrl/Metakey. - Move the board globally by:
- pressing the
Spacekey and dragging the mouse. - rolling the mouse wheel to move up / down.
- rolling the mouse wheel while pressing the
Shiftkey to move left / right.
- pressing the
You can also visit here, which is hosted by
deno deploy, to play around with the demo.Notice that I put single quotes to 'buttons' - this is because they are not real buttons, but just rectangle
nodes that can respond to pointer events.
carefree-board is still in its VERY EARLY stage, and mainly serves as a POC. The
final goal is to define a set of abstract interfaces that can be extended to everything
related to 2D graphics.
All submodules are structured under a deno workspace, and their functionalities are as
follows:
cfb-core: implements the core components ofcfb.cfb-svg: implementssvgexporters forcfb.cfb-web: a web-native renderer forcfbthat transpiles the data structures intodomelements.
It REALLY took me couple of days to figure out how to manage a hybrid deno
monorepo. Let me define it - a hybrid deno monorepo is a monorepo that:
- All members are
denofirst modules. - Some members are
browserspecific modules, and need to have a runnable frontend demo.
The second part is where nightmare begins. I struggled quite a bit to figure out how to correctly do the linkings / bundlings / servings. Finally I made it to what I think simple and elegant, and I'd like to share some experience here:
Hint: after all these setups, everything is TIDY and BLAZINGLY FAST compared to the traditional
webpack/rollup/tsconfig/package.json/ ... mess, which makes me feel all the efforts are worth it!
- Export everything in
main.ts(to distinguish frommod.tsthat can be used in bothnodeandbrowserenvironments) (exmaple). - Write startup codes in
public/index.ts, which may import the workspace members and setup the application (example). - Use
esbuildin adenoscript to bundleindex.ts(notmain.ts!) into a singlejsfile. It's common practice here towatchfor changes (example). - Write an
index.htmlthat includes the bundledjsfile. If the startup codes need to refer to some concretedomelements, make sure to include the<script>tag after the elements are defined (example). - Use
Deno.serveto serve theindex.html(example). - Happy coding!
One implicit step is that we need to create an
imports.jsonexplicitly. This step is to makednt/esbuild/deno publishhappy, and I think it can (and maybe should) be skipped once thedenoecosystem becomes more mature.
Some common deno tasks for development:
deno task check: will run bunch of checks asynchronously, includingfmt,lint,test, drypublish, etc.deno task bump: bump the patch version in eachdeno.jsonfile no matter what.
Some common deno tasks for CI:
deno task build: build into npm packages withdnt.deno task publish:npm: publish the npm packages.
There are several module-specific tasks as well:
deno task {cmd}:web: tasks specific tocfb-web, seecfb-websection below for more details.
A common .vscode/settings.json for this project is as follows:
{
"deno.enable": true,
"deno.lint": true,
"typescript.preferences.preferTypeOnlyAutoImports": true,
"[json]": {
"editor.defaultFormatter": "denoland.vscode-deno"
},
"[markdown]": {
"editor.defaultFormatter": "denoland.vscode-deno"
},
"[typescript]": {
"editor.defaultFormatter": "denoland.vscode-deno"
}
}I did not use
{
"...": "...",
"editor.defaultFormatter": "denoland.vscode-deno"
}directly because I found its priority is not high enough in my case.
A common setup for developing cfb-web is as follows:
- Open two terminals.
- In the first terminal, run
deno task dev:web, this should be able to watch ALL changes in the workspace. - In the second terminal, run
deno task start:web, this should start a local server athttp://localhost:1245and you can test the changes in the browser. Notice that there are no hot-reload, so you need to refresh the page manually when changes are made.