wrttn-essays is a personal blog and rigorous practice platform dedicated to analytical writing, self-discovery, and enhancing essay skills for high-stakes examinations like the UPSC Civil Services Examination (CSE) Mains.
The core goal of this project is to provide a structured environment for:
- Developing Argumentation: Transforming raw ideas into clear, well-structured arguments.
- Skill Brushing: Improving clarity, grammar, and expressive ability through consistent practice.
- UPSC Preparation: Serving as a dedicated repository for essays that build the necessary analytical rigor and eloquence for the Mains essay paper.
This application is built with the Next.js App Router and uses Server Components for efficient data fetching from Markdown files.
- Framework: Next.js 16+ (App Router)
- Language: TypeScript
- Styling: Tailwind CSS (for rapid utility-first styling)
- Icons: lucide-react (ArrowUp, Download, ArrowLeft)
- Markdown Parsing: react-markdown with remark-gfm
- Metadata Extraction: gray-matter
- Font: Google Font & Next/Font (Lora & Inter)
- Data Source: Markdown files in
/contentdirectory
- Appears when user scrolls down more than 300px on essay pages
- Smooth scroll animation to the top
- Fixed position button (bottom-right corner)
- Mobile-responsive sizing (smaller on mobile, larger on desktop)
- Uses
ArrowUpicon from lucide-react
- Download icon button in essay detail header (top-right)
- Shows tooltip: "Preview hand-written pdf" on hover
- Automatically detects if PDF exists for the essay
- Button is hidden if PDF is not available
- Opens PDF in a new tab when clicked
- PDFs are stored in
/public/pdfs/{essayId}.pdf
- Responsive header navigation (gap reduces on mobile)
- Adaptive font sizes across all components
- Reduced padding/spacing on mobile devices for optimal viewing
- Touch-friendly button sizes
- Optimized EssayCard and EssayDetail layouts for small screens
- Excludes disclaimer section from word count calculations
- Removes Markdown syntax before counting words
- More accurate reading time estimation (based on 200 WPM)
- Generates excerpt from actual essay content only
Follow these steps to set up and run the project locally.
Ensure you have the following installed:
- Node.js (LTS version)
- npm or yarn
Clone the repository and install dependencies:
git clone https://github.com/bentekku/wrttn-essays.git
cd wrttn-essays
npm install # or yarn installThe application reads essay content from Markdown files in the /content directory with YAML front matter:
---
title: "Your Essay Title"
date: "December 27, 2025"
tags: ["Tag1", "Tag2"]
---
## Your essay content here...To enable PDF download feature:
- Place PDF files in
/public/pdfs/directory - Name them matching the essay filename (e.g.,
the-years-teach-much-which-the-days-never-know.pdf) - The download button automatically appears if a matching PDF exists
Start the development server with:
npm run dev # or yarn devOpen http://localhost:3000 in your browser to see the result.
The project adheres to the Next.js App Router conventions:
| Path | Description |
|---|---|
app/page.tsx |
The primary Essay List Page (Server Component). Fetches and sorts essays by date. |
app/essays/[id]/page.tsx |
The Dynamic Essay Detail Page (Server Component). Displays individual essays with scroll-to-top & PDF features. |
app/[about]/page.tsx |
The About Page component. |
components/Header.tsx |
Navigation header with responsive design. |
components/Footer.tsx |
Footer with social links. |
components/EssayList.tsx |
Lists all essays in chronological order. |
components/EssayCard.tsx |
Card component for each essay preview. |
components/EssayDetail.tsx |
Full essay view with PDF download button (Client Component). |
components/ScrollToTop.tsx |
Scroll-to-top button component (Client Component). |
libs/utils.ts |
Utility functions for calculating word count, read time, and excerpt. |
libs/types.ts |
TypeScript type definitions. |
libs/essays.ts |
Server-side functions for fetching essay data from Markdown files. |
content/ |
Directory containing essay Markdown files. |
public/pdfs/ |
Directory for essay PDF files (optional). |
- Markdown-Based Content: Stored in
/contentdirectory with YAML front matter - Server-Side Processing: Uses
fs,path, andgray-matterlibrary for data fetching - Smart Calculations: Word count excludes disclaimer sections and Markdown syntax, read time based on 200 WPM, excerpts extracted from cleaned content
Scroll-to-Top Button (components/ScrollToTop.tsx):
- Client Component with scroll event listener
- Conditional rendering based on scroll position (> 300px)
- Smooth scroll animation using
window.scrollTo() - Mobile-responsive with responsive padding and icon sizing
PDF Download Button (components/EssayDetail.tsx):
- Async PDF existence check using HEAD request on component mount
- Conditional rendering (only shows if PDF exists)
- Opens PDF in new tab on click
- Uses tooltip for UX clarity
Mobile Responsiveness:
- Tailwind breakpoints (
md:) for responsive design - Adaptive padding, margins, and font sizes
- Root Route:
/renders the sorted essay list - Dynamic Route:
/essays/{essayId}displays individual essays - Navigation: All client-side navigation uses Next.js
Linkcomponent - Static Generation: Essay pages are pre-rendered at build time using
generateStaticParams()
-
Create a Markdown file in the
content/directory with a descriptive filename (use kebab-case):content/your-essay-title.mdTip: Need help generating slugs for your filenames? Check out slug-mkr - a utility tool for converting titles into URL-friendly slugs!
-
Add YAML front matter at the top of the file with metadata:
--- title: "Your Essay Title" date: "December 27, 2025" tags: ["Tag1", "Tag2", "Tag3"] ---
-
Write your essay content in Markdown format below the front matter
-
Add a disclaimer at the end of the essay (optional but recommended):
--- **Disclaimer:** [Your disclaimer text here]
-
Optional: Add a PDF to
/public/pdfs/your-essay-title.pdffor the download featureNote: Use the same slug for both the
.mdand.pdffilenames for consistency! -
Rebuild the project (if in development, the changes will hot-reload):
npm run build
Once you add an essay file, the following are automatically calculated:
- β Word Count: Counted from content (excluding disclaimer)
- β Read Time: Calculated at 200 WPM
- β Excerpt: First 160 characters of cleaned content
- β
Route:
/essays/{filename-without-extension}
This project is ready for deployment on Vercel, Netlify, or any Node.js-compatible hosting platform.
- Push your changes to GitHub
- Go to Vercel
- Import the repository
- Click "Deploy"
Vercel will automatically:
- Build the project
- Optimize images and assets
- Deploy to a global CDN
"Scroll to top" on the bottom right of the pageAdd option to preview and download pdf of the essay written on papers if availableRSS feed feature- Theme switching ?? (not sure on this one, might add it for accessibility)
- More accessibility features (text-to-speech for the essay?)
This project is open source and available under the MIT License.
- Built with Next.js
- Styled with Tailwind CSS
- Icons from lucide-react
- Markdown parsing with react-markdown
- Metadata extraction with gray-matter
- RSS Feed with rss
Happy writing! πβ¨