
Building the DEV Community Homepage with Pure Canvas In modern frontend development, we...
title: Building the DEV Community Homepage with Pure Canvas published: true description: tags:
In modern frontend development, we are accustomed to building user interfaces with HTML and CSS. But have you ever wondered what it would be like to completely abandon the DOM tree and use pure Canvas to draw a complex modern web page (like the DEV Community homepage)?
In the react-canvas project, we took on a hardcore challenge: building the DEV Community homepage from scratch using a custom React renderer, powered by Skia (CanvasKit) and the Yoga layout engine.
🔗 Live Demo: https://react-canvas-design.vercel.app/#/devto
💻 GitHub Repository: https://github.com/ouzhou/react-canvas

To achieve this goal, we couldn't use the standard react-dom. Our underlying infrastructure includes:
In the world of pure Canvas, there are no <div>, <span>, or <img> tags. Everything is a custom node.
We replaced traditional HTML tags with the basic components provided by react-canvas:
<div> -> <View>: Acts as the basic container, supporting Flexbox layout.<span> / <p> -> <Text>: Used for text rendering, calling Skia's Paragraph API under the hood.<img> -> <Image>: Used for rendering network images.<svg> -> <SvgPath>: Used for rendering vector icons.<ScrollView>: Since Canvas has no native scrollbars, we have to handle scroll events and viewport clipping ourselves.We use CanvasProvider at the outermost layer to initialize the runtime and load the necessary fonts:
import { CanvasProvider, Canvas, View, Text } from "@react-canvas/react-v2";
import localParagraphFontUrl from "../assets/NotoSansSC-Regular.otf?url";
<CanvasProvider initOptions={{ defaultParagraphFontUrl: localParagraphFontUrl }}>
{({ isReady, runtime }) => (
<Canvas
width={vw}
height={vh}
paragraphFontProvider={runtime.paragraphFontProvider}
defaultParagraphFontFamily={runtime.defaultParagraphFontFamily}
>
{/* Page Content */}
</Canvas>
)}
</CanvasProvider>
Thanks to Yoga, we can use Flexbox layout just like in React Native. All styles are inline JS objects rather than CSS classes:
// Example layout for the DEV top navigation bar
<View
style={{
width: vw,
height: 56,
backgroundColor: "#ffffff",
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between",
paddingLeft: 16,
paddingRight: 16,
}}
>
{/* Logo and Navigation Items */}
</View>
In the DOM, we typically use the :hover pseudo-class to handle mouse hover states. In react-canvas, the style property supports passing a function that receives the current interaction state:
<View
style={({ hovered }) => ({
padding: 16,
backgroundColor: hovered ? "rgba(59, 73, 223, 0.1)" : "transparent", // Change background on hover
cursor: "pointer",
})}
>
<Text style={({ hovered }) => ({ color: hovered ? "#3b49df" : "#404040" })}>
Home
</Text>
</View>
In traditional CSS, we can easily write border-bottom: 1px solid #e5e5e5. However, in our current custom renderer, support for single-sided borders is still being refined.
To draw perfect 1px dividers in Canvas, we use absolutely positioned <View> elements to simulate them:
// Simulating border-bottom
<View style={{
position: "absolute",
bottom: 0,
left: 0,
right: 0,
height: 1,
backgroundColor: "#e5e5e5"
}} />
By combining these basic capabilities, we successfully replicated the complex layout of the DEV Community homepage 1:1, including:
All rendering is done entirely within a single <canvas> tag!
Building complex Web UIs with pure Canvas is a fascinating exploration. While it loses the accessibility (A11y), SEO, and native text selection capabilities provided by the DOM, it offers ultimate rendering control and cross-platform consistency (the exact same code can easily be ported to native mobile apps or even desktop environments).
This is the core appeal of technologies like Flutter and React Native Skia. Through react-canvas, we've brought this "pixel-perfect control" experience to the Web.
gemmaI ported the whole Gemma-4 family — E2B, E4B, 12B, 31B, and the 26B-A4B MoE — to run on...
communityHey DEV, I'm Tobore. Let's actually connect. I've been on here for a while now, mostly writing and...
ai(yep, kinda clickbait, just for the funsies 😊) At the beginning of the year, I relaunched my...
aiMy laptop was sitting idle with the fan at full tilt. Nothing was running that I knew of. The culprit...
githubactionsI Built a Thing! TL;DR — Google Gemini-based Pull Request reviews and Issue Triaging for...
aiI've been hearing the word "harness" thrown around a lot lately. I assumed it just meant "the IDE" or...
Workflows from the Neura Market marketplace related to this Stable Diffusion resource