# Changelog

All notable changes to the template. Security-relevant changes are marked **Security**.
Format: [Keep a Changelog](https://keepachangelog.com), versions follow [SemVer](https://semver.org).

## [Unreleased]

### Added
- **Two-factor reminder (Security):** an admin user without two-factor authentication gets a screen over the admin asking to set it up,
  with a button to the profile. "Skip for now" hides it for 24 hours (`users.two_factor_prompt_skipped_at`); it comes back until two-factor
  is on. `ADMIN_TWO_FACTOR_PROMPT=false` in `.env` switches it off. Needs `php artisan migrate`.
- **Settings > Email:** the SMTP server (host, port, TLS/SSL, username, password encrypted with `APP_KEY`, sender) is set in the admin and
  stored in the database; `.env` `MAIL_*` stays in effect until "How to send" is chosen. "Send test email" shows the server's own error,
  saving restarts the queue workers, and the page lists the values per provider. Setup guide: `docs/email.md`. New setting field type `password`.

## [0.2.0] - 2026-10-08

### Added
- **Update module** (optional, on by default): System > Updates shows the installed and the latest DigiCMS version, the release notes
  of every newer release (security fixes flagged) and the installed and latest version of each module; the bell and the dashboard
  say "Updates available" / "Security update available" (permission `update.view`). The site reads `release.json` from the template's
  `main` branch daily (the scheduler, or after the first admin page of the day), never while a page loads; `UPDATE_CHECK=false` turns it off,
  `UPDATE_MANIFESTS` adds an add-ons manifest. `php artisan update:check` on the command line.
- **`php artisan update:apply`** brings a client project to a newer release: it compares the release the project is on, the new
  one and the project's own files, replaces what the project never changed, keeps what it changed (the new version goes next to it
  as `<file>.new`), never touches the public site, `.env` or `config/modules.php`, and sets `TEMPLATE_VERSION`. `--dry-run`,
  `--to=x.y.z`, `--module=Name` (one module, or install a new one). Releases are fetched with git, so a private repository works.
  It refuses on production and on a working tree with uncommitted changes.
- **Updates need a public repository:** while the template repository is private (`release.json` answers 404) the checks stay off
  quietly, without notices or errors, and switch on by themselves once it is public.
- **Module versions:** every `module.php` has a `version`. `php artisan update:manifest` writes `release.json` from `TEMPLATE_VERSION`,
  the module versions and `CHANGELOG.md` when a release is made (see docs/upgrading.md).
- **Revision module** (optional, on by default): every save of an article or page keeps a version of its content (title, excerpt, body,
  template, featured image; never the status, publish date or slug). The Revisions card in the form lists them; compare one with the
  current content line by line and restore it (saved as a new version, logged in the activity log). The newest 30 are kept (Settings > Revisions).
  **Autosave:** the form keeps the writer's unsaved changes every 30 seconds in a separate row, without changing the live content, and offers
  to put them back when the form is opened again (also for an article or page not saved yet). Another content module joins with
  `Revision::registerType()` in the Revision provider and a `<livewire:revision.panel>` in its form.
- **Notifications bell** in the admin header: a module lists what needs attention under `notices` in `module.php`
  (Comment: comments to review; Backup: the last backup failed, also for the nightly one).
- **Transfer module** (Import & export): download articles, pages, categories and tags as one JSON file and add them to another site.
  Import previews first, only adds (a taken slug is skipped), sanitizes bodies, all or nothing.

- **Media:** upload a new image straight from any picker (featured image, share image) without opening the library;
  crop an image in the library (free, 1:1, 4:3, 3:2, 16:9): the crop is saved as a new item, the original stays.
- **Dashboard:** "Needs your attention" block (comments to review, a failed backup, unsafe settings on a live site),
  draft and scheduled article counts, and "Latest articles / pages" lists. Modules add lists with `recent` in `module.php`.
  The checks of `app:security-check` now live in `App\Core\Support\SecurityChecks`.

- **Dashboard charts:** bar charts per day (articles published, comments, uploads, new users, admin changes) with a 7/30/90 day
  switch and a comparison with the previous period, and rings for the share per status (articles, pages, comments). Drawn as server-side
  SVG (no chart library, works with the strict CSP and in dark mode). Modules add charts with `charts` in `module.php`.
- **Admin footer:** every admin page ends with "DigiCMS v<version> · Built by Digitalku", linking to https://digitalku.com. `ADMIN_FOOTER=false` in `.env` hides it
  (it is the component `<x-admin.footer>`, set in the admin layout).
- **Colourful buttons:** new colour tokens `--info` (blue) and `--warning` (amber) beside the green primary and the red destructive;
  `<x-admin.button>` has `info` and `warning` variants, `secondary` is a soft green, `outline` and `ghost` pick up the green;
  row actions are coloured by what they do (edit blue, view and approve green, unapprove, spam and disable amber, delete red).
- **Selection bar:** when rows are selected the table shows a bar with the count and coloured actions (publish green, draft amber, delete red);
  on a phone it sticks to the bottom of the screen with the actions in two columns. `New ...` buttons have a plus icon.
- **Compact tables:** the actions of a row are icon buttons (edit, preview, delete, restore, approve ...) with a tooltip and a screen reader
  name, from `<x-admin.row-actions>` and `<x-admin.row-action>`; text in a table is cut to 30 characters with "..." (the whole text is the
  tooltip; a column can set `limit`, `0` for never); titles, names, dates and the actions column do not wrap; cells are tighter.
- **Modules page** (Settings > Modules): see every module, switch the optional ones on and off from the admin (core locked, dependencies checked,
  tables and permissions created when switching on, closed in production). New permission `module.manage`.
- **Page views (Analytics module):** counts views of articles and pages (one row per item per day; bots, staff, prefetch and repeat visits
  the same day are not counted, settable), shows totals in the article and page lists, a "Page views" chart and a "Most viewed" list on the dashboard.
  After updating run `php artisan migrate` and `php artisan db:seed --class=CoreSeeder`.
- **`app:dummy-data`:** fills a development site with neutral dummy content spread over the last days (`--days`, `--articles`), and
  `--clean` removes exactly what it made. Refuses to run in production without `--force`.
- **Polish:** the admin language switch is the flag of the current language with a dropdown (flags and names); the sidebar has even rows,
  a line between the content pages and the site-running pages and a guide line beside sub-pages; the dashboard draws only charts that
  have data (the others are named in one line), puts latest articles, pages and activity side by side, and keeps one width.
- **Module settings:** Settings has a page per module with settings: Media (largest upload), Articles (articles per page, feed length),
  Activity log (how long entries are kept), next to General, Contact, SEO and Comments. A settings group has a `description` and
  `sections` (cards with a title); each page has its own title and breadcrumb. Add settings to a module with `app/Modules/<Name>/settings.php`.
- **Sidebar, WordPress style:** a group is an entry with an icon that unfolds its pages (a group with one page is that page).
  Group icons come from `ModuleRegistry::GROUP_ICONS`.
- **Dashboard:** charts in rows (a bar chart beside a ring), totals in the rings, axis ticks, empty states, and quick actions
  (the "New ..." shortcuts of the command palette).
- **Sidebar:** groups fold and remember their state; new groups Users (Users, Roles), System (Activity log, Backups, Import & export)
  and Settings (one entry per settings group: General, Contact, SEO, Comments, each its own page at `/admin/settings/{group}`).
- **Admin header:** the language select became one flag per language.
- **Dashboard:** the total cards (users, media files ...) are gone; `stats` in `module.php` is no longer used.
- **Fix:** "Back up now" did nothing on a site without a queue worker. It now runs right after the response; a backup left "queued" for more than two minutes no longer blocks the next one.

## [0.1.0] - 2026-10-05

First release.

### Added
- **Foundation:** Laravel 13, Fortify auth (login, reset, 2FA), roles and permissions, activity log,
  admin layout and components (DataTable, forms, RichEditor with Tiptap, MediaPicker, SeoFields, modal, toasts).
- **Core modules:** Setting, User (users, roles, permissions), Media (WebP variants), Category (categories and tags),
  Seo (meta, JSON-LD, sitemap, robots.txt), Article (with RSS), Page.
- **Add-ons** (kept outside the template in `digi-template-addons`, copied in per client): Menu builder, Redirect manager
  (automatic redirect on slug change), Contact (form and email notifications), Banner, Gallery, Testimonial, Faq,
  Newsletter (double opt-in).
- **Frontend:** `setting()`, `module_enabled()` and add-on helpers, `<x-seo>`, breadcrumb and prose components,
  minimal starter layout and a "Welcome to DigiCMS" home page.
- **Tooling:** `app:install`, `make:module`, `module:list`, `module:remove`, `app:clean-demo`, `seo:sitemap`; the browser
  setup wizard at `/setup`; neutral demo seeder.
- **Admin look:** shadcn-admin design rebuilt in Blade + Tailwind (tokens, light and dark mode, grouped collapsible sidebar,
  module dashboard cards).
- **Multi-language:** English and Indonesian. Admin and interface translated (`lang/id.json`, per-module `Resources/lang`), language switchers for
  the admin and the public site (cookies), content in several languages (one row per language, `Translatable`) for articles, pages and
  categories with a Language card, `hreflang` links and per-language sitemap entries, translatable settings, default language in the
  setup wizard (which is itself translated, with a language switcher) and `app:install --locale`.
- **Comments:** a Comment module (requires Article): visitor comments with moderation (pending, approved, spam), one level of replies,
  honeypot, signed time token and rate limit, links limit, close after N days, admin table with bulk actions and activity log,
  dashboard card, settings tab and Indonesian strings of its own.
- **Site settings:** Title, Tagline, Favicon (Media library), Address, Time zone (searchable, with UTC offsets), Date format and Time
  format. The database keeps UTC; dates are shown and typed in the site's zone (the old `APP_TIMEZONE` write by the setup wizard had
  no effect and is gone). Modules can add settings with their own `settings.php`.
- **Admin sidebar:** Content (Articles, Categories, Tags, Pages), Media and Engagement groups.
- **Admin:** command palette (Ctrl/Cmd+K); profile page (name, email, picture, password, two-factor); users can be invited by email,
  disabled and enabled (the last active super admin is protected); activity log page; backups page (run, download, delete);
  media folders, in-place file replacement and a "used in" list.
- **Public site:** the article list, article, page, sign-in and error pages (401, 403, 404, 419, 429, 500, 503) share the style of the
  welcome page; header with the language switcher and a footer.
- **Security:** headers and a Content-Security-Policy (strict on the public site, Alpine-friendly in the admin), HSTS, rate limits for password
  resets and the profile password prompt, a ceiling per visitor, `php artisan app:security-check`, an automated check that every admin
  page needs a permission. Docs: `docs/security.md`.
- **Performance:** frontend cache (tagged or versioned) with immediate invalidation, query-count tests for every page, queued image conversions.
- **Comments, more:** email for comments to review, per article and page switch (pages can take comments), counts in the article list,
  Cloudflare Turnstile.
- **Multi-language, more:** tags per language, a feed per language (`/feed/id.xml`), `hreflang` alternates in the sitemap.
- **Backup:** `spatie/laravel-backup` configured for database + uploaded media, opt-in nightly schedule
  (`BACKUP_SCHEDULE`), optional zip encryption, failure-only mail.
- Documentation in `docs/`, Pest test suite.

### Security
- Server-side HTML sanitizing for all rich text; policies and permission checks on every admin action.
- Honeypot, signed time token and rate limits on public forms; optional Cloudflare Turnstile.
- Signed confirm/unsubscribe links that only change data on POST; IP addresses anonymized; CSV-injection guard on exports.
- Setup wizard: lock file, closed in production, atomic `.env` writes, rate limited.
- Backups exclude `.env` and code and can be encrypted.
