This repository contains the source for my personal website and blog. I am keeping it public as a reference for academics, roboticists, and researchers who want something more personal than a generic template: a place to show projects and publications, but also a place to write longer notes, build logs, essays, and half-formed thoughts.
The site uses a comic-book-inspired layout with readable article pages, MDX blog posts, project/publication panels, RSS, and a small optional likes feature. The visual system is mostly CSS: rough panel borders, hand-drawn link annotations, extruded hover states, and dithered image treatment.
If you use this as a starting point, I would recommend changing the visual language to fit your own taste and work. The comic-panel style fits this site because I like it; it does not need to become the official uniform of every robotics PhD on the internet, haha.
- Next.js App Router
- React and TypeScript
- MDX for blog posts
- CSS-first styling with custom comic-panel and sketch effects
- RSS feed, sitemap, robots file, and article metadata
- Optional lightweight blog engagement API through
NEXT_PUBLIC_LIKES_API_URL
app/
about/
blog/
posts/ MDX blog posts
[slug]/ individual blog pages
projects/
publications/
globals.css site-wide visual system
components/
BlogExplorer.tsx blog listing, search, tags, and like counts
ArticleLikeButton.tsx article like button
ComicPanel.tsx reusable panel wrapper
LinkSketches.tsx hand-drawn hover annotations
SAButton.tsx shared button adapter
SAPanel.tsx shared panel adapter
nav.tsx sidebar and mobile navigation
packages/sa-ui/
src/ CSS source modules and the enhancer source
react/ thin React adapters
dist/ committed CSS and JavaScript files
examples/ plain HTML examples
public/
images, logos, icons, and static assets
packages/sa-ui contains the shared visual contract. The package has CSS tokens, base styles, layouts, components, effects, slide patterns, an optional enhancer, and React adapters.
Import the full CSS contract in a CSS-aware application:
import '@senthur/sa-ui/styles.css'
import '@senthur/sa-ui/fonts.css'The font import is optional. Omit it when the application does not use the handwriting font.
For a smaller CSS contract, import the required source modules directly:
import '@senthur/sa-ui/tokens.css'
import '@senthur/sa-ui/base.css'
import '@senthur/sa-ui/layouts.css'
import '@senthur/sa-ui/effects.css'
import '@senthur/sa-ui/components/button.css'Load tokens.css before every direct module. Load effects.css before button or panel CSS when the component uses extrusion.
Use data-sa-active="true" for the visual state of a noninteractive tag. Use aria-pressed="true" on a toggle button.
Use aria-current on a current link. The native attributes apply the same active style and preserve the state semantics.
Import the React adapters when the application uses React:
import { Button, Panel, SketchAnnotation } from '@senthur/sa-ui/react'Run the plain HTML slide example from the repository root:
npm run demo --workspace @senthur/sa-uiOpen http://localhost:4173/examples/slides.html. The example loads the committed files in packages/sa-ui/dist/. It has no framework build step.
Keep application content outside the package. Project cards, publication cards, navigation, routes, and application state belong to the application.
Install dependencies:
npm installStart the development server:
npm run devBuild the production version:
npm run buildStart the production server locally:
npm run startBlog posts live in app/blog/posts as .mdx files. Each post uses frontmatter for metadata:
---
title: My Post Title
publishedAt: 2026-01-01
summary: A short description of the post.
image: /projects/example.jpg
imagePosition: center center
tags: robotics, design
---
Post content goes here.The site automatically reads the post metadata for the blog index, individual article pages, RSS feed, sitemap, and structured article data.
The blog supports optional view and like counts for each post. The site records one view for each anonymous browser and post pair. A database constraint ignores reloads from the same browser.
Set NEXT_PUBLIC_LIKES_API_URL to point the frontend at that service. The variable name stays unchanged for deployment compatibility. Without it, the site still builds and runs without remote engagement controls.
This repository is public as a reference for the website implementation. The code can be used as inspiration, but the writing, images, logos, and personal branding are specific to this site.