- Add TotalPublishedPosts cache key for reusing total count across pages
- list_published_posts now checks total cache before running COUNT(*)
- Add note to get_posts_by_tag about total = posts.len() assumption
- Remove unused invalidate_total_published_posts helper
- Move posts.rs (891 lines) to posts/ with 11 submodules
- Extract shared tag sync logic into helpers::sync_tags
- Extract tag cleaning into helpers::clean_tags
- All external import paths unchanged via mod.rs re-exports
- Zero behavioral changes, pure structural refactor
Replace scattered ServerFnError::new("...") inline calls and utils.rs
helper functions with a single AppError enum that provides:
- Automatic tracing::error logging for system errors
- Safe generic messages to frontend (no SQL/connection detail leaks)
- Typed error variants (Unauthorized, Forbidden, NotFound, etc.)
- 5 unit tests for message passthrough and detail hiding
Removes src/api/utils.rs entirely; all error creation now goes through
src/api/error.rs.
- Create src/cache.rs with CacheKey enum, moka cache instances,
getter/setter functions, and invalidation helpers.
- TTLs: post list 60s, tags 300s, single post 600s, stats 60s,
tag posts 120s.
- Register mod cache in src/main.rs.
- All cache internals gated behind #[cfg(feature = "server")]
- Replace image crate's WebP with zenwebp for better quality/speed
- Add webp.rs module with configurable quality and method
- Update .env.example with WEBP_QUALITY and WEBP_METHOD
- Add WebP decode support in image serving pipeline
- Add detailed timing logs for WebP conversion
- Change opt-level from 'z' to 3 for better runtime performance
- Use thin LTO for faster compilation with similar results
- Remove panic=abort and strip=true to preserve server debuggability
- Add --debug-symbols=false to dx build for smaller WASM
- Add build-linux target for static musl binary
- Remove tower_governor (unused, governor used directly instead)
- Remove tower-http fs feature (only trace is used)
- Remove 4 unused web-sys features: HtmlDocument, HtmlScriptElement, HtmlButtonElement, HtmlElement
- Slim tokio features from full to rt-multi-thread,macros,fs,time,sync
ammonia's default url_schemes whitelist excludes 'data', causing
data:image/* URLs to be stripped from img src attributes. Add 'data'
to allowed schemes. Also skip data: URIs in JS thumbnail logic.
- Separate /uploads and /api/upload routes from Dioxus app to avoid
IncrementalRenderer intercepting non-page requests
- Remove broken SmartIpKeyExtractor-based general_limit() that failed
under Dioxus dev server proxy (Unable To Extract Key)
- Move rate limiting into handlers using governor::RateLimiter directly
- Add IMAGE_LIMITER for /uploads/* serving
- Make all rate limits configurable via environment variables
- Add rate limit config to .env.example with sensible defaults
* feat(db): add pg_trgm search index on posts
* feat(api): use pg_trgm similarity search for posts
* fix(api): use ILIKE + word_similarity instead of % operator for search
- Remove unused tags.rs and related re-exports
- Convert strict_limit/upload_limit from Layer to manual check functions
- Add IP-based rate limiting checks to Register, Login, and upload_image
- Keep general_limit as global middleware for all other routes