Blitz.js
Making Fullstack Web Development a Breeze
Acme Design is a full service design agency.
Who am I
Agenda
Why was Blitz created in the first place?
What was its goal?
1
Blitz's goal
What is the Blitz framework?
What are the core concepts?
2
Blitz Framework
What are we working on currently?
How does the Blitz's future look like?
3
Blitz 2.0
The Goals
We're making full-stack web development a breeze.
Blitz aims to make you as productive as possible.
We want to give you the best DX in the world.
What is Blitz?
How do we achieve these goals?
1
Blitz framework was created by Brandon and the community
3
We decided to fork Next.js, weekly downloads stagnated
5
We released an alpha version of the Blitz 2.0
2
Blitz reaching 11k GitHub stars. People loved it
4
We posted an RFC about Blitz pivot, it was very well received
Feb, 2020
2020 – 2021
Mar, 2021
Dec, 2021
May, 2021
Blitz
The Fullstack JavaScript Framework
Next.js
Recipes
Zero-API Layer
React-query
Code scaffolding
AuthN & AuthZ
Prisma
Zod utilites
Misc utilities
Blitz 2.0
The Fullstack JavaScript Toolkit
Blitz Toolkit
@blitzjs/next
@blitzjs/auth
@blitzjs/rpc
blitz core
blitz core
Blitz Toolkit
@blitzjs/next
@blitzjs/auth
@blitzjs/rpc
- CLI
- Env vars loading
- Plugins
- Middlewares
- Code scaffolding
- Recipes
- Utilities
blitz core
Blitz Toolkit
@blitzjs/next
@blitzjs/auth
@blitzjs/rpc
- gSP and gSSP functions
- api wrapper for API Routes
- Client & server plugins setup for Nextjs apps
blitz core
Blitz Toolkit
@blitzjs/next
@blitzjs/auth
@blitzjs/rpc
- Authentication & Authorization
- Passport adapter for 3rd party auth
- Configurable session storage
blitz core
Blitz Toolkit
@blitzjs/next
@blitzjs/auth
@blitzjs/rpc
- Zero-API Data Layer
- React-query-like functions
- Configurable QueryClient
blitz core
Getting started
npm i -g blitz@alpha
blitz new my-new-blitz-project
// app/blitz-server.ts
import { setupBlitzServer } from "@blitzjs/next"
import { AuthServerPlugin, PrismaStorage } from "@blitzjs/auth"
import { db } from "db"
import { simpleRolesIsAuthorized } from "@blitzjs/auth"
const { gSSP, gSP, api } = setupBlitzServer({
plugins: [
AuthServerPlugin({
cookiePrefix: "blitz-app",
storage: PrismaStorage(db),
isAuthorized: simpleRolesIsAuthorized,
}),
],
})
export { gSSP, gSP, api }
Server setup
// app/blitz-client.ts
import { AuthClientPlugin } from "@blitzjs/auth"
import { setupBlitzClient } from "@blitzjs/next"
import { BlitzRpcPlugin } from "@blitzjs/rpc"
export const { withBlitz } = setupBlitzClient({
plugins: [
AuthClientPlugin({
cookiePrefix: "blitz-app",
}),
BlitzRpcPlugin({
reactQueryOptions: {
queries: {
staleTime: 7000,
},
},
}),
],
})
Client setup
Zero-API Layer
Zero-API Layer
// app/products/queries/getProduct.ts
import db from "db"
import * as z from "zod"
const GetProject = z.object({
id: z.number(),
})
export default async function getProject(
input: z.infer<typeof GetProject>,
) {
const data = GetProject.parse(input)
const project = await db.project.findOne({ where: { id: data.id } })
return project
}
Zero-API Layer
import { Suspense } from "react"
import { useQuery, useRouter, useParam } from "blitz"
import getProject from "app/projects/queries/getProject"
function Project() {
const router = useRouter()
const projectId = useParam("projectId", "number")
const [project] = useQuery(getProject, { where: { id: projectId } })
return <div>{project.name}</div>
}
function ProjectPage() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Project />
</Suspense>
)
}
export default ProjectPage
Zero-API Layer
// app/products/mutations/createProduct.tsx
import db from "db"
import * as z from "zod"
const CreateProject = z
.object({
name: z.string(),
})
export default async function createProject(
input: z.infer<typeof CreateProject>,
) {
const data = CreateProject.parse(input)
const project = await db.project.create({ data })
return project
}
Zero-API Layer
import {useMutation} from 'blitz'
import updateProject from 'app/projects/mutations/updateProject'
function (props) {
const [updateProjectMutation] = useMutation(updateProject)
return (
<Formik
onSubmit={async values => {
try {
const project = await updateProjectMutation(values)
} catch (error) {
alert('Error saving project')
}
}}>
{/* ... */}
</Formik>
)
}
// app/auth/mutations/signup.ts
import { resolver, SecurePassword } from "blitz"
import db from "db"
import { Signup } from "app/auth/validations"
import { Role } from "types"
export default resolver.pipe(resolver.zod(Signup), async ({ email, password }, ctx) => {
const hashedPassword = await SecurePassword.hash(password.trim())
const user = await db.user.create({
data: { email: email.toLowerCase().trim(), hashedPassword, role: "USER" },
select: { id: true, name: true, email: true, role: true },
})
await ctx.session.$create({ userId: user.id, role: user.role as Role })
return user
})
AuthZ & AuthN
// app/products/queries/getProduct.tsx
import {Ctx} from "blitz"
import db from "db"
import * as z from "zod"
const GetProject = z.object({
id: z.number(),
})
export default async function getProject(
input: z.infer<typeof GetProject>,
ctx: Ctx
) {
const data = GetProject.parse(input)
ctx.session.$authorize(),
const project = await db.project.findOne({ where: { id: data.id } })
return project
}
AuthZ & AuthN
import { Routes } from "@blitzjs/next"
const Page: BlitzPage = () => {
return <div>{/* ... */}</div>
}
Page.redirectAuthenticatedTo = "/"
Page.redirectAuthenticatedTo = Routes.Home()
Page.redirectAuthenticatedTo = ({ session }) =>
session.role === "admin" ? "/admin" : Routes.Home()
Page.authenticate = true
Page.authenticate = {redirectTo: '/login'}
Page.authenticate = {redirectTo: Routes.Login()}
AuthZ & AuthN
Current
Toolkit
Zero-API Data Layer ✅ ✅
Authentication, authorization ✅ ✅
New app templates ✅ ✅
Code scaffolding ✅ ✅
Recipes ✅ ✅
Websockets 🚀
Cron, scheduled job, job queues 🚀
Mailers/Email integration 🚀
File uploads 🚀
Billing integration 🚀
GraphQL data layer 🚀
Takeaways
➡️ https://canary.blitzjs.com/
➡️ https://github.com/blitz-js/blitz
We'd love your feedback!
Thank You!
Making Fullstack Web Development a Breeze
By Aleksandra Sikora
Making Fullstack Web Development a Breeze
- 1,152