How to Start Contributing to Open Source
Acme Design is a full service design agency.
Agenda
Why contribute to open source?
1
Why?
How to find a project to contribute to?
2
Where?
How to submit your first contribution?
3
How?
Why contribute to open source?
Why contribute to open source?
-
Improve software you rely on
Why contribute to open source?
-
Improve software you rely on
-
Improve your skills
Why contribute to open source?
-
Improve software you rely on
-
Improve your skills
-
Learn new things and teach others
Why contribute to open source?
-
Improve software you rely on
-
Improve your skills
-
Learn new things and teach others
-
Improve communication skills
Why contribute to open source?
Improve software you rely on
Improve your skills
Learn new things and teach others
Improve communication skills
It's empowering
What is an open source project?
- Author: The person/s or organization that created the project
- Owner: The person/s who has administrative ownership
- Maintainers: Contributors who are responsible for managing the the project
- Contributors: Everyone who has contributed something back to the project
- Community Members: People who use the project
1
Blitz framework was created by Brandon and the community
3
We decided to fork Next.js, weekly downloads started to decline
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
Apr, 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!
How to Start Contributing to Open Source
By Aleksandra Sikora
How to Start Contributing to Open Source
- 1,141