hype/README.md

8.1 KiB

🎪 hype

░▒▓███████████████████████████████████████████████▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓███████▓▒░░▒▓████████▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░░▒▓█▓▒░▒▓█▓▒░
░▒▓████████▓▒░░▒▓██████▓▒░░▒▓███████▓▒░░▒▓██████▓▒░
░▒▓█▓▒░░▒▓█▓▒░  ░▒▓█▓▒░   ░▒▓█▓▒░      ░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░  ░▒▓█▓▒░   ░▒▓█▓▒░      ░▒▓█▓▒░
░▒▓█▓▒░░▒▓█▓▒░  ░▒▓█▓▒░   ░▒▓█▓▒░      ░▒▓████████▓▒░
░▒▓███████████████████████████████████████████████▓▒░

hype wraps hono with useful features for fast prototyping:

  • HTTP logging (disable with NO_HTTP_LOG env variable)
  • Static files served from pub/
  • Page-based routing to .tsx files that export a JSX function in ./src/pages
  • Transpile .ts files in src/js/blah.ts via website.com/js/blah.ts
  • Helpers like css and js template tags.
  • Default, simple HTML5 layout with working frontend transpilation/bundling, or supply your own.
  • Optional CSS reset.
  • Optional pico.css.

Overview

Your project structure should be:

.
├── README.md
├── package.json
├── pub
│   ├── asset.txt
│   └── img
│       └── logo.png
├── src
│   ├── css
│   │   └── main.css
│   ├── js
│   │   ├── about.ts
│   │   └── main.ts
│   ├── shared
│   │   └── utils.ts
│   ├── pages
│   │   ├── _layout.tsx
│   │   ├── about.tsx
│   │   └── index.tsx
│   └── server.ts
└── tsconfig.json

URLs

In the above, /about will render ./src/pages/about.tsx.

The req JSX prop will be given the Hono request:

export default ({ req }) => `Query Param 'id': ${req.query('id')}`

To put a file in ./src/pages but prevent it from being server, preface it with _.

Layout

hype will wrap everything in a simple default layout unless ./src/pages/_layout.tsx exists, in which case it'll use the default export in that file.

Using the default layout, you can put TS in ./src/js/main.ts and css in ./src/css/main.css and they'll automatically work in your app.

Here's a starting point:

export default ({ children, title }: any) => (
  <html lang="en">
    <head>
      <title>{title ?? "hype"}</title>
      <meta charset="utf-8" />
      <meta name="viewport" content="width=device-width, initial-scale=1.0" />

      <link href="/css/main.css" rel="stylesheet" />
      <script src="/js/main.ts" type="module"></script>
    </head>
    <body>
      <main>{children}</main>
    </body>
  </html>
)

pico.css

To use pico.css with the default layout, create Hype with { pico: true }:

import { Hype } from "hype"

const app = new Hype({ pico: true })

You can also use pico in your custom layouts:

<link href="/css/pico.css" rel="stylesheet" />

css

CSS can be accessed via /css/main.css:

<link href="/css/main.css" rel="stylesheet" />

Or written inline using the css template tag:

import { css } from "hype"

export default () => (
  <div>
    {css`
      * {
        color: red;
      }
    `}
    <h1>Hello</h1>
  </div>
)

Install the vscode-styled-components VSCode extension to highlight inline css tags!

css reset

To use reset.css with the default layout, create Hype with { reset: true }:

import { Hype } from "hype"

const app = new Hype({ reset: true })

You can also use the css reset in your custom layouts:

<link href="/css/reset.css" rel="stylesheet" />

js

JS can be accessed (and transpiled) via /js/main.ts or /shared/utils.ts:

<script src="/js/main.ts" type="module"></script>

import your modules relatively, for example in main.ts:

import { initAbout } from "./about"
import utils from "./shared/utils"

Or written inline as transpiled typescript using the js template tag:

import { js } from "hype"

export default () => (
  <div>
    {js`
      window.onload = () => alert(welcomeMsg(Date.now()))

      function welcomeMsg(time: number): string {
        return "Welcome to my website!"
      }
    `}
    <h1>Hello!</h1>
  </div>
)

Install the vscode-styled-components VSCode extension to highlight inline js tags!

pub

Anything in pub/ is served as-is. Simple stuff.

utils

hype includes helpful utils for your webapp:

  • capitalize(str: string): string - Capitalizes a word
  • css Template Tag - Lets you inline CSS in your TSX. Returns a <style> tag
  • darkenColor(hex: string, opacity: number): string - Darken a hex color by blending with black. opacity 1 = original, 0 = black
  • isDarkMode(): boolean - Check if the user prefers dark mode
  • js Template Tag - Lets you inline JavaScript in your TSX. Transpiles and returns a <script> tag
  • lightenColor(hex: string, opacity: number): string - Lighten a hex color by blending with white. opacity 1 = original, 0 = white
  • rand(end = 2, startAtZero = false): number - Generate random integer. rand(2) flips a coin, rand(6) rolls a die, rand(20) rolls d20
  • randIndex<T>(list: T[]): number | undefined - Get a random index from an array. randIndex([5, 7, 9]) returns 0, 1, or 2
  • randItem<T>(list: T[]): T | undefined - Get a random item from an array. randItem([5, 7, 9]) returns 5, 7, or 9
  • randomId(): string - Generate a 6 character random ID
  • randRange(start = 0, end = 12): number - Generate random integer in range. randRange(1, 6) rolls a die
  • redirectBack(c: Context, fallback = "/"): Response - Redirect to the referrer, or fallback if no referrer
  • times(n: number): number[] - Generate array of integers. times(3) returns [1, 2, 3]
  • transpile(path: string): Promise<string> - Transpile a TypeScript file at path to JavaScript (cached by mtime)
  • unique<T>(array: T[]): T[] - Remove duplicates from array. unique([1,1,2,2,3,3]) returns [1,2,3]
  • weightedRand(): number - Generate random number between 1 and 10 with decreasing probability (1 is most likely, 10 is least)

Setup

  1. Add the dependency to your project:
bun add git+https://git.nose.space/defunkt/hype
  1. Add dev and start to package.json:
  "scripts": {
    "start": "bun run src/server.ts",
    "dev": "bun run --hot src/server.ts"
  },
  1. Use our tsconfig.json:
{
  "compilerOptions": {
    "lib": ["ESNext", "DOM"],
    "target": "ESNext",
    "module": "Preserve",
    "moduleDetection": "force",
    "jsx": "react-jsx",
    "jsxImportSource": "hono/jsx",
    "allowJs": true,
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "verbatimModuleSyntax": true,
    "noEmit": true,
    "strict": true,
    "skipLibCheck": true,
    "noFallthroughCasesInSwitch": true,
    "noUncheckedIndexedAccess": true,
    "noImplicitOverride": true,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "noPropertyAccessFromIndexSignature": false,
    "baseUrl": ".",
    "paths": {
      "#*": ["src/*"]
    }
  }
}
  1. Use Hype just like Hono in your src/server.ts, exporting app.defaults:
import { Hype } from "hype"

const app = new Hype()

app.get("/my-custom-routes", (c) => c.text("wild, wild stuff"))

export default app.defaults
  1. Enter dev mode
bun install
bun dev