This commit is contained in:
284
README.md
284
README.md
@@ -1,66 +1,107 @@
|
|||||||
# Markdown Blog
|
# Markdown Blog
|
||||||
|
|
||||||
A modern, cross-platform blog system built with **Next.js**, **Markdown**, and **Electron**. Write posts in Markdown, manage content visually, and deploy to web or desktop.
|
A modern, feature-rich blog system built with **Next.js 14**, **TypeScript**, and **Markdown**. Features include a visual admin dashboard, Electron desktop app, Docker deployment, and secure content management.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🚀 Features
|
## 🚀 Key Features
|
||||||
|
|
||||||
- Write and organize posts in Markdown
|
- **📝 Markdown Blog Posts**: Write posts with frontmatter metadata (title, date, tags, summary)
|
||||||
- Visual admin dashboard
|
- **🎨 Visual Admin Dashboard**: Manage posts, folders, and content structure through a web interface
|
||||||
- Responsive UI (Tailwind CSS)
|
- **📌 Pin Posts**: Pin important posts to the top of your blog
|
||||||
- Electron desktop app
|
- **📁 Folder Organization**: Organize posts in nested folders
|
||||||
- Dockerized deployment with persistent storage
|
- **🖥️ Desktop App**: Electron-based desktop application
|
||||||
- Secure admin password (bcrypt)
|
- **🐳 Docker Support**: Containerized deployment with persistent storage
|
||||||
|
- **🔒 Secure Admin**: Password-protected admin interface with bcrypt hashing
|
||||||
|
- **📱 Responsive Design**: Mobile-friendly UI with Tailwind CSS
|
||||||
|
- **🎯 Content Management**: Drag & drop file uploads, post editing, and deletion
|
||||||
|
- **📦 Export Functionality**: Export all posts as tar.gz archive (Docker only)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🛠️ Technologies
|
## 🛠️ Technology Stack
|
||||||
|
|
||||||
- Next.js 14
|
- **Frontend**: Next.js 14, React 18, TypeScript
|
||||||
- TypeScript
|
- **Styling**: Tailwind CSS, @tailwindcss/typography
|
||||||
- Tailwind CSS
|
- **Markdown**: marked, gray-matter, highlight.js
|
||||||
- Electron
|
- **Desktop**: Electron
|
||||||
- Docker
|
- **Security**: bcrypt, DOMPurify
|
||||||
|
- **Deployment**: Docker, PM2
|
||||||
|
- **Development**: ESLint, PostCSS, Autoprefixer
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📦 Project Structure
|
## 📁 Project Structure
|
||||||
|
|
||||||
```
|
```
|
||||||
markdownblog/
|
markdownblog/
|
||||||
├── posts/ # Markdown blog posts
|
├── src/
|
||||||
├── src/ # Next.js app code
|
│ ├── app/
|
||||||
├── electron/ # Desktop app code
|
│ │ ├── admin/ # Admin dashboard pages
|
||||||
├── public/ # Static assets
|
│ │ │ ├── manage/ # Content management interface
|
||||||
├── Dockerfile # Docker configuration
|
│ │ │ └── page.tsx # Main admin dashboard
|
||||||
├── .dockerignore # Docker ignore rules
|
│ │ ├── api/ # API routes
|
||||||
└── manage_container.sh # Docker management script
|
│ │ │ ├── admin/ # Admin API endpoints
|
||||||
|
│ │ │ │ ├── delete/ # Delete posts/folders
|
||||||
|
│ │ │ │ ├── docker/ # Docker detection
|
||||||
|
│ │ │ │ ├── export/ # Export functionality
|
||||||
|
│ │ │ │ ├── folders/ # Folder management
|
||||||
|
│ │ │ │ ├── password/ # Password management
|
||||||
|
│ │ │ │ ├── posts/ # Post CRUD operations
|
||||||
|
│ │ │ │ └── upload/ # File upload handling
|
||||||
|
│ │ │ └── posts/ # Public post API
|
||||||
|
│ │ ├── posts/ # Blog post pages
|
||||||
|
│ │ │ └── [...slug]/ # Dynamic post routing
|
||||||
|
│ │ ├── globals.css # Global styles
|
||||||
|
│ │ ├── layout.tsx # Root layout
|
||||||
|
│ │ └── page.tsx # Homepage
|
||||||
|
│ └── lib/
|
||||||
|
│ ├── markdown.ts # Markdown processing utilities
|
||||||
|
│ └── postsDirectory.ts # Post directory management
|
||||||
|
├── posts/ # Markdown blog posts
|
||||||
|
│ ├── pinned.json # Pinned posts configuration
|
||||||
|
│ ├── welcome.md # Welcome post
|
||||||
|
│ └── mdtest.md # Test post
|
||||||
|
├── public/ # Static assets (favicons, etc.)
|
||||||
|
├── electron/ # Desktop app configuration
|
||||||
|
│ └── main.js # Electron main process
|
||||||
|
├── Dockerfile # Docker container configuration
|
||||||
|
├── docker.sh # Docker deployment script
|
||||||
|
├── entrypoint.sh # Container entrypoint
|
||||||
|
└── package.json # Dependencies and scripts
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## ⚡ Getting Started
|
## ⚡ Quick Start
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- Node.js 18+
|
- **Node.js 18+**
|
||||||
- npm
|
- **npm** or **yarn**
|
||||||
- Docker (for containerized deployment)
|
- **Docker** (for containerized deployment)
|
||||||
|
|
||||||
---
|
### Local Development
|
||||||
|
|
||||||
## 🖥️ Local Development
|
1. **Clone and install**:
|
||||||
|
```bash
|
||||||
|
git clone <repository-url>
|
||||||
|
cd markdownblog
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
```bash
|
2. **Start development server**:
|
||||||
git clone <repo-url>
|
```bash
|
||||||
cd markdownblog
|
npm run dev
|
||||||
npm install
|
```
|
||||||
npm run dev
|
Visit [http://localhost:3000](http://localhost:3000)
|
||||||
```
|
|
||||||
- Visit [http://localhost:3000](http://localhost:3000) in your browser.
|
|
||||||
|
|
||||||
### Build for Production (Local)
|
3. **Desktop app development**:
|
||||||
|
```bash
|
||||||
|
npm run electron-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
### Production Build
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build
|
npm run build
|
||||||
@@ -71,53 +112,180 @@ npm start
|
|||||||
|
|
||||||
## 🐳 Docker Deployment
|
## 🐳 Docker Deployment
|
||||||
|
|
||||||
### Build the Docker Image
|
### Quick Deployment
|
||||||
|
|
||||||
|
Use the provided script for easy deployment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
docker build -t markdownblog .
|
chmod +x docker.sh
|
||||||
|
./docker.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
### Run the Container with Persistent Storage
|
This script will:
|
||||||
|
- Build the Docker image
|
||||||
|
- Create a persistent volume for posts
|
||||||
|
- Run the container on port 8080
|
||||||
|
- Copy built-in posts to the volume
|
||||||
|
|
||||||
```bash
|
### Manual Docker Commands
|
||||||
docker run -p 8080:3000 -v markdownblog-posts:/app/docker markdownblog
|
|
||||||
```
|
|
||||||
- The app will be available at [http://localhost:8080](http://localhost:8080)
|
|
||||||
- All posts are stored persistently in the Docker volume `markdownblog-posts` (mapped to `/app/docker` in the container).
|
|
||||||
|
|
||||||
#### Using a Host Directory for Posts
|
1. **Build the image**:
|
||||||
|
```bash
|
||||||
|
docker build -t markdownblog .
|
||||||
|
```
|
||||||
|
|
||||||
```bash
|
2. **Run with persistent storage**:
|
||||||
docker run -p 8080:3000 -v /absolute/path/to/posts:/app/docker markdownblog
|
```bash
|
||||||
```
|
docker run -d \
|
||||||
|
--name markdownblog \
|
||||||
|
-p 8080:3000 \
|
||||||
|
-v markdownblog-posts:/app/docker \
|
||||||
|
markdownblog
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Using host directory**:
|
||||||
|
```bash
|
||||||
|
docker run -d \
|
||||||
|
--name markdownblog \
|
||||||
|
-p 8080:3000 \
|
||||||
|
-v /path/to/your/posts:/app/docker \
|
||||||
|
markdownblog
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Features
|
||||||
|
|
||||||
|
- **Persistent Storage**: Posts are stored in Docker volumes
|
||||||
|
- **Export Functionality**: Export all posts as tar.gz (Docker only)
|
||||||
|
- **Auto-restart**: Container automatically restarts on failure
|
||||||
|
- **Built-in Posts**: Welcome and test posts included
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📝 Writing Posts
|
## 📝 Writing Blog Posts
|
||||||
|
|
||||||
- Add Markdown files to the `posts/` directory (or the mounted volume).
|
### Post Structure
|
||||||
- Each post should have frontmatter:
|
|
||||||
|
Create Markdown files in the `posts/` directory with frontmatter:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
---
|
---
|
||||||
title: "Your Post Title"
|
title: "Your Post Title"
|
||||||
date: "YYYY-MM-DD"
|
date: "2024-01-15"
|
||||||
tags: ["tag1", "tag2"]
|
tags: ["technology", "programming", "web"]
|
||||||
summary: "A brief summary of your post"
|
summary: "A brief description of your post content"
|
||||||
---
|
---
|
||||||
|
|
||||||
Your post content here...
|
Your post content here...
|
||||||
|
|
||||||
|
## Headers
|
||||||
|
|
||||||
|
Regular Markdown syntax is supported.
|
||||||
|
|
||||||
|
### Code Blocks
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
console.log("Hello, World!");
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Lists
|
||||||
|
|
||||||
|
- Item 1
|
||||||
|
- Item 2
|
||||||
|
- Nested item
|
||||||
|
```
|
||||||
|
|
||||||
|
### Post Organization
|
||||||
|
|
||||||
|
- **Root Level**: Posts directly in `posts/` folder
|
||||||
|
- **Folders**: Create subdirectories for organization
|
||||||
|
- **Nested Structure**: Support for unlimited nesting levels
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 🔒 Admin Password Security
|
## 🔐 Admin Dashboard
|
||||||
|
|
||||||
- Admin password is securely hashed with bcrypt and stored in `posts/admin.json`.
|
### Access
|
||||||
- Never commit your `posts/admin.json` file.
|
|
||||||
|
- **URL**: `/admin`
|
||||||
|
- **Default Username**: `admin`
|
||||||
|
- **Password**: Set via API or environment variable
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- **📝 Create Posts**: Rich text editor with live Markdown preview
|
||||||
|
- **📁 Manage Folders**: Create and organize content structure
|
||||||
|
- **📌 Pin Posts**: Pin important posts to the top
|
||||||
|
- **🔄 Edit Posts**: In-place editing with frontmatter support
|
||||||
|
- **🗑️ Delete Content**: Remove posts and folders
|
||||||
|
- **📤 Upload Files**: Drag & drop Markdown files
|
||||||
|
- **🔐 Change Password**: Secure password management
|
||||||
|
- **📦 Export Posts**: Download all posts as archive (Docker only)
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- **Password Hashing**: bcrypt with salt
|
||||||
|
- **Session Management**: Local storage-based authentication
|
||||||
|
- **Input Sanitization**: DOMPurify for XSS protection
|
||||||
|
- **File Validation**: Markdown file type checking
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🎨 Customization
|
||||||
|
|
||||||
|
### Styling
|
||||||
|
|
||||||
|
- **Tailwind CSS**: Utility-first CSS framework
|
||||||
|
- **Typography**: @tailwindcss/typography for content styling
|
||||||
|
- **Syntax Highlighting**: highlight.js with GitHub theme
|
||||||
|
- **Responsive Design**: Mobile-first approach
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
- **Next.js Config**: `next.config.js`
|
||||||
|
- **Tailwind Config**: `tailwind.config.js`
|
||||||
|
- **TypeScript Config**: `tsconfig.json`
|
||||||
|
- **PostCSS Config**: `postcss.config.js`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🔧 Development Scripts
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev # Start development server
|
||||||
|
npm run build # Build for production
|
||||||
|
npm run start # Start production server
|
||||||
|
npm run lint # Run ESLint
|
||||||
|
npm run electron # Start Electron app
|
||||||
|
npm run electron-dev # Start Electron with dev server
|
||||||
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 📄 License
|
## 📄 License
|
||||||
|
|
||||||
MIT
|
MIT License - see [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🤝 Contributing
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create a feature branch
|
||||||
|
3. Make your changes
|
||||||
|
4. Test thoroughly
|
||||||
|
5. Submit a pull request
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 🐛 Troubleshooting
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
- **Port conflicts**: Change port in `docker.sh` or Docker run command
|
||||||
|
- **Permission errors**: Ensure `docker.sh` is executable (`chmod +x docker.sh`)
|
||||||
|
- **Volume issues**: Check Docker volume exists and has proper permissions
|
||||||
|
- **Build failures**: Ensure Node.js version is 18+ and all dependencies are installed
|
||||||
|
|
||||||
|
### Support
|
||||||
|
|
||||||
|
For issues and questions, please check the project structure and API documentation in the codebase.
|
||||||
@@ -584,31 +584,11 @@ export default function AdminPage() {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<button
|
<button
|
||||||
onClick={() => {
|
onClick={handleExportTarball}
|
||||||
if (isDocker) {
|
|
||||||
handleExportTarball();
|
|
||||||
} else {
|
|
||||||
// Custom popup for local server message
|
|
||||||
const dockerSupportPopup = document.createElement('div');
|
|
||||||
dockerSupportPopup.innerHTML = '⚠️ Exporting from local server isn\'t supported, please pull from the server\'s Filesystem';
|
|
||||||
dockerSupportPopup.style.position = 'fixed';
|
|
||||||
dockerSupportPopup.style.top = '50%';
|
|
||||||
dockerSupportPopup.style.left = '50%';
|
|
||||||
dockerSupportPopup.style.transform = 'translate(-50%, -50%)';
|
|
||||||
dockerSupportPopup.style.backgroundColor = 'white';
|
|
||||||
dockerSupportPopup.style.padding = '20px';
|
|
||||||
dockerSupportPopup.style.borderRadius = '5px';
|
|
||||||
dockerSupportPopup.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.2)';
|
|
||||||
dockerSupportPopup.style.zIndex = '1000';
|
|
||||||
document.body.appendChild(dockerSupportPopup);
|
|
||||||
setTimeout(() => {
|
|
||||||
document.body.removeChild(dockerSupportPopup);
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
className="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700"
|
className="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700"
|
||||||
|
title="Export Docker Posts"
|
||||||
>
|
>
|
||||||
Export Docker Posts
|
Export Posts
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user