hwy

Hwy is a fullstack web framework for driving a (p)react frontend with a Go backend. Includes end-to-end typesafety, file-based nested UI routing, and much more.

BSD-3-CLAUSE License

Downloads
572
Stars
319
Committers
2

Bot releases are visible (Hide)

hwy - v0.11.0 Latest Release

Published by sjc5 6 months ago

hwy - v0.10.0

Published by sjc5 6 months ago

hwy - v0.9.0

Published by sjc5 6 months ago

hwy - v0.8.5

Published by sjc5 6 months ago

hwy - v0.8.4

Published by sjc5 6 months ago

hwy - v0.8.2

Published by sjc5 6 months ago

hwy - v0.8.1

Published by sjc5 6 months ago

hwy - v0.8.0

Published by sjc5 6 months ago

This release is the result of a major re-write of the framework and represents what is essentially a pivot. New documentation is forthcoming.

hwy - v0.7.2

Published by sjc5 10 months ago

This release adds support for a watchInclusions array in your hwyConfig.dev object. This is helpful if you want to re-compile your Hwy project based on upstream activity in a broader monorepo. It works just like watchExclusions, except it's the opposite.

hwy - v0.7.1

Published by sjc5 11 months ago

Make experimental, HTMX-aware Suspense component asynchronous.

hwy - v0.7.0

Published by sjc5 11 months ago

v0.7.0 release notes


IMPORTANT – API Changes to Support Hono First-Class Async JSX Support (and experimental streaming)

Hono recently released their highly anticipated version 3.10.0 release, which includes first class support for async components using normal syntax (no more {await outlet()} hacks!) as well as experimental streaming and Suspense support. Incredible stuff!

Here's how to bring your app up to date:

Upgrade dependencies

Before making the changes described below, upgrade to the latest version of Hwy (all packages, >=0.7.0) and the latest version of Hono (>=3.10.0). If you're using the node server, also make sure to update @hono/node-server to at least >=1.2.3.

RootOutlet and renderRoot

  • Your rootOutlet no longer needs to be rendered like {await rootOutlet({ ...props })} and instead is now called RootOutlet (traditional JSX component capitalization) and can simply be used as <RootOutlet {...props} /> (no await needed).
  • renderRoot now takes a single object argument instead of three ordered arguments. Before, the three ordered arguments were (in order), c (Hono Context), next (Hono Next), and rootMarkup. Now it's an object with c, next, and root (same fundamental shape as before) as required properties, as well as an optional property experimentalStreaming property, which defaults to false.

OLD ❌

app.all("*", async (c, next) => {
  return await renderRoot(c, next, async ({ activePathData }) => {
    return (
      <html lang="en">
        ...
        <body {...props}>
          {await rootOutlet({
            activePathData,
            c,
            fallbackErrorBoundary: () => {
              return <div>Something went wrong.</div>;
            },
          })}
        </body>
      </html>
    );
  });
});

NEW ✅

app.all("*", async (c, next) => {
  return await renderRoot({
    c,
    next,
    experimentalStreaming: true, // optional, defaults to false
    root: ({ activePathData }) => {
      return (
        <html lang="en">
          ...
          <body {...props}>
            <RootOutlet
              c={c}
              activePathData={activePathData}
              fallbackErrorBoundary={() => {
                return <div>Something went wrong.</div>;
              }}
            />
          </body>
        </html>
      );
    },
  });
});

Outlets

Additionally, outlet components (returned in PageProps and used to render nested child routes) are similarly now capitalized and no longer need the weird async call syntax.

OLD ❌

export default async function ({ outlet }: PageProps) {
  return (
    <Parent>
      {await outlet()}
    </Parent>
  );
}

NEW ✅

export default async function ({ Outlet }: PageProps) {
  return (
    <Parent>
      <Outlet />
    </Parent>
  );
}

Much better! Thanks Hono!

Experimental Streaming and Suspense Support

  • You can turn on experimental streaming support by flipping the experimentalStreaming property mentioned above to true (e.g., renderRoot({ ...props, experimentalStreaming: true})). This will let you add Suspense (experimental!) from Hono to your app. Streaming doesn't work well with HTMX or hx-boost at the moment, so we exported our own Suspense component from hwy core, which simply uses Hono's Suspense component for non-HTMX requests, and directly returns children for HTMX requests. Effectively, this means that you can use suspense for initial page loads, and any subsequent navigations (assuming you're using hx-boost) will be fully rendered before being swapped out by HTMX. If you want to try it, you can do this:
import { Suspense, type PageProps } from "hwy";

export default async function({ c }: PageProps) {
  return (
    <Suspense c={c} fallback={<div>Loading...</div>}>
      <SomeAsyncChild />
    </Suspense>
  );
}

IMPORTANT – Other API changes

DataFunctionArgs type is now DataProps

Renames DataFunctionArgs type to DataProps. This name is more consistent with its sibling type PageProps.

OLD ❌

export function loader({ params }: DataFunctionArgs) {
  return <div />
}

NEW ✅

export function loader({ params }: DataProps) {
  return <div />
}

As a reminder, DataProps (previously DataFunctionArgs) is the appropriate type for the single object parameter to both Hwy loaders and actions. It takes the same generics as before.

New stuff

@hwy-js/utils package

We added a new package called @hwy-js/utils that includes some new goodies. They should be considered experimental.

getFormStrings

We added a utility called getFormStrings to @hwy-js/utils. getFormStrings takes a generic of all the string literal types you expect in form data (essentially, the names of the inputs you submitted in a form) and returns them in an object. Very handy. An earlier version of this was included in templates as extractSimpleFormData. We made it a little more robust, renamed it, and tossed it in a utils package.

Usage:

const data = await getFormStrings<"email" | "password">({ c });
console.log(data);
// { email: "[email protected]", password: "123" }

Client cookie events

We also added a brand new client cookie event helper system to the new @hwy-js/utils package. Very useful for triggering client-side toasts and stuff like that from server loaders or anywhere you have access to the Hono context object. This approach (cookie-based RPC) is a bit more robust than HX-Trigger because it will always persist across redirects (because it's cookie-based, not header-based). We'll document it eventually, but you can probably figure it out just by peaking into the source code. It's pretty cool!

More redirect options

Adds an option to the redirect helper to trigger a redirect using HX-Location instead of redirecting with Hono's c.redirect method. This will likely mostly be useful when you are calling an endpoint manually using fetch or htmx.ajax or similar. To opt in to that behavior, pass useHxRedirect: true to the redirect options arg.

Bug fixes

  • Fixes some bugs in the redirect helper, as well as some bugs in the data function handlers which resulted in thrown redirects not being sent. Now fixed.
  • Corrected some esbuild settings for browser-targeted files.
  • Fixes an issue where dev server exceptions weren't being appropriately handled. Practically speaking, this fixes an issue where you'd get EADDRINUSE when trying to restart your dev server. Very annoying, now fixed.

General

  • Removes some unused / unnecessary internal API surface.
  • Bumps dependencies.
  • Switch default dev port in newly bootstrapped projects back to 3000. The prior setting (5555) is the prisma studio default port, and it's not really necessary to try to use a unique one. The traditional 3000 is best, and users can change to whatever they want.
hwy - v0.6.0

Published by sjc5 12 months ago

v0.6.0 – Idiomorph

Overview

This release:

  • Makes it way simpler to use idiomorph with Hwy
  • Adds idiomorph as an option to getDefaultBodyProps
  • Adds new @hwy-js/client package, which allows us to drastically simplify the default client.entry.{js,ts} file
  • Includes idiomorph and new client helpers by default in new apps bootstrapped with create-hwy

Upgrade instructions

To upgrade your existing Hwy app to use idiomorph, do the following:

Step 1

npm i [email protected]
npm i -D @hwy-js/[email protected] @hwy-js/[email protected] @hwy-js/[email protected] idiomorph

Why is idiomorph a dev dependency? Because it's bundled into your client entry at build time (no need for idiomorph to live next to Hono/Hwy on your server other than as part of your static assets).

Step 2

Then, add { idiomorph: true } to your getDefaultBodyProps call (which returns the props you spread into your app's root body tag). For example:

<body {...getDefaultBodyProps({ idiomorph: true })}>

Or, if you're using NProgress, you can do this:

<body {...getDefaultBodyProps({ idiomorph: true, nProgress: true })}>

Step 3

Then, update your client.entry.{ts,js} file to the following:

import { initHtmx, initIdiomorph } from "@hwy-js/client";

initHtmx().then(initIdiomorph);

Or, if you're using NProgress, you can do this:

import { initHtmx, initIdiomorph, initNProgress } from "@hwy-js/client";

initHtmx().then(initIdiomorph).then(initNProgress);

New app instructions

Just run:

npx create-hwy@latest

Idiomorph will be included by default for new apps created with create-hwy.

Bonus

  • Adds @nsaunders's very cool CSS Hooks package (https://css-hooks.com) as an option alongside Tailwind and vanilla CSS when you bootstrap a new Hwy app using create-hwy! Closes #40.
hwy - v0.5.0

Published by sjc5 12 months ago

Core

  • Slight refactor to runBuildTasks.
  • Remove unnecessary key={something} code in components. Probably originated from co-pilot thinking these were React components and me not catching it 🙃.
  • Update get-matching-path-data-internal.ts to fix a routing bug where in certain narrow situations, index files would incorrectly render when the ultimate catch should have rendered, plus another bug (caught by new tests 🥳) where sometimes a non-ultimate splat route would be discarded when it shouldn't be, which caused the ultimate splat to render when it didn't need to.
  • Simplify / shrink paths.js output and getMatchingPathData API.
  • Fix a couple instances of snake_case accidentally making its way into public API (loader_args and action_args are now loaderArgs and actionArgs).

Templates in create-hwy

  • Updates to create-hwy templates, including adding an example of some-page.client.ts usage (classic incrementing counter button), plus some necessary changes to the create-hwy scripts to facilitate that.
  • Add all potential third-party packages to create-hwy dev deps so their versions can be read at runtime.
  • Fix instances of charSet that should have been charset.
  • Remove a stray reference in templates to watchExclusions, which now belongs in hwy.config.{ts,js}.
  • Update generated README for Cloudflare Pages template to mention needing to set nodejs_compat compatibility flags in Cloudflare dashboard.
  • Add Node types to compiler options if your deploy target is Node or Vercel Lambda in create-hwy.
  • De-Tailwindify the preflight CSS reset file (basically just remove the Tailwind-specific theme function calls).

Docs

  • Begin refactoring docs to make updates and outside contributions easier. Work on this is ongoing.

General

  • Bump dependencies.
  • Add scripts to make it easier to bump deps across entire repo.
  • Add other time-saving, non-outward-facing helper scripts across repo.
  • Add bundle size badge to docs and READMEs.

Testing

  • Add new Hwy global test_dirname to make router more easily testable.
  • Add vitest and add tests for getMatchingPathData, the function that needs testing the most (a very good place to start).
  • Integrate vitest as appropriate into dev and publish scripts.
  • Update testers/routes code to catch more edge cases.

Replace changesets with custom scripts

  • Removed changesets CLI. Wasn't worth it. Replaced with a few custom scripts to make it easier to do intra-repo versioning and publishing without having to deal with the changesets CLI. Much nicer to work with. Might generalize and publish as its own package sometime, we'll see.
hwy - v0.4.0

Published by sjc5 12 months ago

First off, huge shoutout to @jharrell for his debugging and research assistance on this PR related to adding Cloudflare Pages support! Thank you!

  • Cloudflare Pages is now supported! Closes #6.

  • Added changesets. Closes #14.

  • Adds a hwy.config.ts / hwy.config.js file to the root of your project for setting up dev settings and deployment target, and probably other things in the future. As annoying as config files are, this simplifies a lot of things and is not too much to ask for a framework.

  • Removes a lot of complexity / variance in build commands and deploy target hacks, as now we can just read the deployment target from the Hwy config and handle everything in Hwy's centralized build step.

  • Adds a new @hwy-js/build package, splitting up the live refresh stuff (stays in @hwy-js/dev) from the build stuff.

  • In your src/main.tsx file:

    • {hwyDev?.DevLiveRefreshScript()} is now just <DevLiveRefreshScript />
    • <ClientEntryScript /> is now <ClientScripts activePathData={activePathData} />. This is to enable the new client scripts functionality mentioned below.
  • Added an option to ship client-side JS (including from TS files if you want) by adding a sibling page-name.client.ts or page-name.client.js file to your page. This becomes basically global JS for that page, and anything imported will be bundled into that page's script, which is built into the public folder and referenced in the document head when you visit that page. This will be better documented later. Closes #15.

hwy - @hwy-js/[email protected]

Published by github-actions[bot] 12 months ago

hwy - [email protected]

Published by github-actions[bot] 12 months ago

Patch Changes

  • e889767: more specific docs link in cli output
hwy - v0.4.1

Published by github-actions[bot] 12 months ago

hwy - @hwy-js/[email protected]

Published by github-actions[bot] 12 months ago

Package Rankings
Top 7.58% on Proxy.golang.org
Top 7.53% on Npmjs.org