Public Speaking
for Developers
Eve Porcello
@eveporcello
eve@moonhighway.com
Agenda
Start: 7:00am
Break: 7:45am
End: 9:30am
- Writing a Talk Proposal
- Mapping Talk Content
- Creating an Opener
- Storytelling Techniques
- Live Coding
- Rehearsing Your Talk
- Incorporating Feedback
- Handling Anxiety
Tahoe City, CA
This is a little weird.
Make it your own.
Take what is useful.
Why do you want to give tech talks?
Think back to a great talk you saw.
Why was it good?
Writing a Talk Proposal
Talks are entertainment.
Proposals
- Focus on how people will benefit
- Who is it for?
- Pique people's interest
- What's the hook?
Write Down One Topic That You Could Give a Talk On
Creating a Catchy Title
Algebraic Effects in React
FROM
Algebraic Effects, Fibers, Coroutines... Oh my!
TO
React's Component Lifecycle
FROM
The Life Cycle Methods and The Wolf: A Musicological Romp
TO
JavaScript Games
FROM
Build a Chrome Dinosaur Game in 15 Minutes
TO
React, Vue, and Svelte
FROM
React, Vue, and Svelte as Teen Movie Archetypes
TO
-
Have a point of view
-
Use alliteration
-
Make it sensational!
Writing a Title
Activity!
- Create a title for that topic
- https://sumo.com/kickass-headline-generator/
Abstracts
Proposals
- Focus on how people will benefit
- Who is it for?
- Pique people's interest
- What's the hook?
Who's the jock? The nerd? The misfit? Who's the type A overachiever, or the moody artist, or the partier?
Get to know each of these JavaScript frameworks through the hallowed medium of the teen comedy.
In this talk, we'll dig into what makes these frameworks unique, and as in every good millennial teen movie, you'll leave with a better understanding of each one.
React, Vue, and Svelte as Teen Movie Archetypes
Activity: The Abstract
-
3 sentences
- 1st sentence: Catchy 1st line (maybe a question)
- 2nd sentence: What you'll cover
- 3rd sentence: What people will learn
Use your own topic or enhance this abstract with specifics.
Have you ever wanted to learn Node.js? In this talk, we'll dig deeper into Node.js. You can expect to walk away knowing Node.js.
Organizing Your Content
Where to Start
- Build a Demo / Sample Application
Where to Start
- Sticky Notes
Where to Start
- Outline in a Document
- Then outline in Slides
GraphQL intro
Query Language and the spec
Fields in a query
- All of JavaScript
- All of GraphQL
- All of Prisma
40 mins
Start with Emotion
- Excitement
- Sadness about Failure
- Personalization
- Capture attention in the first 60 seconds
Activity!
- Volunteer
- 30 seconds
End Definitively
- Avoid trailing off
- "Thank You"
Map every minute in between
Presentation Skills
When Crafting Your Talk
- Bring yourself
- Get excited
- Have a point of view
- Relate to what you're presenting with personal experience
If you're in person...
Face Forward
import { PrismaClient } from '@prisma/client'
const prisma = new PrismaClient()
async function main() {
const allUsers = await prisma.user.findMany({
include: { posts: true },
})
console.log(allUsers)
}
main()
.finally(async () => {
await prisma.$disconnect()
})
😀
Live Coding
import React, { Component } from 'react'
import { storage } from '../../client'
import { PLAYER_ROOT_QUERY, LISTEN_FOR_INSTRUCTIONS, LOGOUT } from '.'
import { WaitingForInstructions } from './ui/WaitingForInstructions'
import { End } from './ui/End'
import { Team } from './Team'
import { Game } from './Game'
export class CurrentPlayer extends Component {
logout = () => {
this.props.client.mutate({ mutation: LOGOUT })
storage.removeItem('token')
this.props.client.writeQuery({
query: PLAYER_ROOT_QUERY,
data: {
me: null
}
})
}
componentDidMount() {
this.stopListeningToInstructions = this.props.client
.subscribe({ query: LISTEN_FOR_INSTRUCTIONS })
.subscribe(({ data, error }) => {
if (error) {
return console.error(error)
}
console.log('new instructions: ', data.instructions.endEvent)
this.props.client.writeQuery({
query: PLAYER_ROOT_QUERY,
data: {
me: data.instructions
}
})
})
}
componentWillUnmount() {
if (this.stopListeningToInstructions) {
this.stopListeningToInstructions._cleanup()
}
}
render() {
const { avatar, name, login, team, playingGame, instrument, endEvent } = this.props
return playingGame ?
<Game instrument={instrument} /> :
team ?
<Team {...team}
avatar={avatar}
onLeave={this.logOut} /> :
endEvent ?
<End /> :
<WaitingForInstructions
name={name || login}
avatar={avatar}
onLeave={this.logout} />
}
}
import React from 'react'
import { ExitButton } from './ExitButton'
import styled from 'styled-components'
export const WaitingForInstructions = ({ name, avatar, onLeave=f=>f }) =>
<Container>
<figure>
<img src={avatar} width={48} height={48} alt="" />
</figure>
<h1>
<span>Welcome,</span>
<span>{name}</span>
</h1>
<ExitButton onClick={onLeave} />
</Container>
export class Wejay extends Component {
state = { loadingMusic: true }
async componentDidMount() {
const files = [bass,drums,percussion,sampler,synth]
const tracks = await loadAllAudio(files)
tracks.forEach(track => {
track.volume = 0
track.loop = true
})
tracks.forEach(track => track.play())
let [BASS,DRUMS,PERCUSSION,SAMPLER,SYNTH] = tracks
this.tracks = {BASS,DRUMS,PERCUSSION,SAMPLER,SYNTH}
this.setState({ loadingMusic: false })
}
componentWillUnmount = () => {
Object.keys(this.tracks).forEach(instrument => this.tracks[instrument].src = '')
}
instruments = data =>
data.gameChange.playingMusic.map(({ instrument }) => instrument)
isPlayingMusic = (data, instrument) => data &&
-1 !== this.instruments(data).indexOf(instrument)
playTrack = data => {
if (data) {
this.playSound(this.instruments(data))
}
}
playSound = instruments =>
Object.keys(this.tracks).forEach(key =>
this.tracks[key].volume = instruments.indexOf(key) !== -1 ? 1 : 0
)
render() {
const { players } = this.props
const { loadingMusic } = this.state
return loadingMusic ?
<LoadingScreen /> :
<Subscription subscription={LISTEN_FOR_GAME_CHANGES}>
{({ data }) => {
this.playTrack(data)
return (
<Container>
{(data && data.gameChange.faces.length) ?
<Audience faces={data.gameChange.faces} /> :
null
}
{players.map(p =>
<Musician key={p.login}
avatar={p.avatar}
login={p.login}
instrument={p.instrument}
playingMusic={this.isPlayingMusic(data, p.instrument)}/>
)}
</Container>
)
}}
</Subscription>
}
}
export class Wejay extends Component {
state = { loadingMusic: true }
async componentDidMount() {
const files = [bass,drums,percussion,sampler,synth]
const tracks = await loadAllAudio(files)
tracks.forEach(track => {
track.volume = 0
track.loop = true
})
tracks.forEach(track => track.play())
let [BASS,DRUMS,PERCUSSION,SAMPLER,SYNTH] = tracks
this.tracks = {BASS,DRUMS,PERCUSSION,SAMPLER,SYNTH}
this.setState({ loadingMusic: false })
}
componentWillUnmount = () => {
Object.keys(this.tracks).forEach(instrument => this.tracks[instrument].src = '')
}
instruments = data =>
data.gameChange.playingMusic.map(({ instrument }) => instrument)
isPlayingMusic = (data, instrument) => data &&
-1 !== this.instruments(data).indexOf(instrument)
playTrack = data => {
if (data) {
this.playSound(this.instruments(data))
}
}
playSound = instruments =>
Object.keys(this.tracks).forEach(key =>
this.tracks[key].volume = instruments.indexOf(key) !== -1 ? 1 : 0
)
render() {
const { players } = this.props
const { loadingMusic } = this.state
return loadingMusic ?
<LoadingScreen /> :
<Subscription subscription={LISTEN_FOR_GAME_CHANGES}>
{({ data }) => {
this.playTrack(data)
return (
<Container>
{players.map(p =>
<Musician key={p.login}
avatar={p.avatar}
login={p.login}
instrument={p.instrument}
playingMusic={this.isPlayingMusic(data, p.instrument)}/>
)}
</Container>
)
}}
</Subscription>
}
}
import React, { Component } from 'react'
import { random } from 'faker'
import styled from 'styled-components'
export class ConnectedPlayer extends Component {
bounds = {
height: window.innerHeight,
width: window.innerWidth
}
constructor(props) {
super()
let top, left
switch(Math.floor(Math.random()*8)) {
case 0:
top = `${random.number({ min: 0, max: this.bounds.height * .25 })}px`
left = `${random.number({ min: 0, max: this.bounds.width * .25 })}px`
break
case 1:
top = `${random.number({ min: 0, max: this.bounds.height * .25 })}px`
left = `${random.number({ min: this.bounds.width * .25, max: this.bounds.width * .75 })}px`
break
case 2:
top = `${random.number({ min: 0, max: this.bounds.height * .25 })}px`
left = `${random.number({ min: (this.bounds.width * .75)-100, max: this.bounds.width-60 })}px`
break
case 3:
top = `${random.number({ min: this.bounds.height * .25, max: this.bounds.height * .75 })}px`
left = `${random.number({ min: 0, max: this.bounds.width * .25 })}px`
break
case 4:
top = `${random.number({ min: this.bounds.height * .25, max: this.bounds.height * .75 })}px`
left = `${random.number({ min: (this.bounds.width * .75)-100, max: this.bounds.width-60 })}px`
break
case 5:
top = `${random.number({ min: this.bounds.height * .75, max: this.bounds.height-60 })}px`
left = `${random.number({ min: 0, max: this.bounds.width * .25 })}px`
break
case 6:
top = `${random.number({ min: this.bounds.height * .75, max: this.bounds.height-60 })}px`
left = `${random.number({ min: this.bounds.width * .25, max: this.bounds.width * .75 })}px`
break
default:
top = `${random.number({ min: this.bounds.height * .75, max: this.bounds.height-60 })}px`
left = `${random.number({ min: (this.bounds.width * .75)-100, max: this.bounds.width-60 })}px`
break
}
this.state = { top, left }
}
render() {
const { avatar, login, team } = this.props
const { top, left } = this.state
return (
<Container teamColor={team && team.color.name} top={top} left={left}>
<img src={avatar} alt={login} />
</Container>
)
}
}
const Container = styled.div`
position: fixed;
top: ${props => props.top};
left: ${props => props.left};
img {
width: 60px;
height: 60px;
border-radius: 50%;
border: solid 5px ${props => props.teamColor ? props.teamColor : props.theme.colors.contrast};
}
`
What
Terminal
VSCode
Start from Scratch
Minimize Cut and Paste
Zoom In Then Zoom Out
(Have a backup)
Storytelling
Stories
- Humor
- Vulnerability
- Connection
- Memory
Tricks
- Rule of threes
- Raise the stakes
Formats
- Hero's Journey
- Start in the Middle
- Post Mortem
Activity: Today!
- What's the most interesting thing that has happened to you today?
Activity: Success & Failure
- Tell me about a time when you felt really successful/unsuccessful at work.
- Who were you with?
- Why was it important?
- When you think back, what emotions do you have?
Dealing with Pre-Talk
Anxiety
If you look relaxed, you're prepared.
Rehearsing the Talk
- Create a rehearsal schedule
- Run through the content at least once with a friend, co-worker, or family member
Make it feel real
- Present in as close to the conditions as you can (standing, etc)
- Present at a local or online event
Tech Rehearsal
- Go to the venue
- Plug in your computer if possible
- Share your screen
- Go to the worst seat
- From tech rehearsal to presentation, don't change your demo
Have backups 💥
- Slides
- Wifi
- Dongles
You're the talent.
Treat yourself accordingly!
Play Music
One Cool Thing
Next Steps
- Write down 3 events that you'd like to speak at
- Send your abstract to one of your fellow ambassadors
- Send in your abstract!
Thank You!
- @eveporcello
- eve@moonhighway.com
Public Speaking for Developers
By Moon Highway
Public Speaking for Developers
- 487