Thanks!
@saltnburnem
#CommitYourCode | #DeveloperCommunity
🛸
Commit Your Code
#CommitYourCodeÂ
@saltnburnem
🛸
#CommitYourCode | #DeveloperCommunity
#DeveloperCommunity
@saltnburnem
🛸
#CommitYourCode | #DeveloperCommunity
Chris DeMars
@saltnburnem

    @saltnburnem | 🦋 @chrisdemars.net
Senior Developer Advocate

REDACTED
REDACTED
🛸
#CommitYourCode | #DeveloperCommunity
Chris DeMars
@saltnburnem

    @saltnburnem | 🦋 @chrisdemars.net
Senior Developer Advocate

🛸
#CommitYourCode | #DeveloperCommunity
Close Encounters
@saltnburnem
#MichiganDevFest | #DeveloperCommunity
of the
Data Kind
Exploring UFO Sightings with MongoDB and NextJS
@saltnburnem
First
#CommitYourCode | #DeveloperCommunity
@saltnburnem
UFO/UAP History
Sightings & Abductions
#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
July 1947
#CommitYourCode | #DeveloperCommunity
@saltnburnem
Betty & Barney Hill (1961)
#CommitYourCode | #DeveloperCommunity
@saltnburnem
Betty & Barney Hill

First Documented Abduction Case
#CommitYourCode | #DeveloperCommunity
@saltnburnem
March 20th, 1966
Dexter, MI

#CommitYourCode | #DeveloperCommunity
@saltnburnem
Tech Time!
#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
The React Framework for the Web
Built-in Optimizations
Dynamic HTML Streaming
React Server Components
Route Handlers
Server Actions
npx create-next-app@latest#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
The world's most popular document database
Document Model
Flexible Schema
Distributed and Resilient
Â
Horizontally Scale
#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
A cloud for your entire journey
GPU Droplets: Simple, powerful virtual machines for AI/ML
Managed MongoDB, Kafka, MySQL, PostgreSQL
Fully-managed PaaS solution
Spaces object storage and Volumes block storageÂ
DigitalOcean Kubernetes a.k.a. DOKS
#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
👽
#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem

#CommitYourCode | #DeveloperCommunity
@saltnburnem
Install the MongoDB integration into your Next app!
#CommitYourCode | #DeveloperCommunity
@saltnburnem
Install the MongoDB integration into your Next app!
npx create-next-app --example with-mongodb close-encounters#CommitYourCode | #DeveloperCommunity
@saltnburnem
npx create-next-app --example with-mongodb close-encounterscd close-encounters
npm install
npm run dev#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
Compass is a free interactive tool for querying, optimizing, and analyzing your MongoDB data. Get key insights, drag and drop to build pipelines, and more.
#CommitYourCode | #DeveloperCommunity
@saltnburnem

#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem

#CommitYourCode | #DeveloperCommunity
@saltnburnem
Components
Pages
#CommitYourCode | #DeveloperCommunity

Types
@saltnburnem
Pages - index.tsx
import Head from "next/head";
import clientPromise from "../lib/mongodb";
import type { InferGetServerSidePropsType, GetServerSideProps } from "next";
import Container from "@mui/material/Container";
import Box from "@mui/material/Box";
import Header from "../components/Header/Header";
import EncounterCard from "../components/EncounterCard/EncounterCard";
import { useState } from "react";
import { IndexProps } from "../types";
import { Encounter } from "../types/encounter";
import { SearchBar } from "../components/SearchBar/SearchBar";#CommitYourCode | #DeveloperCommunity
@saltnburnem
Pages - index.tsx
export const getServerSideProps: GetServerSideProps<IndexProps> = async () => {
try {
await clientPromise;
const client = await clientPromise;
const db = client.db("close-encounters");
const encounters = await db
.collection("encounters")
.find({})
.limit(30)
.toArray();
return {
props: {
isConnected: true,
encounters: JSON.parse(JSON.stringify(encounters)),
},
};
} catch (e) {
console.error(e);
return {
props: { isConnected: false, encounters: [] },
};
}
};#CommitYourCode | #DeveloperCommunity
@saltnburnem
Pages - index.tsx
export default function Home ({
encounters,
}: InferGetServerSidePropsType<typeof getServerSideProps>) {
const [search, setSearch] = useState("");
const filterEncounters = (encounter: Encounter) => {
return (
encounter.name.toLowerCase().includes(search.toLowerCase()) ||
encounter.location.toLowerCase().includes(search.toLowerCase())
);
};
const filteredEncounters = encounters.filter(filterEncounters);
return (
<>
<Head>
<title>UFO Encounters and Sightings</title>
<meta
name="description"
content="A collection of UFO, UAP, and USO sightings and encounters."
/>
<link rel="icon" href="/favicon.ico" />
</Head>
<Header />
<Container maxWidth="lg">
<SearchBar setSearch={setSearch} />
<main>
<Box display="grid" gridTemplateColumns="repeat(3, 1fr)" gap={4}>
<EncounterCard encounters={filteredEncounters} />
</Box>
</main>
</Container>
<footer>
<a
href="https://www.digitalocean.com/"
target="_blank"
rel="noopener noreferrer"
>
Powered by{" "}
<img
src="/do-blue-h-logo.png"
alt="DigitalOcean Logo"
className="logo"
/>
</a>
</footer>
</>
);
}
#CommitYourCode | #DeveloperCommunity
@saltnburnem
Components - Header.tsx
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';#CommitYourCode | #DeveloperCommunity
@saltnburnem
Components - Header.tsx
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';const Header = () => {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static" sx={{ backgroundColor: '#00ff60' }}>
<Toolbar variant="dense">
<Typography variant="h6" component="div" sx={{ flexGrow: 1, color: 'black' }}>
UFO Encounters & Abductions
</Typography>
</Toolbar>
</AppBar>
</Box>
);
}
export default Header;#CommitYourCode | #DeveloperCommunity
@saltnburnem
Components - Header.tsx
const Header = () => {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static" sx={{ backgroundColor: '#00ff60' }}>
<Toolbar variant="dense">
<Typography variant="h6" component="div" sx={{ flexGrow: 1, color: 'black' }}>
UFO Encounters & Abductions
</Typography>
</Toolbar>
</AppBar>
</Box>
);
}
export default Header;
#CommitYourCode | #DeveloperCommunity
@saltnburnem
Components - SearchBar.tsx
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import { Dispatch, SetStateAction } from "react";
export const SearchBar = ({
setSearch,
}: {
setSearch: Dispatch<SetStateAction<string>>;
}) => {
return (
<Box
component="form"
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
paddingTop: "5rem",
"& > :not(style)": { m: 1, width: "50ch", fontWeight: "bold" },
}}
noValidate
autoComplete="off"
>
<TextField
onChange={(e) => setSearch(e.target.value)}
id="outlined-basic"
label="Search for UFO Sightings"
variant="outlined"
aria-label="Search for UFO Sightings"
/>
<Typography variant="body2" color="text.secondary">
*This is a list of some sample data of UFO/UAPUSO abductions and
sightings in the United States. Search for an encounter by name or
location.
</Typography>
</Box>
);
};#CommitYourCode | #DeveloperCommunity
@saltnburnem
Components - SearchBar.tsx
import Box from "@mui/material/Box";
import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography";
import { Dispatch, SetStateAction } from "react";
export const SearchBar = ({
setSearch,
}: {
setSearch: Dispatch<SetStateAction<string>>;
}) => {
return (
<Box
component="form"
sx={{
display: "flex",
justifyContent: "center",
alignItems: "center",
flexDirection: "column",
paddingTop: "5rem",
"& > :not(style)": { m: 1, width: "50ch", fontWeight: "bold" },
}}
noValidate
autoComplete="off"
>
<TextField
onChange={(e) => setSearch(e.target.value)}
id="outlined-basic"
label="Search for UFO Sightings"
variant="outlined"
aria-label="Search for UFO Sightings"
/>
<Typography variant="body2" color="text.secondary">
*This is a list of some sample data of UFO/UAPUSO abductions and
sightings in the United States. Search for an encounter by name or
location.
</Typography>
</Box>
);
};#CommitYourCode | #DeveloperCommunity

@saltnburnem
Components - EncounterCard.tsx
import * as React from "react";
import Card from "@mui/material/Card";
import CardActions from "@mui/material/CardActions";
import CardContent from "@mui/material/CardContent";
import CardMedia from "@mui/material/CardMedia";
import Typography from "@mui/material/Typography";
import Link from "@mui/material/Link";
import { EncounterProps } from "../../types/encounter";#CommitYourCode | #DeveloperCommunity
@saltnburnem
Set up some Types & Interfaces!
export type IndexProps = {
isConnected: boolean;
encounters: Encounter[];
};export type Encounter = {
_id: string;
name: string;
location: string;
close_encounter_level: string;
extraterrestrial_type: string;
image: string;
url: string;
};
export interface EncounterProps {
encounters: Encounter[];
}#CommitYourCode | #DeveloperCommunity
@saltnburnem
Components - EncounterCard.tsx
export type IndexProps = {
isConnected: boolean;
encounters: Encounter[];
};export type Encounter = {
_id: string;
name: string;
location: string;
close_encounter_level: string;
extraterrestrial_type: string;
image: string;
url: string;
};
export interface EncounterProps {
encounters: Encounter[];
}
#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
#CommitYourCode | #DeveloperCommunity
@saltnburnem
What did we learn?
NextJS
UFO History
Mongo DB/Compass
DigitalOcean
Storing Data and Deploying in the Cloud
#CommitYourCode | #DeveloperCommunity
@saltnburnem

Thanks!
#CommitYourCode | #DeveloperCommunity
Close Encounters of the Data Kind - 25 minutes
By Chris DeMars
Close Encounters of the Data Kind - 25 minutes
Close Encounters of the Data Kind - 25 minutes
- 140