DL CMS.
A single-site publishing workspace: English admin, native PHP, and no frontend build.
Start publishing
Open /admin for the workspace and /site for the public journal. Posts, pages, categories, tags, images, comments, roles and site settings are managed in one place.
php dl cms:prepareSecure first installation
On a fresh deployment, cms:prepare creates tables and a private one-time key in storage/cms-setup.key. Visit /admin/setup, enter that key and create the owner account. Setup closes after ownership is claimed. Local development access is stored privately in storage/cms-local-access.txt and is excluded from release archives.
Write, recover and publish
Use DL WYSIWYG for headings, bold/italic/underline, lists, alignment, colors, links, media-library images and editable tables. Undo/redo, word count and focused writing are included. Existing blocks remain compatible; raw HTML and scripts are not accepted. Autosave keeps a separate recovery copy after 15 seconds of typing inactivity; click Save to update content. The latest 20 prior versions can be restored as drafts. Scheduled publishing uses UTC and query-time eligibility, without a worker.
People and permissions
Administrators manage the site; editors manage all content; authors publish their own posts; contributors submit drafts; subscribers manage their profile. Write requests require CSRF and server-side permission checks. Password changes revoke existing sessions.
Media and comments
JPEG, PNG, WebP and GIF images up to 5 MB are validated and stored privately, then served at public media URLs. Add alt text and captions. Comments require site-wide and per-post opt-in and are always held for moderation.
Themes and plugins
Appearance provides a theme gallery with preview, ZIP upload and activation. Menus is a separate workspace for named menus, ordering, submenus and header/footer locations. Settings only controls site identity and comments. Reviewed local plugins remain managed separately.
AI suggestions
Configure AI_BASE_URL, AI_MODEL and AI_API_KEY privately. Writers may request a title, excerpt or outline. Suggestions are not automatically applied or published. The CMS limits calls to 3 per minute and 30 per 24 hours per user. Live provider calls have not been tested.
Own your data
Tools exports DL JSON content. Imports become private drafts with new slugs. This is not a full backup and does not include users, media files, taxonomy or settings. Back up the database and private storage together. WordPress WXR import is not available.
Hosting and SEO
Use PHP 8.2+, PDO SQLite/MySQL (including MariaDB), fileinfo for images and cURL for AI. Configure CMS_DB_DSN and private credentials; SQLite is the default. Isolated lifecycle tests also pass on MySQL 8.4 and MariaDB 11.4; both use mysql: DSNs and utf8mb4/InnoDB. Only public/ is web-facing. /cms-sitemap.xml contains eligible public content when indexing is enabled. RSS is at /feed.xml; the read-only public API is /api/cms/posts.
Alpha scope
This is a working core CMS, not full WordPress parity. Advanced block formatting, full-site editing, image transforms, nested menus, custom-field UI, email delivery, automatic updates and WordPress ecosystem compatibility are not implemented. Multisite is out of scope. Full operational guidance and feature boundaries are in docs/cms.md.
Traffic analytics & SEO health
Open Analytics & SEO from the CMS sidebar. It records anonymous public page views for /site, /blog/* and /page/*, with 7/30/90-day trends, referrer channels, devices, UTM campaigns, CSV export, country maps and editorial SEO checks. Administrators and editors can view reports. Existing installations run analytics:prepare once. Country data needs a trusted hosting proxy header; otherwise location stays Unknown. Google Search Console is not connected: queries, impressions, CTR, rankings and Core Web Vitals are not measured by this tracker.
php dl analytics:prepare
php dl analytics:prune
php tests/analytics.phpVerify before deployment
Run isolated tests, then verify cPanel, MySQL, HTTPS, permissions and your provider on the target host. A lower runtime footprint is a design choice; no WordPress performance comparison has been completed.
php tests/cms.php
python3 tests/cms_http.py /path/to/phpDL Counsel theme
Appearance includes DL Counsel, a monochrome law-firm homepage inspired by ProCounsel. Use Customize for the firm name, hero, about text, four practice areas, media image and contact details. Preview does not activate the theme.
- Activate in Appearance to use the landing page at /site. /site?journal=1 retains the blog archive. Published posts and pages keep CMS SEO and content behavior.
- Contact details start empty. Enter email and phone to enable direct links. There is no appointment backend or email-sending form.
- Bundled PHP templates require no build, external font, icon CDN or frontend framework. The theme is included in the framework, not in a declarative upload ZIP.
Visual page editor
Pages → Add page provides Text and Visual choices. Visual saves the current text before opening the section canvas. Layout pages switch between the canvas and structured Text source without flattening content. Select elements to edit their content and layout. Appearance → DL Counsel → Create editable homepage creates an editable draft copy.
- Add heading, text, rich text, image, button, divider and Form elements. Arrange sections in Navigator; use column, spacing, alignment and background presets. Undo/redo and CMS revisions are available.
- Save page respects draft/published status and detects stale versions. Page settings includes SEO, visibility and optional administrator homepage assignment. The editor warns before leaving unsaved work; it does not autosave.
- Public pages are server-rendered with responsive CSS, no build. Shared headers/footers use Menus and theme Customize. This is a DL editor, not full Elementor compatibility.
Smart forms and notifications
Administrators can create forms and review responses in Forms. Use contact, consultation or feedback presets, add fields, make them required, or show them conditionally. Publish and insert a Form element in a visual page.
- Responses are stored privately with field snapshots, new/read/archive status, filters and CSV export. Duplicate submission protection, CSRF, honeypot and rate limits are enforced server-side.
- SMTP is optional and initially disabled. Set a recipient per form and configure private MAIL_* values. Responses remain stored if email fails; retry from the response inbox. Acceptance by SMTP does not confirm delivery.
- Email contains the form name and response ID only. There is no visitor autoresponder, attachment upload, payment processing or calendar booking backend.
MAIL_TRANSPORT=smtp
MAIL_HOST=mail.your-domain.example
MAIL_PORT=587
MAIL_ENCRYPTION=tls
MAIL_USERNAME=notifications@your-domain.example
MAIL_PASSWORD="fill privately"
MAIL_FROM=notifications@your-domain.example