Skip to content

Latest commit

Β 

History

64 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

⚑ EINCODE β€” Where Code Meets Curiosity

Ein's Digital Laboratory. Not a portfolio. A laboratory. Experiments, prototypes, and open-source artifacts β€” forged, tested, and refined in public.

EINCODE Banner

Live Next.js React Tailwind TS

pnpm Node License PRs


Table of Contents


Philosophy

EINCODE is built as a digital workshop, not a static showcase:

  • Forge in public β€” every experiment ships with source, live demo, and lab notes.
  • Lab over gallery β€” WIP is first-class. Progress bars, status indicators, and field notes tell the story of how it was built.
  • Content as code β€” blog posts are MDX files versioned in content/ (content/building-linux-distro-from-scratch.mdx:1), rendered with next-mdx-remote + shiki + rehype.
  • Modern by default β€” Next.js 16 App Router, React 19 Server Components, Tailwind v4 CSS-first config, next/font optimized fonts.

If you want a template for a fast, SEO-perfect, MDX-powered personal site that still feels like a hacker lab β€” this is it.


πŸ”— Live Demo

Environment URL
Production https://eindev.ir
Alt Domain https://eincode.dev (see .env.example:2)

Preview the hero's typewriter, projects grid, lab notes, and workbench directly on the homepage β€” app/page.tsx:10 composes Header, HeroSection, ProjectsGrid, LabNotes, Workbench, Footer.


✨ Features

Area What you get
Hero Lab Typewriter role rotation ("building interfaces", "crafting code"), ASCII terminal, floating version badge β€” components/hero-section.tsx:6
Artifacts Grid 8 open-source projects with shipped / in-progress / archived filters, stars/forks, glassmorphism & hover-lift β€” components/projects-grid.tsx:7
Workbench Live WIP terminal with progress bars (60–90%), ~/ehsanghaffar/active header β€” components/workbench.tsx:4
Lab Notes 4 field notes with category pills & gradient hovers β€” components/lab-notes.tsx:7
Blog Engine File-based MDX in content/ (8 posts), gray-matter frontmatter, GFM, autolink headings, pretty-code β€” lib/mdx-utils.ts:8
Theming Dark/light/system with next-themes, ThemeProvider (app/layout.tsx:100), ThemeToggle + ThemeChanger, OKLCH tokens, globals.css:8
MDX Pipeline next-mdx-remote + rehype-slug + rehype-autolink-headings + rehype-pretty-code (shiki) + remark-gfm β€” components/mdx-remote.tsx:1
SEO Mastery metadata (app/layout.tsx:25), JSON-LD (lib/structured-data.ts:32), sitemap.ts:4 + robots.ts:3, OG image public/og-image.png
A11y + Perf next/font (Geist, Geist_Mono, Space_Grotesk), AVIF/WebP images (next.config.mjs:5), reduced-motion, touch targets 44px β€” app/globals.css:640
UI Kit shadcn/ui on Radix primitives β€” 20+ components in components/ui/ (accordion, dialog, dropdown-menu, etc.)
Analytics Vercel Analytics injected in root layout β€” app/layout.tsx:103

🧱 Tech Stack

Core

Tech Version Purpose Config
Next.js 16.1.0 App Router, Turbopack, SSR/SSG, Metadata API next.config.mjs:1
React 19.2.3 Server Components, use client islands package.json:64
TypeScript 5.9.3 Strict types, path alias @/* tsconfig.json:25
Tailwind CSS 4.1.9 CSS-first @import "tailwindcss", OKLCH, @plugin typography app/globals.css:1

UI & Styling

Tech Details
Radix UI 16 primitives β€” accordion, dialog, popover, tabs, toast, etc. β€” package.json:24
shadcn/ui components.json + components/ui/ + lib/utils.ts:1 (cn = clsx + tailwind-merge)
Lucide React 0.454.0 icons throughout
next-themes 0.4.6 class-based dark mode
tw-animate-css 1.3.3 animation utilities

Content & Markdown

Tech Usage
next-mdx-remote 6.0.0 Serialize & hydrate MDX
gray-matter 4.0.3 Frontmatter parsing β€” lib/mdx-utils.ts:3
remark-gfm 4.0.1 GitHub Flavored Markdown
rehype-slug / autolink-headings / pretty-code Anchors + Shiki highlighting
shiki 3.22.0 Syntax highlighting
@tailwindcss/typography 0.5.19 Prose styling .prose β€” app/globals.css:163

Tooling

Tech Version
pnpm >=9 recommended (lockfile pnpm-lock.yaml)
ESLint eslint . β€” package.json:18
Vercel Analytics latest
zod 3.25, react-hook-form 7.60, recharts 2.15, date-fns 4.1, embla-carousel... Extra UI deps pre-wired

πŸ“ Project Structure

eincode/
β”œβ”€β”€ app/                          # Next.js 16 App Router β€” app/layout.tsx:92
β”‚   β”œβ”€β”€ (public)/                 # Route group (shared layout)
β”‚   β”‚   β”œβ”€β”€ blog/
β”‚   β”‚   β”‚   β”œβ”€β”€ [postSlug]/page.tsx  # Dynamic MDX post β€” lib/mdx-utils.ts:34
β”‚   β”‚   β”‚   └── page.tsx             # Blog index
β”‚   β”‚   β”œβ”€β”€ projects/page.tsx
β”‚   β”‚   β”œβ”€β”€ workbench/page.tsx
β”‚   β”‚   β”œβ”€β”€ notes/page.tsx
β”‚   β”‚   β”œβ”€β”€ introduction/page.tsx
β”‚   β”‚   └── layout.tsx
β”‚   β”œβ”€β”€ page.tsx                  # Homepage β€” composes 6 sections
β”‚   β”œβ”€β”€ layout.tsx                # Root layout, fonts, metadata, ThemeProvider
β”‚   β”œβ”€β”€ globals.css               # Tailwind v4 + OKLCH tokens + animations
β”‚   β”œβ”€β”€ sitemap.ts                # Dynamic sitemap from MDX β€” app/sitemap.ts:4
β”‚   β”œβ”€β”€ robots.ts                 # Robots.txt β€” app/robots.ts:3
β”‚   β”œβ”€β”€ error.tsx / not-found.tsx
β”‚   └── favicon.ico
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ hero-section.tsx          # Typewriter + ASCII terminal
β”‚   β”œβ”€β”€ projects-grid.tsx         # Filterable artifacts grid
β”‚   β”œβ”€β”€ workbench.tsx             # Terminal-style WIP list
β”‚   β”œβ”€β”€ lab-notes.tsx             # Field notes grid
β”‚   β”œβ”€β”€ header.tsx / footer.tsx
β”‚   β”œβ”€β”€ cursor-glow.tsx
β”‚   β”œβ”€β”€ mdx-remote.tsx / mdx-components.tsx
β”‚   β”œβ”€β”€ theme-provider.tsx / theme-toggle.tsx / theme-changer.tsx
β”‚   └── ui/                       # 20+ shadcn/ui components
β”œβ”€β”€ content/                      # MDX blog source (8 posts)
β”‚   β”œβ”€β”€ building-linux-distro-from-scratch.mdx
β”‚   β”œβ”€β”€ mcp-protocol-llm-applications.mdx
β”‚   β”œβ”€β”€ nextjs-16-tailwind-v4-migration.mdx
β”‚   └── ... (5 more)
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ mdx-utils.ts              # getAllMDXPosts(), getMDXPostBySlug()
β”‚   β”œβ”€β”€ blog-data.tsx             # Legacy in-memory posts + helpers
β”‚   β”œβ”€β”€ structured-data.ts        # JSON-LD: BlogPosting, WebSite, Person
β”‚   β”œβ”€β”€ themes.ts / utils.ts
β”œβ”€β”€ types/mdx.ts                  # BlogPostFrontmatter, BlogPost
β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ og-image.png / og-images/
β”‚   β”œβ”€β”€ icon.svg / apple-icon.png
β”‚   └── site.webmanifest
β”œβ”€β”€ docs/                         # architecture.md, performance.md, etc.
β”œβ”€β”€ next.config.mjs               # AVIF/WebP, deviceSizes
β”œβ”€β”€ components.json               # shadcn config
β”œβ”€β”€ tsconfig.json                 # @/* alias
└── package.json

πŸš€ Getting Started

Prerequisites

  • Node.js >=18 (20+ recommended)
  • pnpm β€” npm i -g pnpm or see pnpm.io
  • Git

1. Clone & Install

git clone https://github.com/ehsanghaffar/eincode.git
cd eincode
pnpm install

2. Environment

cp .env.example .env
# edit .env
Variable Required Default Description
NEXT_PUBLIC_SITE_URL No https://eindev.ir Canonical URL for metadata/sitemap β€” app/layout.tsx:26
NEXT_PUBLIC_GITHUB_URL No https://github.com/ehsanghaffar Social link
NEXT_PUBLIC_TWITTER_URL No β€” Social link
NEXT_PUBLIC_LINKEDIN_URL No β€” Social link

No database, no API keys. The site is fully static + MDX. Analytics is zero-config on Vercel.

3. Run Dev Server (Turbopack)

pnpm dev
# β†’ http://localhost:3000

Hot reload is near-instant with Next.js 16 Turbopack.

4. Production Build

pnpm build
pnpm start
# β†’ http://localhost:3000 (optimized)

✍️ Content Authoring β€” MDX

All posts live in content/*.mdx and are read at build time via lib/mdx-utils.ts:8.

Frontmatter Schema β€” types/mdx.ts:1

---
title: "Building a Linux Distro from Scratch"
excerpt: "A comprehensive guide to compiling the kernel..."
date: "2025-11-15"          # display date
dateISO: "2025-11-15"       # used for sorting β€” lib/mdx-utils.ts:29
category: "systems"          # systems | ai | frontend
readTime: "12 min read"
tags: ["linux", "kernel", "devops"]
author: "Ehsan Ghaffar"
published: true              # false = draft, filtered out
image: "/og-images/my-post.png"  # optional
---

Create a New Post

# 1. Add file
touch content/my-new-post.mdx

# 2. Write MDX β€” supports GFM, code blocks with Shiki, headings with anchors
---
title: "My New Post"
excerpt: "One-line hook for the blog index."
date: "2026-08-23"
dateISO: "2026-08-23"
category: "frontend"
readTime: "5 min read"
tags: ["nextjs", "tailwind"]
published: true
---

## Introduction

Hello MDX!

```ts
export const hello = "world"
```

> Tip: headings auto-get `id` + anchor links via `rehype-slug` + `rehype-autolink-headings`.

No restart needed in dev β€” just refresh. For production, the post is auto-added to sitemap.ts:48.

Helpers

import { getAllMDXPosts, getMDXPostBySlug, getAllMDXCategories } from "@/lib/mdx-utils"
import { getPostBySlug, getRelatedPosts } from "@/lib/blog-data" // legacy helper

πŸ—Ί Routes & App Router

Route File Description
/ app/page.tsx:10 Hero + Projects + Lab Notes + Workbench + Footer
/blog app/(public)/blog/page.tsx Paginated MDX listing
/blog/[postSlug] app/(public)/blog/[postSlug]/page.tsx MDX render + JSON-LD + related posts
/projects app/(public)/projects/page.tsx Full artifacts archive
/workbench app/(public)/workbench/page.tsx Dedicated WIP view
/notes app/(public)/notes/page.tsx Lab notes archive
/introduction app/(public)/introduction/page.tsx About / intro
/sitemap.xml app/sitemap.ts:4 Auto-generated from static + MDX routes
/robots.txt app/robots.ts:3 allow: /, disallow: /api/, /_next/

Static routes use weekly/daily changeFrequency; blog posts use monthly with priority: 0.7.


🎨 Design System

Tokens β€” app/globals.css:8

  • OKLCH palette β€” oklch(0.5 0.22 170) primary (teal) for both light & dark, with tailored lightness.
  • CSS-first Tailwind v4 β€” no tailwind.config.js; all tokens in @theme inline β€” app/globals.css:86.
  • Fonts β€” Geist (sans), Geist_Mono (mono), Space_Grotesk via next/font/google with display: swap + CSS variables β€” app/layout.tsx:9.

Utilities

  • .glass / .glass-strong β€” backdrop-blur + saturate
  • .hover-lift β€” translateY(-4px) + shadow
  • .cursor-glow β€” 400px radial gradient following cursor (hidden on mobile) β€” app/globals.css:188
  • .scanlines β€” subtle repeating linear gradient overlay β€” app/globals.css:206
  • Animations: fade-in-up, scale-in, slide-in-*, float, pulse-glow, shimmer + stagger-1..8

Theming

// app/layout.tsx:100
<ThemeProvider attribute="class" defaultTheme="dark" enableSystem storageKey="theme-mode">

Toggle via components/theme-toggle.tsx and multi-theme switcher components/theme-changer.tsx + lib/themes.ts.


πŸ” SEO & Performance

  • Metadata API β€” title.template, openGraph, twitter, robots, icons, manifest β€” app/layout.tsx:25
  • JSON-LD β€” WebSite + Person on homepage (app/page.tsx:12), BlogPosting + BreadcrumbList on posts β€” lib/structured-data.ts:3
  • Sitemap & Robots β€” dynamic, MDX-aware
  • Images β€” formats: ['image/avif','image/webp'], 8 deviceSizes β€” next.config.mjs:5
  • Fonts β€” next/font self-hosted, no CLS
  • A11y β€” prefers-reduced-motion, 44px touch targets, focus-visible rings, semantic headings
  • Perf β€” Turbopack dev, transform: translateZ(0) hardware accel, blur reduction on touch devices β€” app/globals.css:140

Check deeper dives in docs/performance.md, docs/accessibility.md, docs/architecture.md.


πŸ“œ Scripts

Command Description Source
pnpm dev Start dev server (Turbopack) next dev
pnpm build Production build next build
pnpm start Serve production build next start
pnpm lint ESLint eslint .
pnpm analyze Bundle analyzer next experimental-analyze

☁️ Deployment

Optimized for Vercel β€” zero config.

# via CLI
pnpm i -g vercel
vercel --prod

# or connect GitHub repo β†’ Vercel auto-deploys on push

Other platforms (Netlify, Docker, Node server): pnpm build && pnpm start serves on PORT (default 3000). For Docker, see the sibling template next16-docker-tw4-starter.

Environment on Vercel: set NEXT_PUBLIC_SITE_URL to your production domain.


🀝 Contributing

Contributions are welcome β€” especially fixes to MDX rendering, a11y, or new lab notes!

  1. Open an issue for larger changes
  2. Branch: git checkout -b feat/my-change
  3. Commit with clear messages
  4. PR with screenshots for UI changes, and ensure pnpm build passes

Code style: TypeScript strict, eslint ., Tailwind v4 utilities, Radix + shadcn patterns.


πŸ“„ License & Author

MIT Β© 2024–2025 Ehsan Ghaffar β€” github.com/ehsanghaffar Β· eindev.ir Β· twitter.com/ehsanghaffar

Built with ❀️, oklch, and a healthy obsession with next/font.


Forge. Break. Rebuild. Repeat. β€” EINCODE

About

A modern personal portfolio and digital laboratory built with Next.js 16, React 19 and cutting-edge web technologies.

Topics

Resources

Stars

10 stars

Watchers

0 watching

Forks

Contributors

Languages