https://github.com/amirardalan/amirardalan.com
A Markdown blog and CMS written in TypeScript using Next.js App Router. Publish and edit blog posts without a build using On-demand Revalidation.
https://github.com/amirardalan/amirardalan.com
authjs clsx dark-mode google-fonts nextjs ogimage-nextjs react supabase tailwindcss upstash-redis zustand
Last synced: about 1 month ago
JSON representation
A Markdown blog and CMS written in TypeScript using Next.js App Router. Publish and edit blog posts without a build using On-demand Revalidation.
- Host: GitHub
- URL: https://github.com/amirardalan/amirardalan.com
- Owner: amirardalan
- License: other
- Created: 2021-04-29T06:37:15.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2025-08-25T20:56:32.000Z (about 2 months ago)
- Last Synced: 2025-08-25T22:30:10.908Z (about 2 months ago)
- Topics: authjs, clsx, dark-mode, google-fonts, nextjs, ogimage-nextjs, react, supabase, tailwindcss, upstash-redis, zustand
- Language: TypeScript
- Homepage: https://amir.sh
- Size: 29.8 MB
- Stars: 65
- Watchers: 2
- Forks: 9
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE.txt
- Security: SECURITY.md
Awesome Lists containing this project
README
# amirardalan.com
Amir Ardalan's personal website built with [Startup](https://github.com/amirardalan/startup). This is a Markdown Blog and CMS written in TypeScript leveraging React Server Components. Create, edit, and manage blog posts and categories inside a custom CMS. Update static posts without a build leveraging the power of on-demand revalidation.
### Stack
- TypeScript
- [Next.js](https://nextjs.org/docs/getting-started) App Router
- [Auth.js](https://authjs.dev/) auth
- [Tailwind CSS](https://tailwindcss.com/docs/installation) styles
- [Supabase](https://supabase.com/docs/guides/database/overview) Postgres database
- [Drizzle ORM](https://orm.drizzle.team/) for Postgres
- [MDX](https://mdxjs.com/) Markdown
- [Sugar High](https://github.com/huozhi/sugar-high) syntax highlighting
- [Zustand](https://github.com/pmndrs/zustand) state management
- [CLSX](https://github.com/lukeed/clsx) `className` logic### Features
- Custom CMS (Publish, Edit, Manage Drafts and Categories)
- Light/Dark/System Theme toggle
- Dynamic (theme-based) favicon
- Dynamic Metadata and Page Titles
- Route-based active navigation highlighting
- Dynamic footer copyright date
- Custom Tooltip, Modal, and Toast components
- Next.js [optimized fonts](https://nextjs.org/learn/dashboard-app/optimizing-fonts-images)
- [OG Image](https://vercel.com/docs/functions/og-image-generation) metadata
- Dynamically-generated [sitemap.xml](https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap)
- Custom [Cloudinary](https://cloudinary.com/) CMS Media Gallery
- [PostHog](https://posthog.com/) analytics and blog post view count
- Blog likes with [Upstash](https://upstash.com/) Redis
- Accessibility, perfomance, and SEO best-practices
- 100% Lighthouse score## Getting Started
### Setup
```bash
npm install
```Then, set up your [GitHub oAuth App](https://authjs.dev/getting-started/providers/github?framework=next-js) and add your GitHub Client ID and Secret in a `.env.local` file:
```
// .env.local# Set for each environment
NEXT_PUBLIC_URL="http://localhost:3000"# Set your timezone
NEXT_PUBLIC_TIMEZONE="America/Los_Angeles"# Resume Link (redirect in next.config.ts)
RESUME_URL=# Auth.js
AUTH_SECRET=
AUTH_TRUST_HOST="NEXT_PUBLIC_URL"# GitHub OAuth
AUTH_GITHUB_ID=
AUTH_GITHUB_SECRET=# Email verification (CMS Users)
ALLOWED_EMAILS=
ALLOWED_EMAIL_DOMAINS=# Supabase (CMS Database)
DB_URL=
DB_API_KEY=# Cloudinary (CMS Media Gallery)
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME=
CLOUDINARY_URL=
CLOUDINARY_API_KEY=
CLOUDINARY_API_SECRET=# PostHog (Analytics)
NEXT_PUBLIC_POSTHOG_KEY=
NEXT_PUBLIC_POSTHOG_HOST=
POSTHOG_API_KEY=
POSTHOG_PROJECT_ID=# Upstash/Redis (Blog Likes)
ENABLE_DEV_CACHE="true"
KV_URL=
KV_REST_API_READ_ONLY_TOKEN=
REDIS_URL=
KV_REST_API_TOKEN=
KV_REST_API_URL=
```And finally, generate a Next Auth secret which will automatically overwrite the placeholder in the `.env.local` file:
```bash
npx auth secret
```### Database
```bash
npx drizzle-kit push
```> [!NOTE]
> This command will create the database tables and columns based on the schema defined in `./src/db/schema.ts` file.### Run
```bash
npm run dev
```### Preview
To test On-demand Revalidation of blog posts and to ensure the app is in good shape to run on production it is recommended to compile a preview build.
```bash
npm run preview
```> [!NOTE]
> This script will format the project using Prettier, check linting, and then compile a preview build.### Drizzle Studio
To interact with the postgres database locally:
```bash
npx drizzle-kit studio
```> [!NOTE]
> If using Brave browser you must turn Brave Shield off for `https://local.drizzle.studio/`### Markdown Features
#### Images
Blog posts are written in Markdown. Markdown images will utilize the Next Image component for optimized loading. The markdown image can be passed a priority prop:
```markdown

```Or you can use an image wrapped in a custom MDX `` component to add a caption (this also works with an optional priority prop for images above the fold):
```markdown
```
#### Code
Highlight individual lines or blocks of code (line 2 and lines 3-5):
````
```typescript{2,3-5}
````