Upgrade to Pro — share decks privately, control downloads, hide ads and more …

A Recipe to Power Up Gatsby with Auth

A Recipe to Power Up Gatsby with Auth

Gatsby rose to fame as a static site generator, but it’s also an amazing platform for building dynamic sites! Wouldn’t it be awesome if we could add a user profile with access to protected data in our Gatsby app? Like Mario’s fire flower or Link’s hook shot, adding auth will power up your dynamic Gatsby site. Just one question: is it any different than adding auth to a regular React app?

In this talk, you’ll learn about Gatsby’s build process and runtime and how they impact setting up auth. You’ll also learn how to use Hooks and Context to build your auth sidekick. Finally, you’ll learn how Gatsby recipes can speed up this implementation and make it easy to replicate in all of your projects. By the end, you’ll be ready for the next level of your Gatsby quest!

Sam Julien

July 01, 2020
Tweet

More Decks by Sam Julien

Other Decks in Technology

Transcript

  1. A Receipe to Power Up Gatsby

    View full-size slide

  2. A Receipe to Power Up Gatsby
    with Auth!

    View full-size slide

  3. Static Site Generator
    @samjulien

    View full-size slide

  4. Dynamic Site Framework
    @samjulien

    View full-size slide

  5. Blazing Fast Web & App Framework
    @samjulien

    View full-size slide

  6. Gatsby Recipes #
    @samjulien

    View full-size slide

  7. Adding Auth to Gatsby
    @samjulien

    View full-size slide

  8. Adding Auth to Gatsby
    @samjulien
    Build Time vs. Runtime

    View full-size slide

  9. Adding Auth to Gatsby
    @samjulien
    Build Time vs. Runtime
    Using Hooks for Auth

    View full-size slide

  10. Adding Auth to Gatsby
    @samjulien
    Build Time vs. Runtime
    Using Hooks for Auth
    An Auth Recipe for Gatsby %

    View full-size slide

  11. @samjulien
    Sam Julien
    samjulien.com

    View full-size slide

  12. @samjulien
    Sam Julien
    samjulien.com
    Sr. Developer Advocate Engineer at Auth0

    View full-size slide

  13. @samjulien
    Sam Julien
    samjulien.com
    Sr. Developer Advocate Engineer at Auth0
    Google Developer Expert

    View full-size slide

  14. @samjulien
    Sam Julien
    samjulien.com
    Sr. Developer Advocate Engineer at Auth0
    Google Developer Expert
    Instructor for Thinkster & egghead

    View full-size slide

  15. Adding Auth to Gatsby
    @samjulien
    Build Time vs. Runtime
    Using Hooks for Auth
    An Auth Recipe for Gatsby %

    View full-size slide

  16. Build Time Runtime
    @samjulien

    View full-size slide

  17. Build Time
    Runtime
    @samjulien

    View full-size slide

  18. Build Time
    Runtime

    @samjulien

    View full-size slide

  19. Build Time
    Runtime


    @samjulien

    View full-size slide

  20. No browser APIs available!
    @samjulien

    View full-size slide

  21. Build Time
    Runtime

    @samjulien

    View full-size slide

  22. Build Time Runtime
    @samjulien

    View full-size slide

  23. Build Time
    Runtime
    @samjulien

    View full-size slide

  24. Build Time
    Runtime

    @samjulien

    View full-size slide

  25. Build Time
    Runtime


    @samjulien

    View full-size slide

  26. Build Time Runtime
    @samjulien

    View full-size slide

  27. Build Time Runtime
    @samjulien

    View full-size slide

  28. Start login
    Handle redirect
    Log in to provider
    @samjulien

    View full-size slide

  29. Handle redirect
    Success
    Error
    @samjulien

    View full-size slide

  30. Success
    User Token
    @samjulien

    View full-size slide

  31. Success
    User Token
    Redirect
    @samjulien

    View full-size slide

  32. Adding Auth to Gatsby
    @samjulien
    Build Time vs. Runtime
    Using Hooks for Auth
    An Auth Recipe for Gatsby %

    View full-size slide

  33. Auth Utility
    @samjulien

    View full-size slide

  34. @samjulien
    Auth Utility

    View full-size slide

  35. @samjulien
    Store token and user in memory
    Auth Utility

    View full-size slide

  36. @samjulien
    Store token and user in memory
    Interact with auth SDK
    Auth Utility

    View full-size slide

  37. @samjulien
    Store token and user in memory
    Interact with auth SDK
    Handle all redirect logic
    Auth Utility

    View full-size slide

  38. @samjulien
    export const AuthContext = React.createContext(defaultContext);
    export const useAuth = () => useContext(AuthContext);

    View full-size slide

  39. @samjulien
    export const AuthContext = React.createContext(defaultContext);
    export const useAuth = () => useContext(AuthContext);

    View full-size slide

  40. @samjulien
    export const AuthContext = React.createContext(defaultContext);
    export const useAuth = () => useContext(AuthContext);

    View full-size slide

  41. @samjulien
    export const AuthContext = React.createContext(defaultContext);
    export const useAuth = () => useContext(AuthContext);

    View full-size slide

  42. @samjulien
    export const AuthContext = React.createContext(defaultContext);
    export const useAuth = () => useContext(AuthContext);

    View full-size slide

  43. @samjulien
    export const AuthProvider = ({
    children,
    ...initOptions
    }) => {...};

    View full-size slide

  44. @samjulien
    export const AuthProvider = ({
    children,
    ...initOptions
    }) => { };

    View full-size slide

  45. @samjulien
    export const AuthProvider = ({
    children,
    ...initOptions
    }) => { ...};

    View full-size slide

  46. @samjulien
    ...

    View full-size slide

  47. @samjulien
    const [authClient, setAuthClient] = useState();
    const [isAuthenticated, setIsAuthenticated] = useState();
    const [token, setToken] = useState();
    const [user, setUser] = useState();
    const [loading, setLoading] = useState(true);

    View full-size slide

  48. @samjulien
    const [authClient, setAuthClient] = useState();
    const [isAuthenticated, setIsAuthenticated] = useState();
    const [token, setToken] = useState();
    const [user, setUser] = useState();
    const [loading, setLoading] = useState(true);

    View full-size slide

  49. @samjulien
    const [authClient, setAuthClient] = useState();
    const [isAuthenticated, setIsAuthenticated] = useState();
    const [token, setToken] = useState();
    const [user, setUser] = useState();
    const [loading, setLoading] = useState(true);

    View full-size slide

  50. @samjulien
    const [authClient, setAuthClient] = useState();
    const [isAuthenticated, setIsAuthenticated] = useState();
    const [token, setToken] = useState();
    const [user, setUser] = useState();
    const [loading, setLoading] = useState(true);

    View full-size slide

  51. @samjulien
    const [authClient, setAuthClient] = useState();
    const [isAuthenticated, setIsAuthenticated] = useState();
    const [token, setToken] = useState();
    const [user, setUser] = useState();
    const [loading, setLoading] = useState(true);

    View full-size slide

  52. @samjulien
    useEffect(() => {
    const initAuth = async () => {
    // initialize the auth client
    const authFromHook = await createAuthClient(initOptions);
    setAuth(authFromHook);
    // check if we're in the middle of a redirect
    if (
    window.location.search.includes("code=") &&
    window.location.search.includes("state=")
    ) {
    const { appState } = await authFromHook.handleRedirectCallback();
    onRedirectCallback(appState);
    }

    View full-size slide

  53. @samjulien
    useEffect(() => {
    const initAuth = async () => {
    // initialize the auth client
    const authFromHook = await createAuthClient(initOptions);
    setAuth(authFromHook);
    // check if we're in the middle of a redirect
    if (
    window.location.search.includes("code=") &&
    window.location.search.includes("state=")
    ) {
    const { appState } = await authFromHook.handleRedirectCallback();
    onRedirectCallback(appState);
    }

    View full-size slide

  54. @samjulien
    useEffect(() => {
    const initAuth = async () => {
    // initialize the auth client
    const authFromHook = await createAuthClient(initOptions);
    setAuth(authFromHook);
    // check if we're in the middle of a redirect
    if (
    window.location.search.includes("code=") &&
    window.location.search.includes("state=")
    ) {
    const { appState } = await authFromHook.handleRedirectCallback();
    onRedirectCallback(appState);
    }

    View full-size slide

  55. @samjulien
    useEffect(() => {
    const initAuth = async () => {
    // initialize the auth client
    const authFromHook = await createAuthClient(initOptions);
    setAuth(authFromHook);
    // check if we're in the middle of a redirect
    if (
    window.location.search.includes("code=") &&
    window.location.search.includes("state=")
    ) {
    const { appState } = await authFromHook.handleRedirectCallback();
    onRedirectCallback(appState);
    }

    View full-size slide

  56. @samjulien
    // set initial state using hooks
    const isAuthenticated = await authFromHook.isAuthenticated();
    setIsAuthenticated(isAuthenticated);
    if (isAuthenticated) {
    const user = await authFromHook.getUser();
    setUser(user);
    }
    setLoading(false);
    };
    initAuth();
    }, []);

    View full-size slide

  57. @samjulien
    // set initial state using hooks
    const isAuthenticated = await authFromHook.isAuthenticated();
    setIsAuthenticated(isAuthenticated);
    if (isAuthenticated) {
    const user = await authFromHook.getUser();
    setUser(user);
    }
    setLoading(false);
    };
    initAuth();
    }, []);

    View full-size slide

  58. @samjulien
    // set initial state using hooks
    const isAuthenticated = await authFromHook.isAuthenticated();
    setIsAuthenticated(isAuthenticated);
    if (isAuthenticated) {
    const user = await authFromHook.getUser();
    setUser(user);
    }
    setLoading(false);
    };
    initAuth();
    }, []);

    View full-size slide

  59. @samjulien
    // set initial state using hooks
    const isAuthenticated = await authFromHook.isAuthenticated();
    setIsAuthenticated(isAuthenticated);
    if (isAuthenticated) {
    const user = await authFromHook.getUser();
    setUser(user);
    }
    setLoading(false);
    };
    initAuth();
    }, []);

    View full-size slide

  60. @samjulien
    // set initial state using hooks
    const isAuthenticated = await authFromHook.isAuthenticated();
    setIsAuthenticated(isAuthenticated);
    if (isAuthenticated) {
    const user = await authFromHook.getUser();
    setUser(user);
    }
    setLoading(false);
    };
    initAuth();
    }, []);

    View full-size slide

  61. @samjulien
    // set initial state using hooks
    const isAuthenticated = await authFromHook.isAuthenticated();
    setIsAuthenticated(isAuthenticated);
    if (isAuthenticated) {
    const user = await authFromHook.getUser();
    setUser(user);
    }
    setLoading(false);
    };
    initAuth();
    }, []);

    View full-size slide

  62. @samjulien
    const handleRedirectCallback = async () => {
    // handle callback
    // use hooks to set state
    };

    View full-size slide

  63. @samjulien
    return (
    value={{
    isAuthenticated,
    user,
    token,
    loading,
    handleRedirectCallback,
    getToken: (...p) => authClient.getTokenSilently(...p),
    logout: (...p) => authClient.logout(...p),
    }}
    >
    {children}

    );

    View full-size slide

  64. @samjulien
    return (
    value={{
    isAuthenticated,
    user,
    token,
    loading,
    handleRedirectCallback,
    getToken: (...p) => authClient.getTokenSilently(...p),
    logout: (...p) => authClient.logout(...p),
    }}
    >
    {children}

    );

    View full-size slide

  65. @samjulien
    return (
    value={{
    isAuthenticated,
    user,
    token,
    loading,
    handleRedirectCallback,
    getToken: (...p) => authClient.getTokenSilently(...p),
    logout: (...p) => authClient.logout(...p),
    }}
    >
    {children}

    );

    View full-size slide

  66. @samjulien
    return (
    value={{
    isAuthenticated,
    user,
    token,
    loading,
    handleRedirectCallback,
    getToken: (...p) => authClient.getTokenSilently(...p),
    logout: (...p) => authClient.logout(...p),
    }}
    >
    {children}

    );

    View full-size slide

  67. @samjulien
    return (
    value={{
    isAuthenticated,
    user,
    token,
    loading,
    handleRedirectCallback,
    getToken: (...p) => authClient.getTokenSilently(...p),
    logout: (...p) => authClient.logout(...p),
    }}
    >
    {children}

    );

    View full-size slide

  68. @samjulien
    return (
    value={{
    isAuthenticated,
    user,
    token,
    loading,
    handleRedirectCallback,
    getToken: (...p) => authClient.getTokenSilently(...p),
    logout: (...p) => authClient.logout(...p),
    }}
    >
    {children}

    );

    View full-size slide

  69. Auth Utility
    @samjulien

    View full-size slide

  70. @samjulien
    Auth Utility

    View full-size slide

  71. @samjulien
    Store token and user in memory
    Interact with auth SDK
    Handle all redirect logic
    Auth Utility

    View full-size slide

  72. Does our Gatsby app work?
    @samjulien

    View full-size slide

  73. Maybe (but probably not).
    @samjulien

    View full-size slide

  74. gatsby develop vs gatsby build
    @samjulien

    View full-size slide

  75. Build Time Runtime
    @samjulien

    View full-size slide

  76. Build Time
    Runtime
    @samjulien

    View full-size slide

  77. Build Time
    Runtime

    @samjulien

    View full-size slide

  78. Build Time
    Runtime


    @samjulien

    View full-size slide

  79. Build Time Runtime
    @samjulien

    View full-size slide

  80. @samjulien
    export const AuthContext = React.createContext(defaultContext);
    export const useAuth = () => useContext(AuthContext);

    View full-size slide

  81. @samjulien
    export const AuthContext = React.createContext(defaultContext);
    export const useAuth = () => useContext(AuthContext);

    View full-size slide

  82. @samjulien
    const defaultContext = {
    isAuthenticated: false,
    user: null,
    token: null,
    loading: false,
    login: () => {},
    };

    View full-size slide

  83. Why do we do this?
    @samjulien

    View full-size slide

  84. Example: NavBar Component
    @samjulien

    View full-size slide

  85. @samjulien
    const NavBar = () => {
    const { isAuthenticated, login, logout } = useAuth();
    return (

    Home{" "}
    {!isAuthenticated && login()}>Log in}
    {isAuthenticated && (
    <>
    Profile
    logout()}>Log out
    >
    )}

    );
    };

    View full-size slide

  86. @samjulien
    const NavBar = () => {
    const { isAuthenticated, login, logout } = useAuth();
    return (

    Home{" "}
    {!isAuthenticated && login()}>Log in}
    {isAuthenticated && (
    <>
    Profile
    logout()}>Log out
    >
    )}

    );
    };

    View full-size slide

  87. @samjulien
    const NavBar = () => {
    const { isAuthenticated, login, logout } = useAuth();
    return (

    Home{" "}
    {!isAuthenticated && login()}>Log in}
    {isAuthenticated && (
    <>
    Profile
    logout()}>Log out
    >
    )}

    );
    };

    View full-size slide

  88. @samjulien
    const NavBar = () => {
    const { isAuthenticated, login, logout } = useAuth();
    return (

    Home{" "}
    {!isAuthenticated && login()}>Log in}
    {isAuthenticated && (
    <>
    Profile
    logout()}>Log out
    >
    )}

    );
    };

    View full-size slide

  89. @samjulien
    const NavBar = () => {
    const { isAuthenticated, login, logout } = useAuth();
    return (

    Home{" "}
    {!isAuthenticated && login()}>Log in}
    {isAuthenticated && (
    <>
    Profile
    logout()}>Log out
    >
    )}

    );
    };

    View full-size slide

  90. What if we use this in a Gatsby page?
    @samjulien

    View full-size slide

  91. @samjulien
    export default () => {
    const { loading } = useAuth();
    if (loading) {
    return Loading...;
    }
    return (




    );
    };

    View full-size slide

  92. @samjulien
    export default () => {
    const { loading } = useAuth();
    if (loading) {
    return Loading...;
    }
    return (




    );
    };

    View full-size slide

  93. @samjulien
    export default () => {
    const { loading } = useAuth();
    if (loading) {
    return Loading...;
    }
    return (




    );
    };

    View full-size slide

  94. @samjulien
    const defaultContext = {
    isAuthenticated: false,
    user: null,
    token: null,
    loading: false,
    login: () => {},
    };

    View full-size slide

  95. Where do we use this AuthProvider?
    @samjulien

    View full-size slide

  96. Adding Auth to Gatsby
    @samjulien
    Build Time vs. Runtime
    Using Hooks for Auth
    An Auth Recipe for Gatsby %

    View full-size slide

  97. Gatsby Recipes #
    @samjulien

    View full-size slide

  98. Gatsby Recipes #
    @samjulien

    View full-size slide

  99. Automate common tasks
    Gatsby Recipes #
    @samjulien

    View full-size slide

  100. Automate common tasks
    Gatsby Recipes #
    Written in MDX
    @samjulien

    View full-size slide

  101. Automate common tasks
    Gatsby Recipes #
    Install packages and plugins
    Written in MDX
    @samjulien

    View full-size slide

  102. Automate common tasks
    Gatsby Recipes #
    Install packages and plugins
    Generate pages and code
    Written in MDX
    @samjulien

    View full-size slide

  103. Automate common tasks
    Run from the CLI
    Gatsby Recipes #
    Install packages and plugins
    Generate pages and code
    Written in MDX
    @samjulien

    View full-size slide

  104. Written in MDX
    @samjulien

    View full-size slide

  105. Step 0: Create a local MDX file or a Gist.
    @samjulien

    View full-size slide

  106. Install packages and plugins
    @samjulien

    View full-size slide

  107. Step 1: Install Auth SDK
    @samjulien

    View full-size slide

  108. Step 1: Install Auth SDK

    @samjulien

    View full-size slide

  109. Generate pages and code
    @samjulien

    View full-size slide

  110. Step 2: Add Auth Provider
    @samjulien

    View full-size slide

  111. Step 2: Add Auth Provider
    content="./auth-recipe/auth.js" />
    @samjulien

    View full-size slide

  112. Step 2: Add Auth Provider
    content="./auth-recipe/auth.js" />
    @samjulien

    View full-size slide

  113. Step 2: Add Auth Provider
    content="./auth-recipe/auth.js" />
    @samjulien

    View full-size slide

  114. Where do we use this AuthProvider?
    @samjulien

    View full-size slide

  115. Step 3: Add gatsby-browser.js
    @samjulien

    View full-size slide

  116. gatsby-browser.js
    @samjulien

    View full-size slide

  117. export const wrapRootElement = ({ element }) => {
    return (
    // pass in any configuration here
    >
    {element}

    );
    };
    @samjulien

    View full-size slide

  118. export const wrapRootElement = ({ element }) => {
    return (
    // pass in any configuration here
    >
    {element}

    );
    };
    @samjulien

    View full-size slide

  119. export const wrapRootElement = ({ element }) => {
    return (
    // pass in any configuration here
    >
    {element}

    );
    };
    @samjulien

    View full-size slide

  120. Step 3: Add gatsby-browser.js
    @samjulien

    View full-size slide

  121. path="./gatsby-browser.js"
    content="./auth-recipe/gatsby-
    browser.js"
    />;
    Step 3: Add gatsby-browser.js
    @samjulien

    View full-size slide

  122. Build Time Runtime
    @samjulien

    View full-size slide

  123. No browser APIs available!
    @samjulien

    View full-size slide

  124. Watch out for dependencies using
    browser APIs like window or document.
    @samjulien

    View full-size slide

  125. Watch out for dependencies using
    browser APIs like window or document.
    @samjulien
    (Spoilers: auth libraries usually do this a lot because of redirects and pop-ups.)

    View full-size slide

  126. Step 4 (maybe): Add gatsby-node.js
    @samjulien

    View full-size slide

  127. gatsby-node.js
    @samjulien

    View full-size slide

  128. @samjulien
    exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
    if (["build-html", “develop-html"].includes(stage)) {
    actions.setWebpackConfig({
    module: {
    rules: [
    {
    test: /auth-sdk/,
    use: loaders.null(),
    },
    ],
    },
    });
    }
    };

    View full-size slide

  129. @samjulien
    exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
    if (["build-html", “develop-html"].includes(stage)) {
    actions.setWebpackConfig({
    module: {
    rules: [
    {
    test: /auth-sdk/,
    use: loaders.null(),
    },
    ],
    },
    });
    }
    };

    View full-size slide

  130. @samjulien
    exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
    if (["build-html", "develop-html"].includes(stage)) {
    actions.setWebpackConfig({
    module: {
    rules: [
    {
    test: /auth-sdk/,
    use: loaders.null(),
    },
    ],
    },
    });
    }
    };

    View full-size slide

  131. @samjulien
    exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
    if (["build-html", "develop-html"].includes(stage)) {
    actions.setWebpackConfig({
    module: {
    rules: [
    {
    test: /auth-sdk/,
    use: loaders.null(),
    },
    ],
    },
    });
    }
    };

    View full-size slide

  132. @samjulien
    exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
    if (["build-html", "develop-html"].includes(stage)) {
    actions.setWebpackConfig({
    module: {
    rules: [
    {
    test: /auth-sdk/,
    use: loaders.null(),
    },
    ],
    },
    });
    }
    };

    View full-size slide

  133. @samjulien
    exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
    if (["build-html", "develop-html"].includes(stage)) {
    actions.setWebpackConfig({
    module: {
    rules: [
    {
    test: /auth-sdk/,
    use: loaders.null(),
    },
    ],
    },
    });
    }
    };

    View full-size slide

  134. Step 4 (maybe): Add gatsby-node.js
    @samjulien

    View full-size slide

  135. path="./gatsby-node.js"
    content="./auth-recipe/gatsby-
    node.js"
    />;
    Step 4 (maybe): Add gatsby-node.js
    @samjulien

    View full-size slide

  136. Run from the CLI
    @samjulien

    View full-size slide

  137. Step 5: Run your recipe!
    @samjulien

    View full-size slide

  138. gatsby recipes ./auth-recipe/recipe.mdx
    Step 5: Run your recipe!
    @samjulien

    View full-size slide

  139. Level up: Update this to create a local plugin
    @samjulien

    View full-size slide

  140. @samjulien
    name="gatsby-plugin-auth-recipe"
    options={{
    domain: `domain.auth-provider.com`,
    clientId: `theclientid`,
    }}
    />;

    View full-size slide

  141. Let’s Review
    @samjulien

    View full-size slide

  142. Static Site Generator
    @samjulien

    View full-size slide

  143. Dynamic Site Framework
    @samjulien

    View full-size slide

  144. Build Time Runtime
    @samjulien

    View full-size slide

  145. Build Time Runtime
    @samjulien

    View full-size slide

  146. Start login
    Handle redirect
    Log in to provider
    @samjulien

    View full-size slide

  147. Handle redirect
    Success
    Error
    @samjulien

    View full-size slide

  148. Success
    User Token
    @samjulien

    View full-size slide

  149. Success
    User Token
    Redirect
    @samjulien

    View full-size slide

  150. Auth Utility
    @samjulien

    View full-size slide

  151. @samjulien
    Auth Utility

    View full-size slide

  152. @samjulien
    Store token and user in memory
    Auth Utility

    View full-size slide

  153. @samjulien
    Store token and user in memory
    Interact with auth SDK
    Auth Utility

    View full-size slide

  154. @samjulien
    Store token and user in memory
    Interact with auth SDK
    Handle all redirect logic
    Auth Utility

    View full-size slide

  155. @samjulien
    export const AuthContext = React.createContext(defaultContext);
    export const useAuth = () => useContext(AuthContext);

    View full-size slide

  156. @samjulien
    return (
    value={{
    isAuthenticated,
    user,
    token,
    loading,
    handleRedirectCallback,
    getToken: (...p) => authClient.getTokenSilently(...p),
    logout: (...p) => authClient.logout(...p),
    }}
    >
    {children}

    );

    View full-size slide

  157. @samjulien
    const defaultContext = {
    isAuthenticated: false,
    user: null,
    token: null,
    loading: false,
    login: () => {},
    };

    View full-size slide

  158. Gatsby Recipes #
    @samjulien

    View full-size slide

  159. Gatsby Recipes #
    @samjulien

    View full-size slide

  160. Automate common tasks
    Gatsby Recipes #
    @samjulien

    View full-size slide

  161. Automate common tasks
    Gatsby Recipes #
    Written in MDX
    @samjulien

    View full-size slide

  162. Automate common tasks
    Gatsby Recipes #
    Install packages and plugins
    Written in MDX
    @samjulien

    View full-size slide

  163. Automate common tasks
    Gatsby Recipes #
    Install packages and plugins
    Generate pages and code
    Written in MDX
    @samjulien

    View full-size slide

  164. Automate common tasks
    Run from the CLI
    Gatsby Recipes #
    Install packages and plugins
    Generate pages and code
    Written in MDX
    @samjulien

    View full-size slide

  165. Step 0: Create a local MDX file or a Gist.
    @samjulien

    View full-size slide

  166. Step 1: Install Auth SDK

    @samjulien

    View full-size slide

  167. Step 2: Add Auth Provider
    content="./auth-recipe/auth.js" />
    @samjulien

    View full-size slide

  168. path="./gatsby-browser.js"
    content="./auth-recipe/gatsby-
    browser.js"
    />;
    Step 3: Add gatsby-browser.js
    @samjulien

    View full-size slide

  169. export const wrapRootElement = ({ element }) => {
    return (
    // pass in any configuration here
    >
    {element}

    );
    };
    @samjulien

    View full-size slide

  170. path="./gatsby-node.js"
    content="./auth-recipe/gatsby-
    node.js"
    />;
    Step 4 (maybe): Add gatsby-node.js
    @samjulien

    View full-size slide

  171. Build Time Runtime
    @samjulien

    View full-size slide

  172. No browser APIs available!
    @samjulien

    View full-size slide

  173. Watch out for dependencies using
    browser APIs like window or document.
    @samjulien

    View full-size slide

  174. Watch out for dependencies using
    browser APIs like window or document.
    @samjulien
    (Spoilers: auth libraries usually do this a lot because of redirects and pop-ups.)

    View full-size slide

  175. @samjulien
    exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
    if (stage === "build-html") {
    actions.setWebpackConfig({
    module: {
    rules: [
    {
    test: /auth-sdk/,
    use: loaders.null(),
    },
    ],
    },
    });
    }
    };

    View full-size slide

  176. gatsby recipes ./auth-recipe/recipe.mdx
    Step 5: Run your recipe!
    @samjulien

    View full-size slide

  177. Level up: Update this to create a local plugin
    @samjulien

    View full-size slide

  178. samj.im/gatsby-days
    @samjulien

    View full-size slide

  179. samj.im/gatsby-days
    Thank you!
    @samjulien

    View full-size slide