# LaraLog Features Modern blog migrated from SaBlog-X: Filament admin, themes, plugins, sablog import, S3 attachments, Workerman AI queue. ## Local development - Site: http://laralog.test - Admin: http://laralog.test/admin - Account: `admin@laralog.test` / `password` - Database: MySQL `laralog` (Herd, root / empty password) - Remote: `git@gitea.neatcn.com:gouki/laralog.git` See `README.md` and `docs/` for install, import, plugins, and themes. ## Post editor layout - Create/edit post uses **left 2 : right 1** on PC at every breakpoint (not only `lg`). - Left: title, full-width slug, category + format + status on one row (single-choice buttons), cover thumbnail (not full-width), then a tall body editor. - Right group 1: published at, sticky level (none / light / strong / headline), comment status, excerpt, keywords. - Right group 2: read password; membership plugin adds members-only + price here. - Plugins must inject via `PostForm::appendToSidebar()` / `appendToAccessSection()` so they do not break the 2:1 grid. ## Sticky levels - `sticky_level`: 0 none, 1 light, 2 strong, 3 headline. Headline always stays first on home, category, tag, and search lists. - Saving a post keeps `is_sticky` in sync (`true` when level > 0) so older themes still work. - List badges show the Chinese label, not a generic “sticky”. ## Post preview - Edit page and post table have **预览**, opening `/show-{id}.shtml` in a new tab. - Filament v5 actions are `Filament\Actions\Action`. The comments relation manager on the edit page must boot in tests, because a stale `Tables\Actions\Action` import only fails when that Livewire table renders. - Guests still get 404 for drafts. Admin and editor can open unpublished posts and see a preview banner. ## Admin chrome - Top-right badge shows the current app environment (`local` / `prod` / others). - Top-right **网站** opens the public site in a new tab; **写文章** jumps to `/admin/posts/create`. - Sidebar **管理** includes **页面缓存** (view URLs, hit rate, flush) and **语言** (current locale + available packs). Article translations are not built yet; the language page says so. - Sidebar nav is compacted (Filament default `gap-y-7` / `py-8` is too tall for this site). ## Hello World plugin - Enabling a plugin now runs that plugin's `database/migrations` automatically. - Plugin boot / hook failures are isolated so one plugin cannot take down the whole admin. - `/hello-world` stays available even if `hello_world_logs` is missing. ## Frontend feeds - Header/footer **RSS / Sitemap / llms.txt** open in a new tab (`target="_blank"`). - `/llms.txt` is a core route (not a static file). Each request lists current published public posts so new articles show up immediately. - Full text for agents: `/posts/{slug}.md`. Password / members-only posts are omitted. - These machine-readable paths are excluded from page cache. ## Homepage list / full mode - Same switch as old SaBlog: **浏览模式: 标准 | 列表**. - `list` = title + excerpt cards. `full` = full rendered body on the home / category / tag / search lists. - Query `?view=list` or `?view=full` wins, then cookie `ll_home_view`, then setting `home_view_mode`. - Page cache key includes the view mode so the two layouts are not mixed. ## Pagination and imported HTML - Public pagers use `onEachSide(1)` plus a compact `6 / 316` chip (old SaBlog `.p_bar` look), and the main column is CSS grid `minmax(0, 1fr)` so page chips stay in the content column. - `SablogHtmlNormalizer` strips leftover ` `, turns SyntaxHighlighter `codeText` / `dp-*` lists into `
`, and wraps stacked docker/shell `
` lines. - Render path always normalizes, so already-imported posts look right without rewriting the database. Persist with `php artisan sablog:fix-content --all`. - Code blocks wrap / scroll inside the column instead of stretching the page. ## Theme ads / inject - All list and post views include `content_top` / `content_bottom` (and post body) stacks. Saving **主题注入** flushes page cache. - Theme variables (old stylevars) render automatically: `ad_header` → header, leftover HTML vars such as `huangjinlian` → footer. - `sablog:import` now copies the old `stylevars` table into `theme_vars_{theme}`. - Do not add a third half-finished skin. Tighten `sablog` to match the old site; a new theme is a later, complete job. ## Media library (xpier) - Package: `xpier/filament-media-library` (admin Media Library + MediaPicker). - **Markdown body must store `![alt](media:ID)` or `[name](media:ID)`**, never a CDN/object-storage URL. HTML uses `[media=ID]`. - Insert flow: pick a file → **Insert into body**. Cover uses `cover_media_id`. - Legacy sablog `[attach=ID]` / `{{attach:ID}}` still render from Spatie media. - Details: `docs/media.md`.