Animation-heavy personal portfolio on Next.js: a custom cursor, a page-transition loader, and canvas backgrounds.
canvas-animationscss-modulesdark-themehandcodednextjspersonal-websiteportfolioreact
1<!DOCTYPE html>
2<html lang="en">
3<head>
4<meta charset="UTF-8">
5<style>
6 @page {
7 size: letter;
8 margin: 0;
9 }
10
11 * {
12 margin: 0;
13 padding: 0;
14 box-sizing: border-box;
15 }
16
17 body {
18 font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
19 font-size: 9.5pt;
20 line-height: 1.35;
21 color: #1a1a1a;
22 width: 816px;
23 height: 1056px;
24 overflow: hidden;
25 -webkit-print-color-adjust: exact;
26 print-color-adjust: exact;
27 }
28
29 .page {
30 position: relative;
31 width: 816px;
32 height: 1056px;
33 overflow: hidden;
34 }
35
36 /* Sidebar - right column, absolutely positioned */
37 .sidebar {
38 position: absolute;
39 top: 0;
40 right: 0;
41 width: 240px;
42 height: 1056px;
43 background: #1e293b;
44 color: #e2e8f0;
45 padding: 0;
46 display: flex;
47 flex-direction: column;
48 }
49
50 .sidebar .contact {
51 background: #2563eb;
52 padding: 36px 24px 20px 24px;
53 }
54
55 .sidebar .contact .title {
56 font-size: 11pt;
57 font-weight: 700;
58 margin-bottom: 4px;
59 }
60
61 .sidebar .contact .location {
62 font-size: 9pt;
63 margin-bottom: 8px;
64 color: #dbeafe;
65 }
66
67 .sidebar .contact .phone,
68 .sidebar .contact .email {
69 font-size: 9pt;
70 color: #fff;
71 }
72
73 .sidebar .contact .phone {
74 font-weight: 700;
75 margin-bottom: 2px;
76 }
77
78 .sidebar .contact a {
79 color: #fff;
80 text-decoration: none;
81 }
82
83 .sidebar-content {
84 padding: 14px 24px;
85 display: flex;
86 flex-direction: column;
87 gap: 12px;
88 }
89
90 .sidebar h4 {
91 font-size: 9.5pt;
92 font-weight: 700;
93 text-transform: uppercase;
94 letter-spacing: 0.5px;
95 color: #94a3b8;
96 border-bottom: 1px solid #334155;
97 padding-bottom: 3px;
98 margin-bottom: 4px;
99 }
100
101 .sidebar .links a {
102 display: block;
103 font-size: 9pt;
104 color: #93c5fd;
105 text-decoration: none;
106 margin-bottom: 1px;
107 }
108
109 .sidebar .skills-list,
110 .sidebar .tech-list {
111 list-style: none;
112 padding: 0;
113 }
114
115 .sidebar .skills-list li {
116 font-size: 9pt;
117 margin-bottom: 1px;
118 color: #cbd5e1;
119 }
120
121 .sidebar .tech-list li {
122 display: inline;
123 font-size: 9pt;
124 color: #cbd5e1;
125 }
126
127 .sidebar .tech-list li:not(:last-child)::after {
128 content: ", ";
129 }
130
131 .sidebar .education-entry {
132 font-size: 9pt;
133 color: #cbd5e1;
134 }
135
136 .sidebar .education-entry .school {
137 font-weight: 700;
138 color: #e2e8f0;
139 }
140
141 /* Main content - left column */
142 .main {
143 margin-right: 240px;
144 padding: 36px 32px 36px 38px;
145 height: 1056px;
146 overflow: hidden;
147 }
148
149 .main h1 {
150 font-size: 26pt;
151 font-weight: 700;
152 line-height: 1.1;
153 margin-bottom: 5px;
154 color: #111;
155 }
156
157 .main .summary {
158 font-size: 9.5pt;
159 color: #444;
160 margin-bottom: 14px;
161 line-height: 1.4;
162 }
163
164 .main h2 {
165 font-size: 10.5pt;
166 font-weight: 700;
167 color: #2563eb;
168 text-transform: uppercase;
169 letter-spacing: 0.5px;
170 border-bottom: 1px solid #2563eb;
171 padding-bottom: 2px;
172 margin-bottom: 8px;
173 margin-top: 12px;
174 }
175
176 .main h2:first-of-type {
177 margin-top: 0;
178 }
179
180 .main h2 .section-note {
181 font-size: 8.5pt;
182 font-weight: 400;
183 text-transform: none;
184 letter-spacing: 0;
185 color: #2563eb;
186 }
187
188 .entry {
189 margin-bottom: 8px;
190 }
191
192 .entry h3 {
193 font-size: 10.5pt;
194 font-weight: 700;
195 color: #111;
196 margin-bottom: 1px;
197 }
198
199 .entry h3 em {
200 font-weight: 400;
201 font-style: italic;
202 }
203
204 .entry .meta {
205 font-size: 8.5pt;
206 color: #666;
207 margin-bottom: 3px;
208 }
209
210 .entry ul {
211 padding-left: 16px;
212 margin: 0;
213 }
214
215 .entry li {
216 font-size: 9pt;
217 margin-bottom: 1px;
218 color: #333;
219 line-height: 1.35;
220 }
221</style>
222</head>
223<body>
224 <div class="page">
225 <div class="main">
226 <h1>{{name}}</h1>
227 <p class="summary">{{summary}}</p>
228 {{body}}
229 </div>
230 <div class="sidebar">
231 <div class="contact">
232 <div class="title">{{title}}</div>
233 <div class="location">{{location}}</div>
234 <div class="phone">{{phone}}</div>
235 <div class="email"><a href="mailto:{{email}}">{{email}}</a></div>
236 </div>
237 <div class="sidebar-content">
238 <div class="links-section">
239 <h4>Links</h4>
240 <div class="links">
241 {{links}}
242 </div>
243 </div>
244 <div class="skills-section">
245 <h4>Skills</h4>
246 <ul class="skills-list">
247 {{skills}}
248 </ul>
249 </div>
250 <div class="tech-section">
251 <h4>Technologies</h4>
252 <ul class="tech-list">
253 {{technologies}}
254 </ul>
255 </div>
256 <div class="education-section">
257 <h4>Education</h4>
258 {{education}}
259 </div>
260 </div>
261 </div>
262 </div>
263</body>
264</html>