Making Fullstack Web Development a Breeze
Acme Design is a full service design agency.
Why was Blitz created in the first place?
What was its goal?
What is the Blitz framework?
What are the core concepts?
What are we working on currently?
How does the Blitz's future look like?
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.
How do we achieve these goals?
Blitz framework was created by Brandon and the community
We decided to fork Next.js, weekly downloads stagnated
We released an alpha version of the Blitz 2.0
Blitz reaching 11k GitHub stars. People loved it
We posted an RFC about Blitz pivot, it was very well received
Feb, 2020
2020 – 2021
Mar, 2021
Dec, 2021
May, 2021
The Fullstack JavaScript Framework
Next.js
Recipes
Zero-API Layer
React-query
Code scaffolding
AuthN & AuthZ
Prisma
Zod utilites
Misc utilities
The Fullstack JavaScript Toolkit
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 }
// 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,
},
},
}),
],
})
// 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
}
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
// 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
}
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
})
// 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
}
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()}
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 🚀
➡️ https://canary.blitzjs.com/
➡️ https://github.com/blitz-js/blitz