mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-05-06 19:19:19 +02:00
ac872c1fe0aea7be17ce0fd92584d7e17fd97c8b
Replace presentational divs in index.php and main.css with elements that carry correct semantic meaning, fixing multiple WCAG 2.1 AA issues: index.php: - <div class="cards-container"> → <ul class="cards-container"> (list of navigable items) - <a class="card-link"><div class="card">…</div></a> → <li class="card"><a> (block link is the <a>, <li> is the container; removes the redundant .card div wrapper) - <div class="card__media"> → <figure class="card__media"> when wrapping an <img>; gradient placeholder stays as <div> (presentational, aria-hidden) - Improved alt text: "Couverture — [title] par [authors]" instead of bare title - Removed <div class="card__info"> wrapper; caption is now a bare <p class="card__caption"> directly inside the <a> - <div class="filter-info"> → <p class="filter-info" role="status"> (live-region semantics; announces filter state to screen readers) - ✕ symbol in clear-filter link wrapped in <span aria-hidden="true"> - Gradient placeholder div gets aria-hidden="true" (decorative; caption below carries text) - Empty-state <p style="…"> → <li class="cards-empty"> (removes inline style) - <div class="pagination-wrap"> → <nav class="pagination-wrap" aria-label="Pagination"> with <ul>/<li> children; page-info <span> → <li aria-current="page"> main.css: - .cards-container: add list-style:none; margin:0; padding:0 (reset <ul> defaults) - Remove .card-link rule; replace with .card > a (block flex link, no separate class) - .card__media: add margin:0 to reset <figure> default margin - Remove .card__info rules; rename .authors to .card__caption with same styles - Add .cards-empty rule (removes last inline style from index.php) - .pagination-wrap: restructured for <nav>/<ul>; inner <ul> carries the flex layout - prefers-reduced-motion: add .card__media--gradient guard WCAG criteria addressed: 1.1.1 (alt text), 1.3.1 (info & relationships via semantic list/figure), 2.4.1 (filter-info now live region), role="status" on filter banner.
posterg
Répertoire des travaux de fin d'études de l'ERG (École de Recherche Graphique).
Requirements
- PHP 8.4
- SQLite3 (
php8.4-sqlite3) - nginx (production)
Project structure
posterg/
├── public/ # DocumentRoot — web-accessible only
│ ├── admin/ # Admin panel (session-authenticated)
│ ├── assets/ # CSS, fonts, icons
│ ├── media.php # Controlled file serving (covers, PDFs)
│ └── *.php # Public pages (index, search, tfe, apropos)
├── src/ # PHP classes (not web-accessible)
│ ├── AdminAuth.php
│ ├── Database.php
│ ├── RateLimit.php
│ └── config.php
├── templates/ # Shared PHP template partials
├── config/ # Bootstrap and credentials (not web-accessible)
├── storage/ # Database and uploaded files (not web-accessible)
│ ├── schema.sql
│ ├── test.db
│ └── fixtures/
├── tests/
├── scripts/ # Dev and server management scripts
│ ├── setup-dev.sh
│ ├── deploy-server.sh # Run on server with sudo to apply nginx config
│ └── manage-admin-users.sh # Run on server with sudo to manage htpasswd
└── nginx/ # nginx config and reference files
└── posterg.conf
Uploaded files (PDFs, covers) live in storage/ — outside the webroot — and are
served exclusively through public/media.php, which validates paths and MIME types.
Development
just setup # first-time: installs dev dependencies
just serve # http://localhost:8000 (public) and /admin/
just test # run test suite
Admin credentials in development are set via config/admin_credentials.php
(see config/admin_credentials.example.php).
Deployment
Files are pushed to the server with rsync — there is no repo on the remote.
just deploy # rsync app files → posterg:/var/www/posterg/
just deploy-db # push local test.db → remote (only if remote DB is absent)
deploy-db refuses to run if a database already exists on the server, to avoid
accidental overwrites of production data.
First-time server setup
ssh posterg
sudo mkdir -p /var/www/posterg
sudo chown www-data:posterg /var/www/posterg
sudo chmod 775 /var/www/posterg
exit
Then deploy once, copy nginx config, and apply:
just deploy
rsync -v nginx/posterg.conf posterg:/tmp/posterg.conf
ssh posterg "sudo bash /var/www/posterg/scripts/deploy-server.sh"
ssh posterg "sudo systemctl reload nginx"
Admin users (htpasswd)
ssh posterg "sudo bash /var/www/posterg/scripts/manage-admin-users.sh"
Security notes
- Admin panel protected by nginx
auth_basic+ PHP session (AdminAuth) - Uploads stored outside webroot, served via controlled
media.php - Rate limiting on public search (
src/RateLimit.php) - See
docs/TODO.SECURITY.mdfor outstanding items
Description
Languages
PHP
80.5%
CSS
14.9%
Shell
2.8%
JavaScript
1.3%
Just
0.5%