npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@blitzjs/next

v2.0.8

Published

[![Blitz.js](https://raw.githubusercontent.com/blitz-js/art/master/github-cover-photo.png)](https://blitzjs.com)

Downloads

18,470

Readme

Blitz.js

Blitzjs Website

GitHub

Overview

The @blitzjs/next adapter exposes functions & components specific for the Next.js framework.

Setup

You can install @blitzjs/next by running the following command:

npm i @blitzjs/next # yarn add @blitzjs/next # pnpm add @blitzjs/next

Next Config

Blitz.js extends the next.config.js file by accepting a blitz property.

blitz?: {
  resolverPath?: ResolverPathOptions;
  customServer?: {
      hotReload?: boolean;
  };
};

Client

Example

Inside src/blitz-client.ts:

import {setupBlitzClient} from "@blitzjs/next"

export const {withBlitz} = setupBlitzClient({
  plugins: [],
})

Then inside src/pages/_app.tsx wrap MyApp function with the withBlitz HOC component.

import {ErrorFallbackProps, ErrorComponent, ErrorBoundary} from "@blitzjs/next"
import {AuthenticationError, AuthorizationError} from "blitz"
import type {AppProps} from "next/app"
import React, {Suspense} from "react"
import {withBlitz} from "src/blitz-client"

function RootErrorFallback({error}: ErrorFallbackProps) {
  if (error instanceof AuthenticationError) {
    return <div>Error: You are not authenticated</div>
  } else if (error instanceof AuthorizationError) {
    return (
      <ErrorComponent
        statusCode={error.statusCode}
        title="Sorry, you are not authorized to access this"
      />
    )
  } else {
    return (
      <ErrorComponent
        statusCode={(error as any)?.statusCode || 400}
        title={error.message || error.name}
      />
    )
  }
}

function MyApp({Component, pageProps}: AppProps) {
  return (
    <ErrorBoundary FallbackComponent={RootErrorFallback}>
      <Component {...pageProps} />
    </ErrorBoundary>
  )
}

export default withBlitz(MyApp)

API

setupBlitzClient({
  plugins: [],
})

Arguments

  • plugins: An array of Blitz.js plugins
    • Required

Returns

An object with the withBlitz HOC wrapper

Server

Example

Inside src/blitz-server.ts

import {setupBlitzServer} from "@blitzjs/next"

export const {gSSP, gSP, api} = setupBlitzServer({
  plugins: [],
})

API

setupBlitzServer({
  plugins: [],
  onError?: (err) => void
})

Arguments

  • plugins: An array of Blitz.js plugins
    • Required
  • onError: Catch all errors (Great for services like sentry)

Returns

An object with the gSSP, gSP & api wrappers.

Custom Server

The Blitz CLI supports running custom Next.js servers. This means you can compile both javascript & typescript while using the Blitz.js CLI to inject env variables. By default, the CLI checks for src/server/index.[ts | js] or src/server.[ts | js]

For more information about custom Next.js servers, check the official docs

Wrappers

All Next.js wrapper functions are serialized with superjson. That means you can use Date, Map, Set & BigInt when returning data. Another thing to note is that Blitz runs the middlewares from plugins before calling the Next.js request handler.

Examples

getStaticProps

import {gSP} from "src/blitz-server"

export const getStaticProps = gSP(async ({ctx}) => {
  return {
    props: {
      data: {
        userId: ctx?.session.userId,
        session: {
          id: ctx?.session.userId,
          publicData: ctx?.session.$publicData,
        },
      },
    },
  }
})

getServerSideProps

import {gSSP} from "src/blitz-server"

export const getServerSideProps = gSSP(async ({ctx}) => {
  return {
    props: {
      userId: ctx?.session.userId,
      publicData: ctx?.session.$publicData,
    },
  }
})

api

import {api} from "src/blitz-server"

export default api(async (req, res, ctx) => {
  res.status(200).json({userId: ctx?.session.userId})
})

For more information about Next.js API routes, visit their docs at https://nextjs.org/docs/api-routes/introduction

Concepts

Authenticate user before page loads

You may want to check if the user is logged in before your page loads. We’re going to use the getCurrentUser query inside getServerSideProps() by calling the query directly. Then you can check if the user is logged in on the server and use the built-in Next.js redirect property.

import {Routes, BlitzPage} from "@blitzjs/next"
import {gSSP} from "src/blitz-server"
import getCurrentUser from "src/users/queries/getCurrentUser"

export const getServerSideProps = gSSP(async ({ctx}) => {
  const currentUser = await getCurrentUser(null, ctx)

  if (currentUser) {
    return {
      props: {
        user: currentUser,
      },
    }
  } else {
    return {
      redirect: {
        destination: Routes.LoginPage(),
        permanent: false,
      },
    }
  }
})

Return types when data fetching on the server

You can set the types returned from the Next.js data fetching functions. All Blitz.js wrappers for the Next.js functions accept a generic. Same with the BlitzPage type.

So for example, we can use some typescript utilities to help use get the types returned by getCurrentUser()

import {Routes, BlitzPage} from "@blitzjs/next"
import {gSSP} from "src/blitz-server"
import getCurrentUser from "src/users/queries/getCurrentUser"

type TCurrentUser = Awaited<ReturnType<typeof getCurrentUser>>

export const getServerSideProps = gSSP<{user: TCurrentUser}>(async ({ctx}) => {
  const currentUser = await getCurrentUser(null, ctx)

  if (currentUser) {
    return {
      props: {
        user: currentUser,
      },
    }
  } else {
    return {
      redirect: {
        destination: Routes.LoginPage(),
        permanent: false,
      },
    }
  }
})

const Page: BlitzPage<{user: TCurrentUser}> = ({user}) => {
  return (
    <Layout title="Page">
      <div className="container">
        <p>User Page</p>
        {user && <p>{user.email}</p>}
      </div>
    </Layout>
  )
}

export default Page

Handling errors on initial page load

There’s an edge case where you may be throwing an error in a query that’s being called on an initial page load, causing a server error instead of hitting the <ErrorBoundary />. This is because when initially loading the page, there is no ErrorBoundary component rendered until _app.tsx is mounted. Though, this is expected behaviour, there is a workaround.

For an example, in a query where the user is not found you can create a NotFoundError() then return the status code.

export default resolver.pipe(resolver.zod(GetUser), async (input) => {
  const {id} = input

  const user = await db.user.findFirst({where: {id}})

  if (!user) {
    const userError = new NotFoundError("User not found")
    return {
      error: userError.statusCode,
    }
  } else {
    return {
      user,
    }
  }
})

Then on the server (in this case getServerSideProps()) you can call the query and if the error key is found in the return object then show an error.

export const getServerSideProps = gSSP(async ({ ctx }) => {

  const user = await getUser({ 1 }, ctx)
  if("error" in user) {
    return { props: { error: user.error}}
  } else {
    return { props: { user }}
  }
})

You can also catch server errors in _app.tsx and show the errors with a toast component.

function MyApp({Component, pageProps}: AppProps) {
  const getLayout = Component.getLayout || ((page) => page)
  if (pageProps.error) {
    return <ToastComponent>{pageProps.error.statusCode}</ToastComponent>
  }
  return (
    <ErrorBoundary FallbackComponent={RootErrorFallback}>
      {getLayout(<Component {...pageProps} />)}
    </ErrorBoundary>
  )
}