| 1 | - imports at the bottom |
| 2 | - order your file by importance. |
| 3 | - 'G' to jump to imports, etc |
| 4 | - prefer namespace imports |
| 5 | - easier to type and refactor. easier to read. |
| 6 | - large files are okay |
| 7 | - all files are their own library |
| 8 | - split files up by making components modular, not by "oh it's too big" |
| 9 | - engine/render.ts is a standalone library, in order to split JSX, Suspense, |
| 10 | and Marko out, the main file was made modular. |
| 11 | - lowercase |
| 12 | - name objects ultra-concisely |
| 13 | - filenames are often one word describing what they contain |
| 14 | - avoid useless descriptors like "utils", "helpers", and "data" |
| 15 | - examples |
| 16 | - async.ts contains all the async library functions. |
| 17 | - watch.ts contains the file watcher and watch-reload mode. |
| 18 | - render.*, Io |
| 19 | - be ultra-concise in comments |
| 20 | - no "discarded" variables, embrace `void x` |
| 21 | - makes code more readable |
| 22 | - note how i want to write a lint for this |
| 23 | - note the one proposal i want about void |
| 24 | - push the ts inference engine (as const, ReturnType, etc) |
| 25 | - reduces how much you repeat yourself making it easier to refactor things |
| 26 | - use the code as the source of truth |
| 27 | - push the ts inference engine (generics) |
| 28 | - do not implement crazy things with the TS engine, instead use generic input |
| 29 | types, and then use regular control to narrow and transform the return type. |
| 30 | source of truth is your code. |
| 31 | - UNWRAP, ASSERT utility globals are amazing |
| 32 | - ban postfix '!' |
| 33 | - stripped for production frontend builds |
| 34 | - destructure often |
| 35 | - use the one example from work lol |
| 36 | - package.json "imports" are amazing |
| 37 | - remapping |
| 38 | - implementation switching |
| 39 | - testing |
| 40 | - embrace the web and node.js APIs |
| 41 | - sitegen relies on so many node features that bun and deno fail to run it. |
| 42 | - overlay modules are great |
| 43 | - avoid dependencies |
| 44 | - once you build your own mini standard library you win |
| 45 | - talk about regrets with mdx |
| 46 | |
| 47 | ## imports at the bottom |
| 48 | |
| 49 | Here is an abridged version of my website's `backend.ts`. When reading it from |
| 50 | top to bottom it is immediately obvious that it is a Hono web server. |
| 51 | |
| 52 | ```ts |
| 53 | // This is the main file for paperclover.net's server. |
| 54 | const app = new Hono(); |
| 55 | const logHttp = console.scoped("http", { color: "magenta" }); |
| 56 | |
| 57 | // Middleware |
| 58 | app.use(...); |
| 59 | ... |
| 60 | |
| 61 | // Backends |
| 62 | app.route("", require("./q+a/backend.ts").app); |
| 63 | ... |
| 64 | |
| 65 | export default app; |
| 66 | |
| 67 | ... |
| 68 | |
| 69 | import { type Context, Hono, type Next } from "hono"; |
| 70 | import { logger } from "hono/logger"; |
| 71 | import { trimTrailingSlash } from "hono/trailing-slash"; |
| 72 | import * as assets from "#sitegen/assets"; |
| 73 | import * as admin from "./admin.ts"; |
| 74 | import * as console from "@paperclover/console"; |
| 75 | ``` |
| 76 | |
| 77 | Since `import`/`export` statements are hoisted like `var` and `function`, the |
| 78 | position of these statements within the file does not matter. The imported |
| 79 | modules have to be loaded first before this file can start. With this, I've |
| 80 | found it nicer to sort the file by _importance_ rather than by arbitrary rules |
| 81 | dictated by how C-style `#include`s worked. |
| 82 | |
| 83 | Start with a documentation comment, then the most important |
| 84 | functions/variables/types, sort the file by importance. Imports are not really |
| 85 | important since you very quickly get to know where common namespaces come from. |
| 86 | And since they're at the bottom, you can just press `G` in Vim or `CMD+Down` on |
| 87 | the Mac to scroll to the end of the file. |