How I Started a Website
Using other peopleβs code
Iβm trying to make a new website, and this will be the first in a series of DevLogs about my development process as I build this website.
The idea of the website came from the need to store information that isnβt necessarily deserving of an entire blog post. These posts cover some of the things that Iβm currently doing as well as some fundamentals of software development.
The tentative name is reference.bayanbennett.com and will serve as an ever-evolving repository of information. Whenever Iβm referencing things, I can point to reference.bayanbennett.com and the page could contain interactive examples, information, and links to other resources. Of course, the site hasnβt been built yet, so the future is still uncertain.
Starting from an Example Project
I decided to start with a Next.js project with Material UI and TypeScript. Hereβs the source: https://github.com/mui-org/material-ui/tree/next/examples/nextjs-with-typescript. As I have not built a production site using Next.js, Iβm going to be making little mistakes and learning a lot.
The only thing that is different about this project and the Material UI template is that I've emptied index.tsx
.
import React from "react";
const IndexPage = () => <>Heh</>;
export default IndexPage;
Iβve also included a layout component in _app.tsx
. Note: the +
simply denotes that the line has been added.
+ import { Layout } from "../layout";/* rest of file is the same */<ThemeProvider theme={theme}>
<CssBaseline />
+ <Layout>
<Component {...pageProps} />
+ </Layout>
</ThemeProvider>
The layout.tsx
file simply is as follows:
import React from "react";
import { AppBar, Container, Toolbar, Typography } from "@material-ui/core";
export const Layout: React.FunctionComponent = ({ children }) => (
<>
<AppBar position="sticky">
<Toolbar>
<Typography variant="h6">Reference</Typography>
</Toolbar>
</AppBar>
<Container>{children}</Container>
</>
);
Proof of Concept for Interactive Examples
I wanted to have an interactive console window that would have example code in it that the user could run, see the results on the page, and modify to their liking. The examples could also include tests, using console.assert
, that the user could run and see the results. There is an overwhelming number of possibilities, but the goal is that a visitor could, at a glimpse, explore a concept on a dedicated page.
For example, I have a post about exponential back-off and retries. The page goes through the code and it lists all the code, but there is no interactivity. Sites like CodeSandbox, JSFiddle, StackBlitz, and CodePen are fantastic resources, but with much more extensive feature sets than what I have in mind. A better comparison would be with the TensorFlowJS documentation, where the user can quickly run code samples and see the output.
Creating a Page
First, weβll need to create a page to show an interactive example for String
s in JavaScript.
/* src/JavaScript/String/index.tsx */import React from "react"const StringPage = () => <>This is the Strings Page</>export default StringPage
Designing a Code Editor Wireframe
MDN is one of the best resources for documentation about web technologies. I was inspired by their code editor that can be found on some of their pages. Take String.length
for example: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/length
For my own reference site, I wanted to have minimal interactive examples and not so much of the depth that MDN provides β Iβm not trying to create an explanatory page.
After a few minutes of playing with a few options, I produced this preliminary layout:
Of course, this is just the first pass at a wireframe. As I progress, the design will undoubtedly change.
Translating the Wireframe to Material UI Components
Since this is a new project, I decided to use Material UI v5, which is currently in its alpha phase. The hope is, by the time that my site is ready, Material UI v5 will also be ready and I donβt have to migrate from v4 β‘ v5. The main drawback of this choice is dealing with bugs and breaking changes.
The layout is housed in the <Container>
component, which limits its width via the maxWidth
attribute. See: https://next.material-ui.com/api/container/
Material UIβs basic layout component is the <Box>
(the same as a <div>
): https://next.material-ui.com/components/box/. Hereβs what the wireframe looks like implemented with the <Box>
component.
import React from "react";
import { Box, Fab } from "@material-ui/core";
import { PlayArrow } from "@material-ui/icons";
const fabStyle = {
position: "absolute",
bottom: 0,
right: 0,
};
const StringPage = () => {
/* Some stuff will go here later */ return (
<>
<Box sx={{ display: "flex", flexDirection: "row" }}>
<Box sx={{ position: "relative", flex: 2 }}>
<textarea />
<Fab size="small" sx={fabStyle}>
<PlayArrow />
</Fab>
</Box>
<Box sx={{ flex: 1, backgroundColor: "rgba(0,0,0,0.1)" }}>{result}</Box>
</Box>
</>
);
};
Evaluating Code
At first, I used React.setState
and onChange
on the <textarea>
tag. A handleChange
function would evaluate the code and save it to the state. However, this meant that code was evaluated on every keypress. When the user would type in βcβ to begin typing βconstβ, the eval
function would throw an error.
The wireframe included a button to evaluate code, so I quickly corrected this oversight and used the onClick
attribute on the <Fab>
component instead. This also meant that I could use an uncontrolled <textarea>
. To read the value of the <textarea>
I could use React.useRef
and pass it to the <textarea>
via the ref
attribute.
Hereβs the result:
import React from "react";
import { Box, Fab } from "@material-ui/core";
import { PlayArrow } from "@material-ui/icons";
const fabStyle = {
position: "absolute",
bottom: 0,
right: 0,
};
const StringPage = () => {
const [result, setResult] = React.useState("");
const codeRef = React.useRef<HTMLTextAreaElement>(null);
const evaluateCode = () => {
if (codeRef.current === null) return;
const code = codeRef.current.value;
if (code.length === 0) return;
try {
setResult(eval(code));
} catch (e) {
console.warn(e);
}
};
return (
<>
<Box sx={{ display: "flex", flexDirection: "row" }}>
<Box sx={{ position: "relative", flex: 2 }}>
<textarea ref={codeRef} />
<Fab size="small" sx={fabStyle} onClick={evaluateCode}>
<PlayArrow />
</Fab>
</Box>
<Box sx={{ flex: 1, backgroundColor: "rgba(0,0,0,0.1)" }}>{result}</Box>
</Box>
</>
);
};
export default StringPage;
Hereβs an example:
TL;DR
In this post, we took a quick look at how I started a simple project from some example code and created a proof-of-concept. The idea is to create a website that I can use to create interactive reference pages. These pages should have code samples that can be executed by the user. In the end, I was able to create a short function that evaluates the given code. The next step is UX/UI refinements, which include displaying the result on the page.