b0ca76e8dc1f5c01201274b07a65838c0692f033
- Add custom publish time field to article create/edit forms - Support datetime-local input for manual time setting - Auto-set on first publish if left blank - Works for both admin and user article forms - Display last updated time on article detail page - Show both published time and last updated time - Auto-maintained by GORM on each update - Format: YYYY-MM-DD HH:MM - Add i18n support for new fields - article_published_at: Published Time / 发布时间 - article_published_at_hint: Leave blank to auto-set on publish / 留空则在发布时自动设置 - article_last_updated: Last Updated / 最后更新 - Update handlers and templates - handlers/article.go: Add parsePublishedAt/formatPublishedAt functions - handlers/home.go: Add formatUpdateTime function - handlers/my_articles.go: Support custom publish time in user articles - templates: Add datetime-local inputs and time display Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Go Blog
A simple, fast blog engine built with Go, Gin, and Tailwind CSS. Supports SQLite and MySQL, with automatic first-run setup.
Features
- Multi-language — 中文 / English, auto-detected or manually switched
- OS-aware config — Linux
/etc/blog_go/, Windows./win/etc/blog_go/ - First-run setup — auto-creates config, database, and admin user
- Avatar + Profile — upload avatar, edit personal info, change password
- Role system — admin sees management panel; authors see profile only
- Responsive UI — Tailwind CSS, works on desktop and mobile
Tech Stack
| Layer | Library |
|---|---|
| Router | gin |
| ORM | gorm |
| SQLite | glebarez/sqlite (pure Go, no CGO) |
| Sessions | gin-contrib/sessions |
| Config | gopkg.in/yaml.v3 |
| Passwords | golang.org/x/crypto |
| CSS | Tailwind CSS (CDN) |
Quick Start
go run .
Open http://localhost:8080 and log in with admin / admin.
Configuration
On first run, a config file is created automatically:
| Platform | Config Path | Storage Path |
|---|---|---|
| Linux | /etc/blog_go/config.yaml |
/srv/blog_go/ |
| Windows | ./win/etc/blog_go/config.yaml |
./win/srv/blog_go/ |
# config.yaml
database:
type: sqlite # sqlite (default) or mysql
dsn: "" # MySQL DSN, ignored for sqlite
port: "8080" # web server port
path: ./win/srv/blog_go # storage path (db, uploads)
secret: <auto-generated> # session encryption key
MySQL
Edit config.yaml:
database:
type: mysql
dsn: user:password@tcp(127.0.0.1:3306)/blog_go?charset=utf8mb4&parseTime=True&loc=Local
port: "8080"
Create the database first:
CREATE DATABASE blog_go CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
Project Structure
go_blog/
├── main.go # Entry point, routes, middleware wiring
├── config/
│ └── config.go # OS-aware config load / auto-create
├── models/
│ ├── user.go # User model + bcrypt
│ └── db.go # GORM init, migration, seed
├── middleware/
│ └── auth.go # Auth guard, language detection
├── handlers/
│ ├── helpers.go # DefaultData + getTr utilities
│ ├── home.go # GET /
│ ├── auth.go # GET/POST /login, POST /logout
│ ├── admin.go # GET /admin (protected)
│ └── profile.go # GET/POST /profile (protected)
├── i18n/
│ └── i18n.go # EN/ZH translation maps + Accept-Language
├── templates/
│ ├── layouts/base.html # Header (nav + avatar dropdown) + footer
│ ├── pages/
│ │ ├── home.html # Public home page
│ │ ├── login.html # Login form
│ │ └── profile.html # Edit profile page
│ └── admin/
│ └── dashboard.html # Admin dashboard
└── win/ # Auto-created runtime data (Windows)
├── etc/blog_go/
│ └── config.yaml
└── srv/blog_go/
├── blog.db
└── avatars/
Routes
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | / |
No | Home page |
| GET | /login |
No | Login form |
| POST | /login |
No | Submit login |
| POST | /logout |
No | Clear session |
| GET | /profile |
Yes | Edit profile |
| POST | /profile |
Yes | Save profile |
| GET | /admin |
Yes | Admin dashboard (admin only) |
| GET | /uploads/* |
No | Static files (avatars, etc.) |
User Roles
| Role | Profile | Admin Dashboard |
|---|---|---|
admin |
✓ | ✓ |
author |
✓ | ✗ |
License
MIT
Languages
Go
53.3%
HTML
45.9%
Shell
0.8%