Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ composer.local.json
composer.local.lock

# Docker files
compose.override.yml
# (compose.override.yml is intentionally TRACKED — deploy.sh pins -f compose.yml
# so it is never merged on the server, but every developer gets the same setup)
/docker/nginx/ssl/

# Docker data volumes
Expand All @@ -45,4 +46,8 @@ docker/data/
*:Zone.Identifier

# Temp files
/public/favicon-code.html
/public/favicon-code.html

# opencode (local AI agent config — kept out of the repo)
/AGENTS.md
/.opencode/
54 changes: 46 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,28 +16,65 @@ The repository serves for [webifycms.com](https://webifycms.com) site which runs

### Docker Setup (recommended)

**Local development:**
**Local development** — `compose.override.yml` is applied automatically by
`docker compose`, giving you live host bind-mounts (code and asset changes are
picked up instantly) and local HTTPS via self-signed certs:

```bash
# Start the containers (compose.override.yml is applied automatically)
# Host-side dependencies (target the same files the containers bind-mount)
npm install

# Start the containers
docker compose up -d

# Install PHP dependencies
docker compose exec app composer install

# Install front-end dependencies and build assets
docker compose exec app npm install
# Build front-end assets (this also copies assets/img/ → public/assets/img/)
docker compose exec app npm run build
```

**Production (server):**
The site is then available at `http://localhost:${NGINX_PORT}` and
`https://webifycms.com.local:${NGINX_PORT_SSL}` (both set in `.env`). For the
HTTPS hostname, add `127.0.0.1 webifycms.com.local` to `/etc/hosts` and trust
the self-signed cert in `docker/nginx/ssl/` once.

**Production (server)** — only the base `compose.yml` is used, so the
local-only override is never merged:

```bash
# Ignore compose.override.yml — only the base compose.yml is used
docker compose -f compose.yml up -d
# Build and start (compose.override.yml is ignored)
docker compose -f compose.yml up -d --build
```

The site will be available at `http://localhost:3000` (configurable via `NGINX_PORT` in `.env`).
The two environments differ only in `compose.override.yml`:

| | Local (`docker compose`) | Production (`docker compose -f compose.yml`) |
|---|---|---|
| `app` image | `docker/php/local.Dockerfile` + host bind-mount | `docker/php/Dockerfile` (bundles code + assets + images) |
| nginx config | `docker/nginx/nginx.local.conf` (local TLS) | `docker/nginx/nginx.caddy.conf` (HTTP, Caddy terminates TLS) |
| SSL certs | `docker/nginx/ssl/` (gitignored, self-signed) | none (Caddy-managed) |
| Web root | host `./` bind-mounted | shared `app-data` volume seeded from the image |

The `compose.override.yml` used for local development:

```yaml
services:
app:
build:
context: .
dockerfile: ./docker/php/local.Dockerfile
volumes:
- ./:/var/www/html
server:
volumes:
- ./:/var/www/html
- ./docker/nginx/nginx.local.conf:/etc/nginx/conf.d/default.conf
- ./docker/nginx/ssl:/etc/nginx/ssl:ro
ports:
- "${NGINX_PORT}:80"
- "${NGINX_PORT_SSL}:443"
```

### Manual Setup

Expand Down Expand Up @@ -73,6 +110,7 @@ npm run build
- JS is extracted from inline `<script>` tags into `assets/js/app.js`
- In development, `App\Infrastructure\Helper\Vite` serves assets from the Vite dev server
- In production, it reads `public/.vite/manifest.json` for hashed filenames
- `npm run build` also copies `assets/img/` into `public/assets/img/` so images referenced directly from templates (e.g. `logo.png`) are served in every environment — same as the production Dockerfile
- Add the Vite dev server origin (`http://localhost:5173`) to your `.env` if needed

### Asset structure
Expand Down
15 changes: 15 additions & 0 deletions assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -998,6 +998,10 @@ img {
gap: 1rem;
}

.ext-themes {
padding-top: 5.5rem;
}

@media (min-width: 48rem) {
.ext-list {
grid-template-columns: 1fr 1fr;
Expand Down Expand Up @@ -1582,6 +1586,11 @@ img {
opacity: 0.3;
}

.post-header__updated {
color: var(--violet);
font-weight: 600;
}

.post-header__title {
font-family: var(--font-display);
font-size: clamp(2.25rem, 5vw, 3.5rem);
Expand Down Expand Up @@ -2537,6 +2546,12 @@ img {
transform: translateY(-0.125rem);
}

.sponsor__card--mono,
.sponsor__card--mono:hover {
filter: none;
transition-property: opacity, transform;
}

.sponsors__cta {
text-align: center;
font-size: 0.9375rem;
Expand Down
18 changes: 18 additions & 0 deletions assets/img/opencode.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
26 changes: 26 additions & 0 deletions compose.override.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Local development overrides.
#
# Automatically merged by `docker compose up -d` (no -f flag needed) on
# developer machines. It is NEVER applied in production: scripts/deploy.sh
# and the docs pin `docker compose -f compose.yml`, so this file is ignored
# on the server even after `git pull`.
services:
# PHP service — live code, no image copy. Requires host-side deps:
# `composer install`, `npm install`, and `npm run build` (see README).
app:
build:
context: .
dockerfile: ./docker/php/local.Dockerfile
volumes:
- ./:/var/www/html

# Nginx service — serve the live host docroot and terminate TLS locally
# with the self-signed certs in docker/nginx/ssl/ (gitignored).
server:
volumes:
- ./:/var/www/html
- ./docker/nginx/nginx.local.conf:/etc/nginx/conf.d/default.conf
- ./docker/nginx/ssl:/etc/nginx/ssl:ro
ports:
- "${NGINX_PORT}:80"
- "${NGINX_PORT_SSL}:443"
55 changes: 55 additions & 0 deletions docker/nginx/nginx.local.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
map $server_port $fastcgi_https {
443 on;
default off;
}

server {
charset utf-8;
client_max_body_size 10M;

listen 80;
listen 443 ssl;

ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;

server_name _;
root /var/www/html/public;
index index.php;

# Security headers
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "camera=(), microphone=(), geolocation=()" always;
add_header X-XSS-Protection "1; mode=block" always;
server_tokens off;

error_log /var/log/nginx/app_error.log;
access_log /var/log/nginx/app_access.log;

location / {
try_files $uri $uri/ /index.php$is_args$args;
gzip_static on;
}

# deny accessing php files for the /assets directory
location ~ ^/assets/.*\.php$ {
deny all;
}

location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param HTTPS $fastcgi_https;
}

location ~* /\. {
deny all;
}
}
46 changes: 34 additions & 12 deletions docs/DEPLOYMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,20 @@ docker network create shared-proxy

### 6. Initial Build and Start

> **Important:** production always uses `-f compose.yml`. The local-only
> `compose.override.yml` must never be merged on the server — running plain
> `docker compose` would auto-load it and break the site (it switches to the
> dev image, host bind-mounts, and local TLS config).

```bash
# Build and start containers
docker compose up -d --build
docker compose -f compose.yml up -d --build

# Verify containers are running
docker compose ps
docker compose -f compose.yml ps

# Check logs
docker compose logs -f
docker compose -f compose.yml logs -f
```

## GitHub Actions Setup
Expand Down Expand Up @@ -152,10 +157,27 @@ cat deploy_key
1. When you push to `main` or merge a PR, the workflow triggers
2. **Test job**: Runs static analysis, code style checks, and tests
3. **Deploy job** (only if tests pass):
- Builds frontend assets locally (`npm run build`)
- Builds frontend assets locally (`npm run build`) — this also copies `assets/img/` into `public/assets/img/`
- Uploads built assets (`public/assets/`, `public/.vite/`) to the server via SCP
- SSHes into the server and runs `scripts/deploy.sh`
4. The deploy script pulls the latest code, rebuilds Docker containers, and restarts them
4. The deploy script pulls the latest code, rebuilds Docker containers (`docker compose -f compose.yml`), and restarts them
5. The server image is built by `docker/php/Dockerfile`, which bundles the app code, the built assets, and the `assets/img/` images into the `app-data` volume — this is what nginx actually serves

### Environment separation

The project ships **one** `compose.yml` for production and a **separate** `compose.override.yml` for local development:

| | Production (server) | Local development |
|---|---|---|
| Compose files | `docker compose -f compose.yml` | `docker compose` (override auto-merged) |
| `app` image | `docker/php/Dockerfile` (code + assets + images bundled) | `docker/php/local.Dockerfile` (live host bind-mount) |
| nginx config | `docker/nginx/nginx.caddy.conf` (HTTP only, Caddy terminates TLS) | `docker/nginx/nginx.local.conf` (local TLS, self-signed certs) |
| SSL certs | Caddy-managed, none required | `docker/nginx/ssl/` (gitignored, local only) |
| Web root | shared `app-data` volume seeded from the image | host `./` bind-mounted into both containers |

`compose.override.yml` is meant to be committed so every developer gets the
same local setup, and `deploy.sh` pins `-f compose.yml` so it is ignored on
the server.

## Manual Deployment

Expand Down Expand Up @@ -187,9 +209,9 @@ git log --oneline -10 # Find the commit you want
git checkout <commit-hash>

# Rebuild and restart
docker compose down
docker compose build --no-cache
docker compose up -d
docker compose -f compose.yml down
docker compose -f compose.yml build --no-cache
docker compose -f compose.yml up -d

# Or go back to the previous version
git checkout main~1
Expand All @@ -201,11 +223,11 @@ git checkout main~1

```bash
# Check container logs
docker compose logs app
docker compose logs server
docker compose -f compose.yml logs app
docker compose -f compose.yml logs server

# Check if port 3000 is in use
sudo netstat -tulpn | grep ':3000\s'
# Check if the port configured in NGINX_PORT is in use
sudo netstat -tulpn | grep ":${NGINX_PORT} "
```

### Permission errors
Expand Down
16 changes: 10 additions & 6 deletions resources/posts/2026-07-alpha-release.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
title: 'WebifyCMS First Alpha Release - The Bedrock'
slug: webifycms-first-alpha-release-the-bedrock
date: '2026-07-10'
updated: '2026-07-31'
---

# WebifyCMS First Alpha Release
Expand All @@ -26,9 +27,11 @@ metadata enforcement, ensuring the core is solid from day one.

## Current Development Status

With the base layer complete, work is now actively underway on `ext-user`, which will provide identity,
authentication, and authorization. Future extensions on the roadmap include content management (`ext-cms`),
an administration panel (`ext-admin`), and a marketplace for themes and extensions (`ext-marketplace`).
With the base layer complete, work is now actively underway on the three pieces that unlock the first
beta: `ext-user` (identity, authentication, and authorization), `ext-admin` (the slot-based admin panel),
and the official default theme `webifycms/theme-canvas`, which powers the front-end. Future extensions on
the roadmap include content management (`ext-cms`) and a marketplace for themes and extensions
(`ext-marketplace`).

## How to Get Involved

Expand All @@ -44,8 +47,9 @@ to be transparent — every layer, every boundary, and every decision is open fo

## What Comes Next

The immediate focus is on completing `ext-user` and preparing for the first beta release.
Alongside that, we will continue expanding documentation, improving test coverage,
and refining the developer experience.
The immediate focus is on completing `ext-user`. Because the user experience spans both the admin panel and
the front-end, that work goes hand in hand with `ext-admin` and the default `theme-canvas` theme — all three
are in progress together. Once they land, we will prepare the first beta release while continuing to expand
documentation, improve test coverage, and refine the developer experience.

Stay tuned for more updates, and thank you for following the WebifyCMS journey.
3 changes: 3 additions & 0 deletions resources/posts/posts.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@
"title": "WebifyCMS First Alpha Release - The Bedrock",
"slug": "webifycms-first-alpha-release-the-bedrock",
"date": "2026-07-10",
"updated": "2026-07-31",
"excerpt": "We are excited to announce the very first alpha release of WebifyCMS — version 0.1.0-alpha \"Bedrock\" is now available. This marks a major milestone for...",
"file": "2026-07-alpha-release.md"
},
{
"title": "WebifyCMS Logo Concept",
"slug": "webifycms-logo-concept",
"date": "2026-06-25",
"updated": "2026-06-25",
"excerpt": "The WebifyCMS logo combines a geometric hexagon mark with bold monospaced typography to communicate structure, clarity, and developer focus. The design...",
"file": "2026-06-logo-concept.md"
},
{
"title": "Introduction to WebifyCMS",
"slug": "introduction-webifycms",
"date": "2026-06-17",
"updated": "2026-06-17",
"excerpt": "Summary: WebifyCMS is an open-source PHP application framework built from the ground up on Clean Architecture and Domain-Driven Design (DDD). It was...",
"file": "2026-06-introduction.md"
}
Expand Down
10 changes: 10 additions & 0 deletions resources/themes.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[
{
"name": "Canvas",
"package": "webifycms/theme-canvas",
"status": "In progress",
"version": "",
"description": "The official default theme that ships with WebifyCMS.",
"url": "https://github.com/webifycms/theme-canvas"
}
]
Loading
Loading