docs: record approved website redesign plan
44
tasks/baseline-2026-09-24.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Bundle 0 flow, accessibility and performance baseline
|
||||
|
||||
Captured 2026-09-24 with the current Next.js 15 frontend, Playwright Chromium, and local production build. Viewports: 320×800, 390×844, 768×900 and 1440×900 CSS pixels. The backend at `127.0.0.1:8000` was not running for this initial capture; a backend-backed replay followed on 2026-09-25 below. Screenshots in [`evidence/2026-09-24/`](evidence/2026-09-24/) are full-page browser captures, not design comps.
|
||||
|
||||
## Route and state map
|
||||
|
||||
| Journey | Current route/transition | States to preserve and replay |
|
||||
| --- | --- | --- |
|
||||
| Visitor/association | `/` → `/about`, `/events`, `/blog` | Home/About render and responsive shell; external contact links |
|
||||
| Auth | `/auth` mobile lookup → existing user password or OTP login; new user OTP → registration details → profile/return; `/auth/google/callback`; `/verify-email/[token]`; `/reset-password` → `/reset-password/[token]`; `/logout` | Invalid mobile, expired/incorrect OTP, resend cooldown, duplicate submit, Google failure, expired reset, protected redirect |
|
||||
| Event | `/events` search/filter → `/events/[slug]` → free registration `/events/[slug]/success` or paid gateway → `/payments/result` | Open, full, closed, already registered, ineligible, invalid coupon, payment pending/success/failure/canceled, callback replay |
|
||||
| Blog | `/blog` banners/search/category/tag/author → `/blog/[slug]` | Empty/failure, long article, media fallback, comments/interactions and share |
|
||||
| Staff | `/admin` → dashboard, events, users, taxonomy, coupons, authorizations, blog editor/review/assets | Anonymous redirect, role denial, save conflict, validation, successful edit/publish, mobile table/form navigation |
|
||||
|
||||
## Browser evidence
|
||||
|
||||
| Page | Captures | Observed behavior |
|
||||
| --- | --- | --- |
|
||||
| Home | `home-320.png`, `home-390.png`, `home-768.png`, `home-1440.png` | Loads with current identity/CTA. At 390px the fixed mobile navigation overlays the first offering card while scrolling; record for later shell work. |
|
||||
| About | `about-320.png`, `about-390.png`, `about-768.png`, `about-1440.png` | Loads with static statistics, affiliations and contacts. The long page contains no `<main>` landmark. |
|
||||
| Auth | `auth-390.png` | Mobile entry screen loads. OTP/login success requires a working auth backend and test account. |
|
||||
| Events | `events-390.png` | Listing displays `رویدادی یافت نشد` when its API request fails, which looks like a real empty catalog. Browser console has `ERR_CONNECTION_REFUSED` to `127.0.0.1:8000/api/events/`. Registration states cannot be replayed from this environment. |
|
||||
| Blog | `blog-390.png` | Listing shell loads; API requests fail and a mock banner is visible. Post navigation and interactions need backend fixtures. |
|
||||
| Staff | `admin-390.png` | Anonymous `/admin` redirects to `/`. Authorized staff walkthrough requires a test account. |
|
||||
|
||||
Screenshots were inspected for page identity and nonblank content. The route screenshots listed above are the accepted current-site baseline; screenshots of rejected concept drafts are not part of that baseline.
|
||||
|
||||
## Measured baseline
|
||||
|
||||
`npm run build` passed on 2026-09-24. Its First Load JS report (production build, compressed route estimate): shared **102 kB**, Home **107 kB**, About **103 kB**, Auth **163 kB**, Events listing **124 kB**, Event detail **469 kB**, Blog listing **141 kB**, Blog detail **469 kB**, Admin dashboard **302 kB**, Admin event editor **727 kB**, Payment result **613 kB**. The build emitted existing `no-img-element` warnings and an ESLint plugin detection warning; it also logged API connection refusal during static page generation.
|
||||
|
||||
`npm run lint` exited successfully with 14 existing `no-img-element` warnings and no errors. A focused backend baseline command, `.venv/Scripts/python.exe manage.py test apps.users.tests apps.events.tests apps.payments.tests --settings=config.settings.test`, was started and stopped after repeated failures reaching the notification store at `127.0.0.1:6379`. Docker Desktop's engine was unavailable, so Redis could not be started locally. This test run has **no passing-suite result**; rerun it with an isolated Redis service for the flow gate.
|
||||
|
||||
At 390px in one local Chromium production run, Home navigation duration was **554 ms** and first contentful paint **424 ms**; About was **173 ms** and **204 ms**. These are local machine observations, not network performance targets or p75 Web Vitals. Both pages had one `<h1>`, no horizontal overflow, and zero `<img>` elements missing an `alt` attribute. Home had one `<main>` landmark; About had none. The desktop and 320px screenshots establish layout comparison points. No automated WCAG score is claimed; a full axe/keyboard/screen-reader audit remains part of the release gate.
|
||||
|
||||
## Manual replay status and next gate
|
||||
|
||||
At the initial capture, completed: Home/About rendering at four widths; auth entry; unauthenticated admin redirect; event API failure display; blog shell with backend unavailable. The backend-backed journeys were pending at that point. Do not infer a business-rule change from the initial frontend-only failure state.
|
||||
|
||||
## Follow-up with Redis and isolated backend, 2026-09-25
|
||||
|
||||
The owner started a Redis container on port 6379. The local backend and frontend then ran against an isolated SQLite test database and disposable fixtures. See the [local journey replay](evidence/2026-09-24/local-replay.md) for auth, free/full/paid event, blog, staff, and failure-state evidence. The event integration suite passed 25 tests. The broader users/events/payments test run executed 148 tests with 89 errors from stale test fixtures/patch targets; its [raw log](evidence/2026-09-24/backend-focused-tests.txt) is preserved. `manage.py check` passed.
|
||||
|
||||
The core browser flows are now captured. External SMS delivery, Google OAuth, and a live payment gateway were deliberately replaced with safe local mocks or left for staging. The baseline also found a countdown hydration mismatch and a notification stream-token 405. The owner accepted this baseline with its then-current limitations in `bundle0-review.md` on 2026-09-26, closing T02 and Checkpoint A at discovery scope. On 2026-09-26, the repository's current pytest suites passed: 79 unit and 158 integration tests. See [the rerun record](evidence/2026-09-24/test-rerun-2026-09-26.md). The original 148-test/89-error run remains historical evidence; the external SMS, OAuth, and live gateway paths remain untested.
|
||||
52
tasks/build-content-line-ledger.ps1
Normal file
@@ -0,0 +1,52 @@
|
||||
# Rebuild the line-level source ledger for the static public-content files.
|
||||
# Run from any directory: pwsh -File tasks/build-content-line-ledger.ps1
|
||||
$frontend = (Resolve-Path (Join-Path $PSScriptRoot '../../guilan-ace-frontend')).Path
|
||||
$sources = @(
|
||||
'src/views/Home.tsx',
|
||||
'src/views/AboutUs.tsx',
|
||||
'src/components/Navbar.tsx',
|
||||
'src/components/Footer.tsx',
|
||||
'src/components/MobileBottomNav.tsx',
|
||||
'src/app/page.tsx',
|
||||
'src/app/about/page.tsx',
|
||||
'src/app/layout.tsx',
|
||||
'src/app/events/page.tsx',
|
||||
'src/app/blog/page.tsx'
|
||||
)
|
||||
|
||||
$rows = foreach ($source in $sources) {
|
||||
$lineNumber = 0
|
||||
foreach ($line in [System.IO.File]::ReadAllLines((Join-Path $frontend $source))) {
|
||||
$lineNumber++
|
||||
if ($line -notmatch '[\u0600-\u06FF]|https?://|favicon\.ico|enamad\.png') { continue }
|
||||
|
||||
$category = 'CMS editorial'
|
||||
$note = ''
|
||||
if ($line -match 'schema\.org|contactType|availableLanguage') {
|
||||
$category = 'code-owned UI'
|
||||
$note = 'Schema structure or vocabulary; referenced identity values remain editorial.'
|
||||
} elseif ($source -match 'Navbar|MobileBottomNav') {
|
||||
if ($line -match 'auth|profile|reset-password|logout|admin|ورود|ثبتنام|حساب|داشبورد|پروفایل|رمز|خروج|منوی') {
|
||||
$category = 'code-owned UI'
|
||||
}
|
||||
} elseif ($source -eq 'src/views/Home.tsx') {
|
||||
if ($line -match 'aria-label|<Button|<Link' -or $lineNumber -in @(55, 60, 121, 122)) { $category = 'code-owned UI' }
|
||||
} elseif ($source -match 'src/app/(events|blog)/page.tsx') {
|
||||
if ($line -match 'search|جست|robots') {
|
||||
$category = 'code-owned UI'
|
||||
$note = 'Query-specific title/description or search behavior; default listing introduction remains editorial.'
|
||||
}
|
||||
}
|
||||
[pscustomobject]@{
|
||||
source = $source
|
||||
line = $lineNumber
|
||||
category = $category
|
||||
source_text = $line.Trim()
|
||||
note = $note
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$output = Join-Path $PSScriptRoot 'content-source-lines.csv'
|
||||
$rows | Export-Csv -LiteralPath $output -NoTypeInformation -Encoding utf8
|
||||
Write-Output "$($rows.Count) source lines written to $output"
|
||||
44
tasks/bundle0-review.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Bundle 0 review for the association owner
|
||||
|
||||
Prepared 2026-09-25; revised after the owner rejected three earlier design concepts and gave three visual references plus the Home structure. This page collects the decisions needed to close Checkpoints A and B in [plan.md](plan.md). It does not authorize a production seed or change any event/payment rule.
|
||||
|
||||
**Owner approval recorded 2026-09-26:** the owner read and approved this review, including the content ownership and exclusions, the local baseline with its stated test/external-integration limits, and the CMS/API decisions below. T01, T02, T05, Checkpoints A/B, and Bundle 0 are closed at discovery and contract scope. Bundle 1 has not started. Later seed, staff-account, media, staging, and release gates remain in [todo.md](todo.md).
|
||||
|
||||
## Already chosen
|
||||
|
||||
- **Home/About design direction approved 2026-09-25:** use the current association logo's teal, pale gold, and charcoal in a modern content-rich interface. [View Home](concepts/d-logo-led-home.html), [About](concepts/d-logo-led-about.html), the [Shadcn/ui and Lucide component map](concepts/d-component-map.md), and the [design record](../../guilan-ace-frontend/DESIGN.md). Home follows intro → featured events → featured blog posts → CTA → footer. This approval settles T04's visual direction; production components and content still require implementation review.
|
||||
- **Identity:** keep the existing repository logo; use the official full name in About and metadata, with the current short lockup and faculty subline in the header.
|
||||
- **Public contacts:** use the About-page email `eastguilanceassociation@gmail.com`, Telegram `t.me/guilancea`, and Instagram `instagram.com/guilance.ir`. The current footer variants are recorded for cutover.
|
||||
|
||||
## Content ownership for review
|
||||
|
||||
The [route matrix](content-inventory.md) and [208-line source ledger](content-source-lines.csv) classify current public copy, images, and metadata. The proposed boundary is:
|
||||
|
||||
| Owner | Examples |
|
||||
| --- | --- |
|
||||
| New CMS | Association identity, approved contacts, Home/About editorial sections, navigation labels/order, footer description, page introductions and default SEO. |
|
||||
| Existing domain models | Events, capacity/prices, registrations/payments, blog articles/authors/media, user profiles. |
|
||||
| Application code | Route destinations, auth/payment state labels, forms and errors, admin controls, responsive behavior, canonical/JSON-LD structure. |
|
||||
|
||||
The initial seed will exclude disputed statistics and founding-year mappings, affiliation relationships, personal LinkedIn/generic X links, and the trust-seal claim until their source and entity are confirmed. The exact legacy values remain in the inventory; nothing is silently rewritten.
|
||||
|
||||
## Approved CMS/API decisions
|
||||
|
||||
The [architecture contract](cms-api-contract-draft.md) and [backend response schema](../../guilan-ace-backend/docs/content-api-schema-draft.md) specify:
|
||||
|
||||
1. Fixed Home editorial sections: association-first `hero`, `featured_events`, `featured_posts`, then `participation`. Event and blog cards read existing domain APIs; the CMS owns only headings/intro/actions around them. About uses `identity` first and `contact` last, with optional mission, activities, values, committees, affiliations, and FAQ. Route IDs and destinations stay in code. The proposed featured-item selection policy is in the contract.
|
||||
2. `content_editor` can draft and preview authorized content; `content_publisher` can publish and restore; superusers retain full control. `is_staff` alone cannot publish. Public readers receive published revisions only.
|
||||
3. Staff preview requires authentication and returns exact draft revisions with `no-store` and `noindex`. A publish swaps an immutable revision pointer and records an audit entry; restore creates another revision rather than rewriting history.
|
||||
4. Public API responses use `ETag` and a proposed 60-second shared-cache bound. The frontend avoids an additional persistent CMS cache. Missing/unpublished content returns 404 and the frontend stays on legacy rendering until cutover.
|
||||
|
||||
Actual staff account assignments, media rights/import, uncertain content claims, and deployment rehearsal happen in later tasks before production release.
|
||||
|
||||
## Accepted baseline of current state
|
||||
|
||||
The [dated baseline](baseline-2026-09-24.md) and [local replay](evidence/2026-09-24/local-replay.md) cover Home/About captures at 320/390/768/1440px and local auth, event, mocked payment, blog and staff journeys with failure cases. With Redis running, `manage.py check` and **25 event integration tests passed**. The historical combined users/events/payments Django test command ran 148 tests with 89 errors, mostly stale test fixtures and patch targets; its raw output remains in [the original test log](evidence/2026-09-24/backend-focused-tests.txt). On 2026-09-26, the current documented pytest suites passed **79 unit tests and 158 integration tests**; see [the rerun record](evidence/2026-09-24/test-rerun-2026-09-26.md). External SMS, Google OAuth, and a live payment gateway remain untested.
|
||||
|
||||
The replay also found a countdown hydration mismatch and notification stream-token HTTP 405. These are current-state issues for later implementation planning. SMS delivery, Google OAuth, and a live gateway were not exercised; the OTP and payment callbacks were safely mocked locally.
|
||||
|
||||
## Approval record
|
||||
|
||||
The owner approved this document on 2026-09-26 after separately approving the Home/About design direction on 2026-09-25. Checkpoint A accepts the inventory classification and recorded local baseline, including the historical 89-error run and the unexercised external paths. The current pytest suite rerun subsequently passed, as recorded above. T05 and Checkpoint B accept the section registry, featured-item policy, field bounds, roles, published/preview API behavior, and cache rule for implementation. This approval does not authorize production content publication.
|
||||
73
tasks/cms-api-contract-draft.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Public content CMS and API contract — approved for implementation
|
||||
|
||||
Date: 2026-09-24; revised 2026-09-25; approved by the owner through `bundle0-review.md` on 2026-09-26. Status: **Bundle 0 contract approved for implementation; no public API or schema exists yet**. Inputs: `content-inventory.md`, `product-review.md`, frontend `PRODUCT.md` and `DESIGN.md`, existing Django Ninja routing in `guilan-ace-backend/config/api.py`.
|
||||
|
||||
## Ownership boundary
|
||||
|
||||
The CMS owns association identity, approved public navigation/footer/contact entries, and page introductions/SEO. It owns ordered, visible sections of `home` and `about` from the finite registry below. It does **not** own event/blog records, registration success markdown already stored on each event, auth/form/admin text, payment outcomes, or free-form layouts. Stable slugs initially: `home`, `about`, `events`, `blog`.
|
||||
|
||||
## Proposed persistent records
|
||||
|
||||
| Record | Fields and constraints |
|
||||
| --- | --- |
|
||||
| `SiteIdentity` singleton | Stable site key and nullable `published_revision_id`. Singleton enforced in service/admin and database. |
|
||||
| `SiteRevision` | Immutable snapshot of `official_name` (required, max 180), `short_name` (required, max 80), `faculty_subline` (max 140), `description` (max 500), logo media FK and required alt when logo exists; approved contacts/social entries and navigation entries with fixed IDs, label, sort order and visibility; footer copy; default SEO. Tracks editor, publisher and timestamps like page revisions. |
|
||||
| `EditorialPage` | Unique immutable `slug` from an allowed registry; `page_kind` (`sections` or `listing_intro`); current published revision FK nullable. Slug never derived from editable title. |
|
||||
| `PageRevision` | Page FK, monotonic revision number, `draft` or `published` snapshot, title, intro, SEO title/description/OG media, creator, publisher, timestamps, source seed key/version and immutable content checksum. Store each publish as a new immutable snapshot; do not mutate the public revision in place. |
|
||||
| `PageSection` within revision | Stable section key, approved type, position integer, visible boolean, bounded type-specific text fields, optional media FK and alt text. Unique `(revision, key)` and `(revision, position)`; type/slug registry restricts allowed combinations. |
|
||||
| `MediaAsset` | Uploaded file, MIME signature, bytes, dimensions, alt, license/source and approval status. Logo and OG media use the same managed-media path; no frontend build URL becomes permanent content. |
|
||||
| `PublicationAudit` | Actor, site or page target, from/to revision, operation (`create_draft`, `update_draft`, `publish`, `restore`), timestamp. Append only. |
|
||||
|
||||
Proposed section registry aligned to the owner's fixed Home order. Section records supply editorial text; they do not duplicate event/post records or select a card layout, colors, or button styling:
|
||||
|
||||
| Page | Section key/type | Required | Editable content | Order/visibility |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `home` | `hero` | Yes | Heading (max 120), lead (max 500), primary/secondary CTA labels (max 40 each), each CTA target selected from fixed `about`, `events`, `blog` route IDs; optional approved image and alt | First and visible. Site name/subline comes from `SiteRevision`, not a second copy. |
|
||||
| `home` | `featured_events` | Yes | Section heading (max 90), introduction (max 300), all-events link label (max 40) | Second and visible. Event cards, posters, dates, prices and status read the existing events API, not this section. |
|
||||
| `home` | `featured_posts` | Yes | Section heading (max 90), introduction (max 300), all-posts link label (max 40) | Third and visible. Post cards, titles, categories, images and links read the existing blog API, not this section. |
|
||||
| `home` | `participation` | Yes | Heading (max 90), body (max 600), up to 2 CTA labels (max 40 each) with fixed route IDs; optional approved image and alt | Fourth and visible, before the shared footer. |
|
||||
| `about` | `identity` | Yes | Heading (max 120), introduction (max 600); official name/mark from `SiteRevision` | First and visible. |
|
||||
| `about` | `mission`, `activities`, `values`, `committees`, `affiliations`, `faq` | No | Heading (max 90), body (max 1200) or typed entries (max 20, each title/question max 120 and text/answer max 600) | Reorderable after identity or hidden. Unmapped statistics and affiliation claims are omitted from the initial seed. |
|
||||
| `about` | `contact` | Yes | Heading (max 90); approved visible contact entries from `SiteRevision` | Last and visible; contacts have one source of truth. |
|
||||
|
||||
`events` and `blog` use bounded title/intro/SEO fields and no sections. Every allowed section key is unique within its page revision; publishing rejects missing required sections or an invalid order. The Home order is fixed by the owner's design requirement; About optional sections remain reorderable/hideable. Section text is plain text. Navigation destination IDs and route paths are code-owned; editors can edit display labels/order/visibility on the approved destination list, not supply arbitrary in-app hrefs. The initial public contact set is the owner's About-page selection. This registry and field limits were accepted for T06 implementation on 2026-09-26.
|
||||
|
||||
The Home featured-event source needs no new CMS event fields. The first release selects the next three published future events by start time; if none exist, it shows recent completed events with an archive label. Blog uses published `is_featured` posts, then recent published posts as a fallback. Empty results show a short honest message and a link to the full listing. This selection policy was accepted on 2026-09-26; it never changes registration, payment, or publication rules.
|
||||
|
||||
## Edit, preview, publish and restore
|
||||
|
||||
| Actor | Draft | Preview | Publish | Restore | Public read |
|
||||
| --- | --- | --- | --- | --- | --- |
|
||||
| Anonymous | No | No | No | No | Published only |
|
||||
| Authenticated nonstaff | No | No | No | No | Published only |
|
||||
| `content_editor` staff group | Yes, on allowed pages | Own/authorized drafts | No | No | Published only |
|
||||
| `content_publisher` staff group | Yes | Yes | Yes | Yes | Published only |
|
||||
| Superuser | Yes | Yes | Yes | Yes | Published only |
|
||||
|
||||
Use explicit Django permissions (`change_content_draft`, `preview_content_draft`, `publish_content`, `restore_content`) and group assignment; `is_staff` alone does not grant publishing. A transaction checks permission and locks the page row, writes an immutable revision and swaps `published_revision_id` atomically. Restore creates a new revision from the chosen prior snapshot, preserving history. Publisher and editor identities remain visible in admin audit. Preview requires authentication, authorization and a draft revision; no public route accepts a draft ID.
|
||||
|
||||
## Proposed API v1
|
||||
|
||||
Mounted under the existing `/api/` Ninja root in `config/urls.py`:
|
||||
|
||||
- `GET /api/v1/content/site`: only published identity. `200` with `revision`, `published_at`, names, logo URL/alt, approved contacts, navigation route IDs/labels/order/visibility, footer and SEO defaults. `404` when there is no published identity.
|
||||
- `GET /api/v1/content/pages/{slug}`: only published page. `200` with `slug`, `revision`, `published_at`, `title`, `intro`, `seo`, and ordered visible `sections`; `404` for unknown or unpublished-only slugs. Hidden sections never leave the response.
|
||||
- `GET /api/v1/content/preview/pages/{slug}?revision=<id>`: authenticated authorized staff only; exact draft revision; `403` for unauthorized staff and `404` for missing draft. The server must not expose draft existence to anonymous callers. Set `Cache-Control: private, no-store`, `Vary: Cookie, Authorization`, and `X-Robots-Tag: noindex, nofollow`.
|
||||
- `GET /api/v1/content/preview/site?revision=<id>`: the same staff permission and no-store rules for a site-identity draft, including logo, navigation, contacts, footer and SEO defaults. Public site data remains at its published revision during preview.
|
||||
|
||||
The [backend API schema draft](../../guilan-ace-backend/docs/content-api-schema-draft.md) contains complete site, Home and About payload examples. Use canonical path from the fixed slug map, not an arbitrary editor URL. Proposed public cache: `Cache-Control: public, s-maxage=60, must-revalidate` plus `ETag` from the published revision and response checksum. The frontend CMS adapter performs uncached server reads so a second page cache does not extend that 60-second bound. Publish/restore invalidates application cache and requests frontend revalidation for `/`, `/about`, `/events`, `/blog`, and shared shell; revalidation failure is logged while the shared API cache still expires within 60 seconds. The deployment proxy already routes `PathPrefix(/api)` to the Django service; the release rehearsal must verify the deployed configuration. `404` is explicit for empty site/page; the frontend flag remains on legacy rendering until approved content exists. Draft preview uses no shared cache at any layer. Unknown slugs and unpublished-only pages have the same public `404` shape.
|
||||
|
||||
## Media, validation and seed rules
|
||||
|
||||
- Reject unsafe markup; text fields are plain text or tightly validated Markdown only where specified. Reject non-HTTP(S) links except explicitly supported `mailto:` and `tel:` contact types. Verify media by content signature, dimensions and byte limit; require meaningful alt for informative images.
|
||||
- Public images use backed-up Django media URLs. Optional image absent means the section remains legible with text alone. The source logo checksum and license/source are recorded before import.
|
||||
- The T12 manifest records stable keys, source path, exact legacy value, checksum where relevant, destination, approval actor/status, and exclusion reason. T13 dry run emits create/skip/conflict and field diffs, never overwrites an editor-modified row by default, and creates drafts only.
|
||||
|
||||
## Paper walkthrough and later release gates
|
||||
|
||||
1. Editor changes `home.hero` in a draft. Public `GET` stays at published revision 3. Authorized preview of draft 4 returns new copy with `no-store`; anonymous preview returns no draft content.
|
||||
2. Publisher reviews preview at 320px and desktop, publishes. Transaction swaps revision pointer to 4 and logs publisher. Public cache invalidates or expires within agreed TTL. Event and payment records are untouched.
|
||||
3. Publisher restores revision 3. Service creates revision 5 with revision 3 content, logs restore, swaps published pointer. Readers see revision 5; revision 4 stays in history.
|
||||
4. At 320px, long Persian identity wraps, navigation remains reachable without covering content, optional image leaves no blank frame, and hidden optional About sections do not leave layout gaps. At desktop, Home section order matches the owner's fixed sequence and the approved visual direction.
|
||||
|
||||
The earlier concepts were rejected. Frontend `DESIGN.md` records the approved logo-led Home/About direction. **T05 and Checkpoint B were accepted on 2026-09-26:** fixed Home order, featured-item selection policy, section registry and field limits above, `content_editor`/`content_publisher` permission policy, exact preview behavior, fixed-route payloads, and the 60-second API cache rule. **Later release gates:** assigning actual staff accounts, importing licensed media, deployment-proxy rehearsal, and mapping disputed content claims before seed publication.
|
||||
BIN
tasks/concepts/assets/Vazirmatn-variable.woff2
Normal file
BIN
tasks/concepts/assets/event-algorithms.webp
Normal file
|
After Width: | Height: | Size: 51 KiB |
BIN
tasks/concepts/assets/event-docker.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
tasks/concepts/assets/event-git.webp
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
tasks/concepts/assets/favicon.ico
Normal file
|
After Width: | Height: | Size: 141 KiB |
18
tasks/concepts/d-component-map.md
Normal file
@@ -0,0 +1,18 @@
|
||||
# Logo-led Home/About comp: implementation map
|
||||
|
||||
Status: Home/About visual direction approved by the owner on 2026-09-25. [Home](d-logo-led-home.html) and [About](d-logo-led-about.html) are static review comps. They use the association's current logo, its sampled teal `#28626E`, pale gold `#F9E697`, and charcoal `#313332`. The event posters are copies of existing backend media. Blog titles and artwork in the Home comp are explicitly illustrative.
|
||||
|
||||
The frontend already has Shadcn/ui source components under `src/components/ui/` and `lucide-react`. Production implementation should compose those local components with theme tokens, not copy this comp's static HTML or inline SVG sprite:
|
||||
|
||||
| Comp element | Frontend composition |
|
||||
| --- | --- |
|
||||
| Primary/secondary action | `Button` with `asChild`, `variant="default"` or `variant="outline"`, and the app's `Link`. Use semantic theme tokens for the logo palette. |
|
||||
| Event/post preview | `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardContent`, `CardFooter`; image from event/blog domain record. |
|
||||
| Archive/category label | `Badge` with `secondary` or `outline` variant. |
|
||||
| Footer and article dividers | `Separator` where a semantic divider helps. |
|
||||
| Mobile navigation | Existing `MobileBottomNav` pattern, adjusted for brand tokens and content clearance. |
|
||||
| Icons | Existing `lucide-react`: `ArrowUpLeft`, `CalendarDays`, `BookOpen`, `Newspaper`, `GraduationCap`, `UsersRound`, `Mail`, `Send`, `Instagram`. The comp's SVG sprite uses their icon paths. |
|
||||
|
||||
Home order is fixed: association intro → featured events → featured blog posts → participation CTA → footer. The CMS supplies intro/CTA and shared identity/contact copy. The event and blog sections read their existing APIs. The events model currently has no editorial `is_featured` flag; proposed first pass selects the next three published future events, then clearly labeled recent archive items if none are upcoming. Blog has `is_featured`; proposed first pass selects published featured posts, then recent published posts as fallback. Dates, prices, capacity, and registration status must come from each event record at render time, never from the static comp. A later owner decision can add manual curation if needed.
|
||||
|
||||
The comp is the approved visual and structural direction for T04. T05 CMS/API contract approval remains open; no production Home/About route or business rule changed.
|
||||
27
tasks/concepts/d-logo-led-about.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<!doctype html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#28626e">
|
||||
<link rel="icon" href="./assets/favicon.ico">
|
||||
<link rel="stylesheet" href="./d-logo-led.css">
|
||||
<title>درباره انجمن — طرح مبتنی بر نشان انجمن</title>
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-head"><div class="wrap head-inner">
|
||||
<a class="brand" href="./d-logo-led-home.html"><img src="./assets/favicon.ico" alt=""><span><strong>انجمن علمی مهندسی کامپیوتر</strong><small>دانشکدهی فنی و مهندسی شرق گیلان</small></span></a>
|
||||
<nav class="top-nav" aria-label="ناوبری اصلی"><a href="./d-logo-led-home.html">خانه</a><a href="./d-logo-led-home.html#events">رویدادها</a><a href="./d-logo-led-home.html#blog">بلاگ</a><a href="#about" aria-current="page">درباره انجمن</a></nav>
|
||||
<div class="head-action"><a class="button outline" href="https://east-guilan-ce.ir/auth">ورود / ثبتنام</a></div>
|
||||
</div></header>
|
||||
<main id="about">
|
||||
<section class="about-hero" aria-labelledby="about-title"><div class="wrap"><h1 id="about-title">درباره انجمن</h1><p>انجمن علمی مهندسی کامپیوتر در دانشکدهی فنی و مهندسی شرق گیلان، فضایی برای یادگیری، اجرای برنامههای علمی و همکاری میان دانشجویان فراهم میکند.</p><div class="full-name">انجمن علمی مهندسی کامپیوتر دانشگاه گیلان (دانشکدهی فنی و مهندسی شرق گیلان)</div></div></section>
|
||||
<section class="section" aria-labelledby="mission-title"><div class="wrap about-columns"><div><h2 id="mission-title">کاری که انجام میدهیم</h2><p>با برگزاری رویدادها و انتشار محتوای آموزشی، فرصتهایی برای تمرین مهارت، آشنایی با موضوعهای تازه و ارتباط با دیگر علاقهمندان به فناوری ایجاد میکنیم.</p><p>دانشجویان میتوانند از راه شرکت در برنامهها، خواندن و نوشتن مطالب یا همکاری در اجرای فعالیتها همراه انجمن باشند.</p><a class="button primary" href="./d-logo-led-home.html#events">دیدن رویدادها <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a></div><div class="about-points"><div class="about-point"><span class="icon-box"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#graduation-cap"/></svg></span><div><strong>یادگیری کاربردی</strong><span>کارگاهها و برنامههای آموزشی</span></div></div><div class="about-point"><span class="icon-box"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#calendar-days"/></svg></span><div><strong>رویدادهای علمی</strong><span>نشستها و فرصتهای آشنایی با تجربههای تازه</span></div></div><div class="about-point"><span class="icon-box"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#users"/></svg></span><div><strong>همکاری دانشجویی</strong><span>مشارکت در برنامهریزی و اجرای فعالیتها</span></div></div></div></div></section>
|
||||
<section class="section alt" id="contact" aria-labelledby="contact-title"><div class="wrap about-columns"><div><h2 id="contact-title">با انجمن در ارتباط باشید</h2><p>برای پرسش، پیشنهاد برنامه یا همکاری، از کانالهای رسمی انجمن پیام بدهید.</p><p>برای شناخت برنامههای برگزارشده و نوشتههای انجمن هم میتوانید بخش رویدادها و بلاگ را ببینید.</p></div><div class="about-contact"><h2>راههای ارتباطی</h2><a dir="ltr" href="mailto:eastguilanceassociation@gmail.com">eastguilanceassociation@gmail.com</a><a dir="ltr" href="https://t.me/guilancea">t.me/guilancea</a><a dir="ltr" href="https://instagram.com/guilance.ir">instagram.com/guilance.ir</a></div></div></section>
|
||||
<section class="section faq" aria-labelledby="faq-title"><div class="wrap"><div class="section-header"><div><h2 id="faq-title">پرسشهای رایج</h2><p>چند پاسخ کوتاه برای شروع.</p></div></div><details><summary>چطور در یک رویداد شرکت کنم؟</summary><p>رویداد موردنظرتان را انتخاب کنید و شرایط، زمان و مراحل ثبتنام همان رویداد را بخوانید.</p></details><details><summary>چطور با انجمن همکاری کنم؟</summary><p>برای پیشنهاد همکاری، از راههای ارتباطی بالا پیام بدهید و موضوع پیشنهادیتان را توضیح دهید.</p></details></div></section>
|
||||
<section class="cta" aria-labelledby="cta-title"><div class="wrap cta-inner"><div><h2 id="cta-title">از برنامههای انجمن شروع کنید</h2><p>رویدادهای برگزارشده و نوشتههای انجمن، بهترین راه برای آشنایی با فعالیتهای ما هستند.</p></div><div class="actions"><a class="button gold" href="./d-logo-led-home.html#events">رویدادها <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a><a class="button outline" href="./d-logo-led-home.html#blog">بلاگ</a></div></div></section>
|
||||
</main>
|
||||
<footer class="site-foot"><div class="wrap"><div class="foot-grid"><div><div class="foot-brand"><img src="./assets/favicon.ico" alt=""><span>انجمن علمی مهندسی کامپیوتر</span></div><p>دانشکدهی فنی و مهندسی شرق گیلان، دانشگاه گیلان. فضایی برای یادگیری، رویداد و همکاری دانشجویی.</p></div><div><h3>دسترسی سریع</h3><a href="./d-logo-led-home.html">خانه</a><a href="#about">درباره انجمن</a><a href="./d-logo-led-home.html#events">رویدادها</a><a href="./d-logo-led-home.html#blog">بلاگ</a></div><div><h3>همراه انجمن</h3><a href="https://east-guilan-ce.ir/auth">ورود / ثبتنام</a><a href="./d-logo-led-home.html#events">برنامهها</a><a href="#contact">پیشنهاد همکاری</a></div><div><h3>ارتباط</h3><a class="contact-link" href="mailto:eastguilanceassociation@gmail.com"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#mail"/></svg><span dir="ltr">eastguilanceassociation@gmail.com</span></a><a class="contact-link" href="https://t.me/guilancea"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#send"/></svg><span>تلگرام انجمن</span></a><a class="contact-link" href="https://instagram.com/guilance.ir"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#instagram"/></svg><span>اینستاگرام انجمن</span></a></div></div><div class="foot-base"><span>انجمن علمی مهندسی کامپیوتر دانشگاه گیلان</span><a href="#about">بازگشت به بالا</a></div></div></footer>
|
||||
<nav class="mobile-nav" aria-label="ناوبری نمونه در موبایل"><a href="./d-logo-led-home.html">خانه</a><a href="./d-logo-led-home.html#events">رویدادها</a><a href="./d-logo-led-home.html#blog">بلاگ</a><a href="#about" aria-current="page">درباره</a></nav>
|
||||
</body>
|
||||
</html>
|
||||
52
tasks/concepts/d-logo-led-home.html
Normal file
@@ -0,0 +1,52 @@
|
||||
<!doctype html>
|
||||
<html lang="fa" dir="rtl">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#28626e">
|
||||
<link rel="icon" href="./assets/favicon.ico">
|
||||
<link rel="stylesheet" href="./d-logo-led.css">
|
||||
<title>خانه — طرح مبتنی بر نشان انجمن</title>
|
||||
</head>
|
||||
<body>
|
||||
<header class="site-head"><div class="wrap head-inner">
|
||||
<a class="brand" href="#home"><img src="./assets/favicon.ico" alt=""><span><strong>انجمن علمی مهندسی کامپیوتر</strong><small>دانشکدهی فنی و مهندسی شرق گیلان</small></span></a>
|
||||
<nav class="top-nav" aria-label="ناوبری اصلی"><a href="#home" aria-current="page">خانه</a><a href="#events">رویدادها</a><a href="#blog">بلاگ</a><a href="./d-logo-led-about.html">درباره انجمن</a></nav>
|
||||
<div class="head-action"><a class="button outline" href="https://east-guilan-ce.ir/auth">ورود / ثبتنام</a></div>
|
||||
</div></header>
|
||||
<main id="home">
|
||||
<section class="hero" aria-labelledby="hero-title"><div class="wrap hero-inner">
|
||||
<div><h1 id="hero-title">انجمن علمی کامپیوتر دانشگاه گیلان</h1><p>در دانشکدهی فنی و مهندسی شرق گیلان، برای یادگیری، برگزاری رویدادهای تخصصی و بهاشتراکگذاشتن تجربههای دانشجویی کنار هم هستیم. اینجا میتوانید با انجمن و برنامههای آن آشنا شوید.</p><div class="hero-actions"><a class="button primary" href="./d-logo-led-about.html">آشنایی با انجمن <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a><a class="button outline" href="#events">دیدن رویدادها</a></div></div>
|
||||
<div class="hero-visual" aria-hidden="true"><div class="gold-rule"></div><img src="./assets/favicon.ico" alt=""><span>یادگیری · رویداد · همکاری</span></div>
|
||||
</div></section>
|
||||
<section class="section" id="events" aria-labelledby="events-title"><div class="wrap">
|
||||
<div class="section-header"><div><h2 id="events-title">رویدادهای برگزیده</h2><p>نگاهی به برنامههای انجمن؛ وضعیت و زمان هر رویداد در صفحهی خودش مشخص میشود.</p></div><a class="section-link" href="https://east-guilan-ce.ir/events">همه رویدادها <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a></div>
|
||||
<div class="cards">
|
||||
<article class="card"><div class="card-image"><img src="./assets/event-docker.webp" alt="پوستر کارگاه آشنایی با داکر"><span class="badge image-badge">نمونه از آرشیو</span></div><div class="card-content"><h3>کارگاه آشنایی با داکر</h3><p>آشنایی عملی با مفاهیم کانتینر و ابزارهای توسعه.</p><div class="card-meta"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#calendar-days"/></svg><span>جزئیات و زمان در صفحه رویداد</span></div></div><div class="card-foot"><a href="https://east-guilan-ce.ir/events">مشاهده رویداد <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a></div></article>
|
||||
<article class="card"><div class="card-image"><img src="./assets/event-git.webp" alt="پوستر کارگاه گیت و گیتهاب"><span class="badge image-badge">نمونه از آرشیو</span></div><div class="card-content"><h3>کارگاه گیت و گیتهاب</h3><p>مروری بر همکاری تیمی، مدیریت نسخه و گردش کار توسعه.</p><div class="card-meta"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#calendar-days"/></svg><span>جزئیات و زمان در صفحه رویداد</span></div></div><div class="card-foot"><a href="https://east-guilan-ce.ir/events">مشاهده رویداد <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a></div></article>
|
||||
<article class="card"><div class="card-image"><img src="./assets/event-algorithms.webp" alt="پوستر دوره ساختمان داده و طراحی الگوریتم"><span class="badge image-badge">نمونه از آرشیو</span></div><div class="card-content"><h3>ساختمان داده و طراحی الگوریتم</h3><p>دورهای برای تمرین حل مسئله و مفاهیم پایهی الگوریتم.</p><div class="card-meta"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#calendar-days"/></svg><span>جزئیات و زمان در صفحه رویداد</span></div></div><div class="card-foot"><a href="https://east-guilan-ce.ir/events">مشاهده رویداد <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a></div></article>
|
||||
</div>
|
||||
</div></section>
|
||||
<section class="section alt" id="blog" aria-labelledby="blog-title"><div class="wrap">
|
||||
<div class="section-header"><div><h2 id="blog-title">از بلاگ انجمن</h2><p>نوشتهها و تجربههایی برای یادگیری فراتر از کلاس.</p></div><a class="section-link" href="https://east-guilan-ce.ir/blog">همه نوشتهها <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a></div>
|
||||
<div class="blog-grid"><article class="card blog-lead"><div class="editorial-art" aria-hidden="true"><small>انجمن علمی مهندسی کامپیوتر</small><strong class="art-word">{ code }</strong><small>خواندن · تجربه کردن · ساختن</small></div><div><div class="card-content"><span class="badge gold">یادگیری</span><h3>از کجا یادگیری برنامهنویسی را شروع کنیم؟</h3><p>یک مسیر ساده برای انتخاب موضوع، تمرین مستمر و ساختن پروژههای کوچک.</p></div><div class="card-foot"><a href="https://east-guilan-ce.ir/blog">خواندن مطلب <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a></div></div></article>
|
||||
<div class="blog-stack"><article class="card blog-row"><span class="blog-mark"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#book-open"/></svg></span><div><span class="badge">راهنما</span><h3>چطور برای یک پروژهی دانشجویی برنامهریزی کنیم؟</h3><p>از ایده تا نسخهی قابل ارائه</p><a class="section-link" href="https://east-guilan-ce.ir/blog">ادامه مطلب <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a></div></article><article class="card blog-row"><span class="blog-mark gold"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#newspaper"/></svg></span><div><span class="badge gold">تجربه</span><h3>یادگیری گروهی چه کمکی به رشد مهارتها میکند؟</h3><p>تمرین، بازخورد و همکاری</p><a class="section-link" href="https://east-guilan-ce.ir/blog">ادامه مطلب <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a></div></article></div></div>
|
||||
<p class="review-note">پوسترهای رویداد از رسانههای موجود پروژهاند. عنوانها و پوششهای بلاگ برای بررسی چیدمان نمایشی هستند؛ نسخهی نهایی، نوشتههای منتشرشده را از سامانه میخواند.</p>
|
||||
</div></section>
|
||||
<section class="cta" aria-labelledby="cta-title"><div class="wrap cta-inner"><div><h2 id="cta-title">در جریان برنامههای انجمن باشید</h2><p>رویدادها و نوشتههای تازه را دنبال کنید و اگر پیشنهادی برای همکاری دارید، با انجمن در ارتباط باشید.</p></div><div class="actions"><a class="button gold" href="https://east-guilan-ce.ir/events">دیدن رویدادها <svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#arrow-up-left"/></svg></a><a class="button outline" href="./d-logo-led-about.html#contact">ارتباط با انجمن</a></div></div></section>
|
||||
</main>
|
||||
<footer class="site-foot"><div class="wrap"><div class="foot-grid"><div><div class="foot-brand"><img src="./assets/favicon.ico" alt=""><span>انجمن علمی مهندسی کامپیوتر</span></div><p>دانشکدهی فنی و مهندسی شرق گیلان، دانشگاه گیلان. فضایی برای یادگیری، رویداد و همکاری دانشجویی.</p></div><div><h3>دسترسی سریع</h3><a href="#home">خانه</a><a href="./d-logo-led-about.html">درباره انجمن</a><a href="https://east-guilan-ce.ir/events">رویدادها</a><a href="https://east-guilan-ce.ir/blog">بلاگ</a></div><div><h3>همراه انجمن</h3><a href="https://east-guilan-ce.ir/auth">ورود / ثبتنام</a><a href="https://east-guilan-ce.ir/events">برنامهها</a><a href="./d-logo-led-about.html#contact">پیشنهاد همکاری</a></div><div><h3>ارتباط</h3><a class="contact-link" href="mailto:eastguilanceassociation@gmail.com"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#mail"/></svg><span dir="ltr">eastguilanceassociation@gmail.com</span></a><a class="contact-link" href="https://t.me/guilancea"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#send"/></svg><span>تلگرام انجمن</span></a><a class="contact-link" href="https://instagram.com/guilance.ir"><svg class="icon" aria-hidden="true"><use href="./d-lucide-icons.svg#instagram"/></svg><span>اینستاگرام انجمن</span></a></div></div><div class="foot-base"><span>انجمن علمی مهندسی کامپیوتر دانشگاه گیلان</span><a href="#home">بازگشت به بالا</a></div></div></footer>
|
||||
<nav class="mobile-nav" aria-label="ناوبری نمونه در موبایل"><a href="#home" aria-current="page">خانه</a><a href="#events">رویدادها</a><a href="#blog">بلاگ</a><a href="./d-logo-led-about.html">درباره</a></nav>
|
||||
<script>
|
||||
function syncNav(){
|
||||
const current = location.hash === '#events' || location.hash === '#blog' ? location.hash : '#home';
|
||||
for (const link of document.querySelectorAll('.mobile-nav a[href^="#"],.top-nav a[href^="#"]')) {
|
||||
if (link.getAttribute('href') === current) link.setAttribute('aria-current','page');
|
||||
else link.removeAttribute('aria-current');
|
||||
}
|
||||
}
|
||||
addEventListener('hashchange',syncNav);
|
||||
syncNav();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
18
tasks/concepts/d-logo-led.css
Normal file
@@ -0,0 +1,18 @@
|
||||
@font-face{font-family:Vazirmatn;src:url('./assets/Vazirmatn-variable.woff2') format('woff2');font-display:swap}
|
||||
:root{--brand:#28626e;--brand-deep:#1c4c57;--gold:#f9e697;--charcoal:#313332;--ink:#22363a;--muted:#53686b;--line:#d9e5e4;--wash:#f3f8f7;--warm:#faf8f0;--white:#fff;--radius:16px}
|
||||
*{box-sizing:border-box}html{scroll-behavior:smooth}body{margin:0;color:var(--ink);background:var(--white);font:400 16px/1.8 Vazirmatn,Tahoma,sans-serif}a{color:inherit}button{font:inherit}a:focus-visible,button:focus-visible,summary:focus-visible{outline:3px solid var(--brand);outline-offset:3px}::selection{background:var(--gold);color:var(--charcoal)}.wrap{width:min(100% - 48px,1180px);margin-inline:auto}
|
||||
.site-head{position:sticky;top:0;z-index:20;background:#fffffff2;border-bottom:1px solid var(--line);backdrop-filter:blur(12px)}.head-inner{min-height:76px;display:flex;align-items:center;justify-content:space-between;gap:28px}.brand{display:flex;align-items:center;gap:11px;min-width:0;text-decoration:none}.brand img{width:44px;height:44px;object-fit:contain}.brand strong{display:block;font-weight:800;font-size:15px;line-height:1.45}.brand small{display:block;font-size:11px;color:var(--muted);line-height:1.5}.top-nav{display:flex;align-items:center;gap:5px}.top-nav a{font-size:14px;font-weight:650;color:var(--muted);padding:9px 14px;border-radius:10px;text-decoration:none}.top-nav a:hover,.top-nav a[aria-current=page]{color:var(--brand-deep);background:var(--wash)}.head-action{display:flex;align-items:center;gap:10px}
|
||||
.button{display:inline-flex;align-items:center;justify-content:center;gap:9px;min-height:44px;padding:9px 18px;border-radius:10px;border:1px solid transparent;text-decoration:none;font-size:14px;font-weight:750;line-height:1.45;white-space:nowrap;transition:background .18s,color .18s,border-color .18s,transform .18s}.button svg{width:17px;height:17px;flex:none}.button.primary{background:var(--brand);color:white}.button.primary:hover{background:var(--brand-deep)}.button.outline{border-color:#b8ceca;background:white;color:var(--brand-deep)}.button.outline:hover{background:var(--wash)}.button.ghost{color:var(--brand-deep)}.button.ghost:hover{background:var(--wash)}.button.gold{background:var(--gold);color:var(--charcoal)}.button.gold:hover{background:#ffeeb0}.button:active{transform:translateY(1px)}
|
||||
.icon{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;flex:none}.badge{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);border-radius:999px;padding:3px 11px;color:var(--brand-deep);background:var(--wash);font-size:12px;font-weight:700;line-height:1.65}.badge.gold{background:#fff8db;border-color:#efe2a7;color:#655019}.badge.neutral{color:var(--muted);background:white}
|
||||
.hero{background:linear-gradient(180deg,#f8fbfa 0%,white 100%);border-bottom:1px solid var(--line)}.hero-inner{display:grid;grid-template-columns:minmax(0,1.14fr) minmax(330px,.86fr);gap:clamp(35px,5vw,80px);align-items:center;min-height:496px;padding-block:62px}.hero h1{font-size:clamp(39px,4.2vw,62px);line-height:1.3;letter-spacing:-.025em;font-weight:850;margin:0 0 19px;max-width:15ch}.hero p{max-width:50ch;color:var(--muted);font-size:18px;line-height:1.95;margin:0 0 25px}.hero-actions{display:flex;gap:11px;flex-wrap:wrap}.hero-visual{position:relative;min-height:330px;border-radius:22px;background:var(--brand);display:grid;place-items:center;overflow:hidden}.hero-visual:before{content:"";position:absolute;inset:18px;border:1px solid #ffffff38;border-radius:14px}.hero-visual:after{content:"";position:absolute;left:-55px;bottom:-105px;width:270px;height:270px;border:1px solid #f9e69766;border-radius:50%}.hero-visual img{position:relative;z-index:1;width:190px;height:190px;object-fit:contain;filter:drop-shadow(0 17px 30px #102c3080)}.hero-visual span{position:absolute;right:30px;bottom:24px;color:#e8f4f2;font-size:13px;font-weight:650}.hero-visual .gold-rule{position:absolute;top:0;right:0;left:0;height:5px;background:var(--gold)}
|
||||
.section{padding-block:77px}.section.alt{background:var(--wash)}.section-header{display:flex;align-items:end;justify-content:space-between;gap:24px;margin-bottom:27px}.section-header h2{font-size:clamp(27px,2.7vw,38px);font-weight:800;line-height:1.4;margin:0}.section-header p{color:var(--muted);margin:6px 0 0;font-size:15px}.section-link{display:inline-flex;align-items:center;gap:6px;color:var(--brand-deep);font-size:14px;font-weight:750;text-decoration:none;white-space:nowrap}.section-link:hover{text-decoration:underline;text-underline-offset:5px}.section-link svg{width:17px;height:17px}
|
||||
.cards{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:18px}.card{min-width:0;overflow:hidden;background:white;border:1px solid var(--line);border-radius:var(--radius);display:flex;flex-direction:column;transition:transform .2s,border-color .2s}.card:hover{transform:translateY(-3px);border-color:#b6ceca}.card-image{position:relative;aspect-ratio:16/9;overflow:hidden;background:#e5eeeb}.card-image img{width:100%;height:100%;object-fit:cover;display:block}.card-image .image-badge{position:absolute;right:13px;top:13px;background:#fffef5ed;border-color:#fff;color:var(--ink)}.card-content{padding:19px 20px 0;flex:1}.card-content h3{font-size:18px;line-height:1.6;font-weight:800;margin:0 0 9px}.card-content p{font-size:14px;line-height:1.8;color:var(--muted);margin:0}.card-meta{display:flex;align-items:center;gap:8px;flex-wrap:wrap;color:var(--muted);font-size:12px;margin-top:15px}.card-meta svg{width:15px;height:15px}.card-foot{padding:17px 20px 19px}.card-foot a{display:inline-flex;align-items:center;gap:5px;color:var(--brand-deep);text-decoration:none;font-size:14px;font-weight:750}.card-foot a:hover{text-decoration:underline;text-underline-offset:4px}.card-foot svg{width:16px;height:16px}
|
||||
.blog-grid{display:grid;grid-template-columns:minmax(0,1.35fr) minmax(0,.9fr);gap:18px}.blog-lead{display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);min-height:320px}.editorial-art{min-height:220px;background:var(--brand-deep);color:var(--gold);padding:24px;display:flex;flex-direction:column;justify-content:space-between;position:relative;overflow:hidden}.editorial-art:after{content:"";position:absolute;width:230px;height:230px;border:1px solid #f9e69785;border-radius:50%;left:-85px;top:46px}.editorial-art .art-word{font-size:clamp(46px,5vw,74px);line-height:1;letter-spacing:-.04em;font-weight:900;direction:ltr;align-self:flex-end;opacity:.92}.editorial-art small{font-size:13px;color:#fff8d2;position:relative;z-index:1}.blog-lead .card-content{padding:28px 26px 0}.blog-lead .card-content h3{font-size:23px}.blog-stack{display:grid;gap:14px}.blog-row{display:flex;align-items:center;gap:17px;padding:21px;min-height:150px}.blog-row .blog-mark{width:76px;height:76px;border-radius:14px;display:grid;place-items:center;flex:none;background:#e8f2f0;color:var(--brand-deep)}.blog-row .blog-mark.gold{background:#fff6d1;color:#6b5716}.blog-row .blog-mark svg{width:30px;height:30px}.blog-row h3{font-size:17px;margin:7px 0 5px}.blog-row p{color:var(--muted);font-size:13px;margin:0}.blog-row .badge{font-size:11px;padding:1px 8px}
|
||||
.cta{background:var(--brand-deep);color:white;position:relative;overflow:hidden}.cta:before{content:"";position:absolute;width:410px;height:410px;border:1px solid #f9e6975e;border-radius:50%;left:-110px;top:-135px}.cta-inner{position:relative;display:flex;justify-content:space-between;align-items:center;gap:30px;padding-block:67px}.cta h2{font-size:clamp(27px,3vw,40px);line-height:1.4;margin:0 0 9px}.cta p{margin:0;color:#d0e2e0;max-width:60ch}.cta .actions{display:flex;gap:10px;flex-wrap:wrap}.cta .button.outline{background:transparent;border-color:#a5c6c6;color:white}.cta .button.outline:hover{background:#ffffff1a}
|
||||
.site-foot{background:var(--charcoal);color:#e9eeed;padding:55px 0 27px}.foot-grid{display:grid;grid-template-columns:1.55fr .8fr .8fr 1.15fr;gap:35px}.foot-brand{display:flex;align-items:center;gap:12px;font-size:17px;font-weight:750}.foot-brand img{width:48px;height:48px}.site-foot p{color:#c0cdcb;font-size:13px;line-height:1.9;max-width:37ch}.site-foot h3{margin:4px 0 14px;font-size:14px;color:white}.site-foot a{display:block;color:#d4dedc;text-decoration:none;font-size:13px;margin-bottom:9px;overflow-wrap:anywhere}.site-foot a:hover{text-decoration:underline;text-underline-offset:4px}.site-foot .contact-link{display:flex;align-items:start;gap:8px}.site-foot .contact-link svg{width:16px;height:16px;margin-top:4px}.foot-base{display:flex;align-items:center;justify-content:space-between;gap:15px;margin-top:39px;padding-top:19px;border-top:1px solid #ffffff30;color:#b7c5c2;font-size:12px}.foot-base a{margin:0}
|
||||
.about-hero{background:var(--wash);padding:85px 0 72px;border-bottom:1px solid var(--line)}.about-hero h1{font-size:clamp(38px,4.2vw,58px);line-height:1.3;margin:0 0 17px}.about-hero p{max-width:70ch;color:var(--muted);font-size:18px;margin:0 0 25px}.about-hero .full-name{border-right:3px solid var(--gold);padding-right:14px;font-size:14px;font-weight:650;color:var(--brand-deep)}.about-columns{display:grid;grid-template-columns:1.1fr .9fr;gap:65px;align-items:start}.about-columns h2{margin:0 0 16px;font-size:31px}.about-columns p{color:var(--muted);margin:0 0 15px}.about-points{display:grid;gap:12px}.about-point{display:flex;align-items:start;gap:13px;padding:15px 0;border-bottom:1px solid var(--line)}.about-point .icon-box{width:40px;height:40px;border-radius:10px;background:var(--wash);color:var(--brand-deep);display:grid;place-items:center;flex:none}.about-point strong{display:block;font-size:16px}.about-point span{font-size:13px;color:var(--muted)}.about-contact{background:var(--warm);border:1px solid #eae4cb;border-radius:var(--radius);padding:30px}.about-contact h2{margin:0 0 11px}.about-contact a{display:block;color:var(--brand-deep);overflow-wrap:anywhere;text-underline-offset:4px;margin:9px 0}.about-contact a[dir=ltr]{text-align:right}.faq details{border-bottom:1px solid var(--line);padding:18px 0}.faq summary{cursor:pointer;font-weight:700}.faq details p{color:var(--muted);margin:10px 0 0;max-width:70ch}
|
||||
.mobile-nav{display:none}.review-note{font-size:12px;color:var(--muted);margin:22px 0 0}#home,#events,#blog,#contact,#about{scroll-margin-top:88px}
|
||||
@media(max-width:1000px){.hero-inner{grid-template-columns:1fr .8fr}.cards{gap:12px}.blog-grid{grid-template-columns:1fr}.blog-stack{grid-template-columns:1fr 1fr}.foot-grid{grid-template-columns:1.4fr 1fr 1fr}.foot-grid>div:last-child{grid-column:1/-1}}
|
||||
@media(max-width:760px){.wrap{width:min(100% - 32px,1180px)}.head-inner{min-height:67px}.brand img{width:39px;height:39px}.brand small{display:none}.brand strong{font-size:14px}.top-nav,.head-action{display:none}.hero-inner{grid-template-columns:1fr;gap:28px;min-height:0;padding-block:54px 40px}.hero h1{font-size:clamp(36px,8vw,48px);max-width:18ch}.hero p{font-size:16px}.hero-visual{min-height:175px}.hero-visual img{width:108px;height:108px}.hero-visual span{font-size:11px;right:18px;bottom:12px}.hero-visual:after{width:160px;height:160px;bottom:-70px;left:-30px}.section{padding-block:56px}.section-header{align-items:start}.section-header h2{font-size:29px}.cards{grid-template-columns:1fr;gap:15px}.card-image{aspect-ratio:16/8.4}.blog-grid,.blog-stack{grid-template-columns:1fr}.blog-lead{grid-template-columns:1fr}.editorial-art{min-height:180px}.blog-row{min-height:130px}.cta-inner{display:block;padding-block:55px}.cta .actions{margin-top:22px}.foot-grid{grid-template-columns:1fr 1fr;gap:27px}.foot-grid>div:first-child,.foot-grid>div:last-child{grid-column:1/-1}.site-foot{padding-bottom:120px}.about-hero{padding:65px 0 55px}.about-columns{grid-template-columns:1fr;gap:28px}.mobile-nav{position:fixed;z-index:30;bottom:calc(12px + env(safe-area-inset-bottom));right:16px;left:16px;display:flex;justify-content:space-around;gap:3px;padding:7px;border:1px solid #cadbd8;border-radius:20px;background:#fffffff2;box-shadow:0 12px 34px #143e4640;backdrop-filter:blur(14px)}.mobile-nav a{flex:1;text-align:center;text-decoration:none;color:var(--muted);font-size:11px;font-weight:700;padding:8px 2px;border-radius:14px}.mobile-nav a[aria-current=page]{background:var(--brand);color:white}}
|
||||
@media(max-width:480px){.hero-actions,.cta .actions{flex-direction:column}.hero-actions .button,.cta .button{width:100%}.section-header{display:block}.section-link{margin-top:8px}.foot-grid{grid-template-columns:1fr 1fr}.foot-base{display:block}.foot-base a{margin-top:7px}}
|
||||
@media(prefers-reduced-motion:reduce){html{scroll-behavior:auto}.button,.card{transition:none}}
|
||||
12
tasks/concepts/d-lucide-icons.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">
|
||||
<symbol id="arrow-up-left" viewBox="0 0 24 24"><path d="M7 17V7h10"/><path d="M17 17 7 7"/></symbol>
|
||||
<symbol id="calendar-days" viewBox="0 0 24 24"><path d="M8 2v4"/><path d="M16 2v4"/><rect width="18" height="18" x="3" y="4" rx="2"/><path d="M3 10h18"/><path d="M8 14h.01"/><path d="M12 14h.01"/><path d="M16 14h.01"/><path d="M8 18h.01"/><path d="M12 18h.01"/><path d="M16 18h.01"/></symbol>
|
||||
<symbol id="book-open" viewBox="0 0 24 24"><path d="M12 7v14"/><path d="M3 18a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h5a4 4 0 0 1 4 4 4 4 0 0 1 4-4h5a1 1 0 0 1 1 1v13a1 1 0 0 1-1 1h-6a3 3 0 0 0-3 3 3 3 0 0 0-3-3z"/></symbol>
|
||||
<symbol id="mail" viewBox="0 0 24 24"><rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/></symbol>
|
||||
<symbol id="send" viewBox="0 0 24 24"><path d="M14.536 21.686a.5.5 0 0 0 .937-.024l6.5-19a.496.496 0 0 0-.635-.635l-19 6.5a.5.5 0 0 0-.024.937l7.93 3.18a2 2 0 0 1 1.112 1.11z"/><path d="m21.854 2.147-10.94 10.939"/></symbol>
|
||||
<symbol id="instagram" viewBox="0 0 24 24"><rect width="20" height="20" x="2" y="2" rx="5" ry="5"/><path d="M16 11.37A4 4 0 1 1 12.63 8 4 4 0 0 1 16 11.37z"/><line x1="17.5" x2="17.51" y1="6.5" y2="6.5"/></symbol>
|
||||
<symbol id="clock" viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16.5 12"/></symbol>
|
||||
<symbol id="users" viewBox="0 0 24 24"><path d="M18 21a8 8 0 0 0-16 0"/><circle cx="10" cy="8" r="5"/><path d="M22 20c0-3.37-2-6.5-4-8a5 5 0 0 0-.45-8.3"/></symbol>
|
||||
<symbol id="graduation-cap" viewBox="0 0 24 24"><path d="M21.42 10.922a1 1 0 0 0-.019-1.838L12.83 5.18a2 2 0 0 0-1.66 0L2.6 9.08a1 1 0 0 0 0 1.832l8.57 3.908a2 2 0 0 0 1.66 0z"/><path d="M22 10v6"/><path d="M6 12.5V16a6 3 0 0 0 12 0v-3.5"/></symbol>
|
||||
<symbol id="newspaper" viewBox="0 0 24 24"><path d="M4 22h16a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H8a2 2 0 0 0-2 2v16a2 2 0 0 1-2 2Zm0 0a2 2 0 0 1-2-2v-9c0-1.1.9-2 2-2h2"/><path d="M18 14h-8"/><path d="M15 18h-5"/><path d="M10 6h8v4h-8V6Z"/></symbol>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
73
tasks/content-inventory.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Bundle 0 public content inventory
|
||||
|
||||
Captured 2026-09-24 from the local frontend source and browser. This is a classification record, not an approved seed. `E` = editorial/site identity (future CMS), `D` = existing domain data, `U` = functional UI kept in code. Paths below are relative to `guilan-ace-frontend/`. Every public route is listed; repeated controls inherit the shared-shell row.
|
||||
|
||||
The [line-level source ledger](content-source-lines.csv) records all Persian-bearing, URL and image-reference lines in the static public-content files with an E/U classification and exact source text. Regenerate it with [the extraction script](build-content-line-ledger.ps1). Dynamic event/blog values are not hard-coded literals, so their domain ownership is mapped in the route table instead. Mixed lines are annotated in the ledger and must be split field by field in the T12 seed manifest.
|
||||
|
||||
## Route map
|
||||
|
||||
| Route | Source | E: future CMS | D: existing model/API | U: code-owned |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| `/` | `src/app/page.tsx`, `src/views/Home.tsx` | Identity, hero, three offering descriptions, closing invitation, page SEO and Organization JSON-LD | None today | Link destinations and action labels, layout |
|
||||
| `/about` | `src/app/about/page.tsx`, `src/views/AboutUs.tsx` | Identity, mission, values, affiliations, committees, FAQ answers, contact/address, page SEO and AboutPage JSON-LD | None today | FAQ interaction, external-link behavior |
|
||||
| `/events` | `src/app/events/page.tsx`, `src/views/Events.tsx` | Listing introduction and default SEO/site name | Event list, dates, prices, capacity, status, images and filters from events API | Search/filter labels, loading/empty/error text and controls; query-specific SEO wording |
|
||||
| `/events/[slug]` | `src/app/events/[slug]/page.tsx`, `src/views/EventDetail.tsx` | Shared identity only | Event title/body/poster, organizer, eligibility, registration dates/capacity, price, SEO and registration-success markdown from event API | Registration/payment actions, validation, state and error messages; Event JSON-LD structure |
|
||||
| `/events/[slug]/success` | `src/app/events/[slug]/success/page.tsx`, `src/views/EventFreeSuccessPage.tsx` | Shared identity only | Verified registration/ticket/event details from API | Confirmation, pending/failure states and metadata labels |
|
||||
| `/payments/result` | `src/app/payments/result/page.tsx`, `src/views/PaymentResult.tsx` | Shared identity only | Verified payment and event details from API | Callback outcome text, retry and status controls |
|
||||
| `/blog` | `src/app/blog/page.tsx`, `src/views/Blog.tsx` | Listing introduction and default SEO/site name | Banners, posts, categories, tags, authors and images from blog API | Search/filter/pagination, loading/empty/error text; query-specific SEO wording |
|
||||
| `/blog/[slug]` | `src/app/blog/[slug]/page.tsx` | Shared identity only | Post text, authors, media, metadata, comments/interactions from blog API | Reading controls, sharing, error/empty text and BlogPosting JSON-LD structure |
|
||||
| `/auth`, `/auth/google/callback` | `src/app/auth/**`, `src/views/Auth.tsx`, `src/views/GoogleAuthCallback.tsx` | Shared identity only | Account existence, OTP and authentication responses | Form labels, constraints, steps, errors, resend/callback states |
|
||||
| `/verify-email/[token]`, `/reset-password`, `/reset-password/[token]`, `/logout` | matching `src/app/**`, `src/views/**` | Shared identity only | Verification/reset result from auth API | Instructions, form labels, success/failure states |
|
||||
| `/profile` | `src/app/profile/page.tsx`, `src/views/Profile.tsx` | Shared identity only | User profile and notifications | Profile controls and validation |
|
||||
| `/admin/**` | `src/app/admin/**`, `src/views/Admin*.tsx` | Shared identity only | Events, users, blog and taxonomy records | Staff navigation, forms, authorization, errors and confirmations |
|
||||
| not found | `src/app/not-found.tsx` | Shared identity only | None | Error explanation and navigation |
|
||||
|
||||
## Shared shell and static source fields
|
||||
|
||||
| Stable group | Current source | Destination and notes |
|
||||
| --- | --- | --- |
|
||||
| `site.official_name`, `site.short_name`, `site.faculty_subline` | `src/components/Navbar.tsx:135-139`, `Footer.tsx:20`, `src/app/layout.tsx:20-27`; Home/About have more variants | E. Official name from `tasks/plan.md`; preserve the current header's short lockup and faculty subline as the refinement basis. Existing variants must be replaced together after cutover. |
|
||||
| `site.logo`, `site.logo_alt` | `public/favicon.ico`; Navbar, Footer, Home/About OG and JSON-LD | E. Preserve source logo; CMS media copy later. `favicon.ico` is the only association mark found in `public/`. |
|
||||
| `site.navigation` | `Navbar.tsx:143-145`, `MobileBottomNav.tsx:38-59`, `Footer.tsx:27-49` | E for public link label/order/visibility; U for route IDs, selected state, auth/profile actions, responsive behavior. No arbitrary external route can bypass URL validation. |
|
||||
| `site.footer_description`, `site.copyright` | `Footer.tsx:22-25,125` | E for descriptive copy and name; U for current year. |
|
||||
| `site.contacts`, `site.social_links`, `site.address` | `Footer.tsx:51-98`, `AboutUs.tsx:117-136,315-344`, `src/app/page.tsx:39-43` | E. User selected About-page contact values on 2026-09-24. Footer and JSON-LD conflicts are listed below. Keep route-level links functional. |
|
||||
| `site.seal` | `public/enamad.png`, `Footer.tsx:103-118` | E for approved seal image/destination; verify legal ownership and destination before moving into CMS. |
|
||||
| `site.seo_defaults` | `src/app/layout.tsx:20-27`; site name repeated in events/blog/event/post metadata | E for title/description/OG identity; U for canonical URL construction, search `noindex`, schema structure. |
|
||||
| `home.hero` | `Home.tsx:9-11,47-51` | E: title and paragraph. |
|
||||
| `home.offering_events`, `home.offering_articles`, `home.offering_community` | `Home.tsx:68-101` | E: headings, subtitles, paragraphs; U: links to existing routes. These are editorial claims, not new domain entities. |
|
||||
| `home.join` | `Home.tsx:106-122` | E: heading and explanatory paragraph; U: signup action/route. |
|
||||
| `home.seo` | `src/app/page.tsx:5-48`, `Home.tsx:13-43` | E: title, description, OG image, organization name/description/contact; U: canonical and JSON-LD field structure. Two SEO implementations currently duplicate values. |
|
||||
| `about.intro`, `about.mission`, `about.values` | `AboutUs.tsx:46-55,163-200` | E. Intro count claims need evidence before publication. |
|
||||
| `about.affiliations` | `AboutUs.tsx:58-99,234-283` | E if association relationship is confirmed. Names, establishment years, focus areas and links require owner review; do not seed as verified facts merely because code contains them. |
|
||||
| `about.committees` | `AboutUs.tsx:100-113,289-302` | E. Committee existence and descriptions require owner review. |
|
||||
| `about.faq` | `AboutUs.tsx:304-310` | E for questions/answers; U for `<details>` disclosure and registration route semantics. The student-ID assertion needs backend confirmation. |
|
||||
| `about.location`, `about.join` | `AboutUs.tsx:315-348` | E for address, postcode, telephone, map URL and invitation; U for mail/Telegram link actions. |
|
||||
| `about.seo` | `src/app/about/page.tsx:5-57`, `AboutUs.tsx:7-40,139-160` | E for title, description, keywords, OG image, identity and sameAs; U for canonical/schema structure. Duplicated client/server SEO values conflict. |
|
||||
| `events.intro`, `blog.intro` | `src/app/events/page.tsx:19-37`, `src/app/blog/page.tsx:24-42` | E for default listing title/description/OG image; U for search-specific title/description and robots behavior. |
|
||||
|
||||
Every image reference in the targeted static public shell is covered by `site.logo`, `site.seal`, or the external About map. Event posters, blog images, banners, avatars and user uploads stay with their existing domain records. There is no Home/About photography in the frontend repository. The owner's revised Home proposal adds featured event and post previews after the intro. Those previews are **D** content from existing APIs; only their section headings/intro/link labels and CTA are **E**. The existing three-offering copy remains in the legacy inventory for audit but is no longer a required Home section.
|
||||
|
||||
## Conflicts and decisions
|
||||
|
||||
| Field | Conflicting source values | Status |
|
||||
| --- | --- | --- |
|
||||
| Association name | Home says `انجمن علمی کامپیوتر دانشگاه گیلان`; Navbar says `انجمن علمی مهندسی کامپیوتر`; Footer says `انجمن علمی کامپیوتر گیلان`; About leads with plural `انجمنهای علمی کامپیوتر گیلان` | Plan supplies official full name. The current header's short name remains the refinement basis; legacy variants stay listed for migration review. |
|
||||
| Email | Home JSON-LD `admin@east-guilan-ce.ir`; Footer `info@east-guilan-ce.ir`; About `eastguilanceassociation@gmail.com` | User selected About-page contact on 2026-09-24. |
|
||||
| Telegram | Footer `t.me/guilance`; About primary contact `t.me/guilancea`; About structured data lists both | User selected `t.me/guilancea` on 2026-09-24. |
|
||||
| Instagram | Footer/About current association link is `instagram.com/guilance.ir`; About affiliate links include others | Current association link retained provisionally; affiliate links await relationship review. |
|
||||
| Other social | Footer links to a personal LinkedIn profile and generic `x.com` | Do not seed into association identity without owner confirmation. |
|
||||
| Statistics and dates | About says `۱۴۰۴`, `۱۰۰+`, `۱۰+`, `۲۰+`, while affiliation rows say `۱۳۹۲` and `۱۳۵۳` | Owner says repository facts are verified; map each value to its entity and as-of date before automatic publishing. Not needed in identity-first concepts. |
|
||||
| Address/hours | Footer has a broad faculty address; About adds Vajjargah, postcode, phone and response hours | User says in-repo contacts are verified; selected About page is source for contact details. Preserve exact legacy values in seed review. |
|
||||
| About association links | `AboutUs.tsx:67` has a leading quote in the Instagram URL | Treat as a source defect; no automatic link publication. |
|
||||
|
||||
## Asset ownership
|
||||
|
||||
| Asset | Current use | Owner/approval action |
|
||||
| --- | --- | --- |
|
||||
| `public/favicon.ico` | Navbar/Footer mark, browser favicon, OG and structured data | Current recognizable logo approved by user as repository asset. Need original vector/high-resolution master, license/source note, and CMS media copy before release. |
|
||||
| `public/enamad.png` | Footer trust seal | Existing site asset; verify seal account and permitted use before migrating. |
|
||||
| `src/app/fonts/Vazirmatn-variable.woff2` | All UI text | Code-owned font file; record license before redistributing in a new design bundle. |
|
||||
| `public/placeholder.svg` | Generic placeholder | Code-owned fallback, not editorial association imagery. |
|
||||
| Backend event/blog/gallery media | Dynamic listings/details | Existing domain data; ownership stays with those records. |
|
||||
|
||||
Source code was classified against local rendering at 390px and 1440px. The owner accepted the content boundary and exclusions in `bundle0-review.md` on 2026-09-26, closing Checkpoint A at inventory scope. Uncertain claims and URLs remain flagged for later seed review; no claim or URL is silently corrected here.
|
||||
209
tasks/content-source-lines.csv
Normal file
@@ -0,0 +1,209 @@
|
||||
"source","line","category","source_text","note"
|
||||
"src/views/Home.tsx","10","CMS editorial","const heroTitle = ""انجمن علمی کامپیوتر دانشگاه گیلان"";",""
|
||||
"src/views/Home.tsx","12","CMS editorial","""با ما همراه شوید و در دنیای مهندسی/علوم کامپیوتر و فناوری پیشرفت کنید. رویدادها، محتوای آموزشی و جامعهای پویا برای رشد شما فراهم است."";",""
|
||||
"src/views/Home.tsx","15","code-owned UI","""@context"": ""https://schema.org"",","Schema structure or vocabulary; referenced identity values remain editorial."
|
||||
"src/views/Home.tsx","18","CMS editorial","url: ""https://east-guilan-ce.ir"",",""
|
||||
"src/views/Home.tsx","19","CMS editorial","sameAs: [""https://east-guilan-ce.ir/blog"", ""https://east-guilan-ce.ir/events""],",""
|
||||
"src/views/Home.tsx","21","CMS editorial","logo: ""https://east-guilan-ce.ir/favicon.ico"",",""
|
||||
"src/views/Home.tsx","39","CMS editorial","<meta property=""og:url"" content=""https://east-guilan-ce.ir"" />",""
|
||||
"src/views/Home.tsx","40","CMS editorial","<meta property=""og:image"" content=""https://east-guilan-ce.ir/favicon.ico"" />",""
|
||||
"src/views/Home.tsx","54","code-owned UI","<Button size=""lg"" aria-label=""مشاهده رویدادهای انجمن"">",""
|
||||
"src/views/Home.tsx","55","code-owned UI","مشاهده رویدادها",""
|
||||
"src/views/Home.tsx","59","code-owned UI","<Button size=""lg"" variant=""outline"" aria-label=""مطالعه مقالات آموزشی"">",""
|
||||
"src/views/Home.tsx","60","code-owned UI","خواندن مقالات",""
|
||||
"src/views/Home.tsx","70","CMS editorial","درباره انجمن",""
|
||||
"src/views/Home.tsx","75","CMS editorial","<CardTitle>رویدادهای تخصصی</CardTitle>",""
|
||||
"src/views/Home.tsx","76","CMS editorial","<CardDescription>برگزاری کارگاهها، سمینارها و نشستهای علمی</CardDescription>",""
|
||||
"src/views/Home.tsx","80","CMS editorial","با شرکت در رویدادهای ما، دانش و مهارتهای خود را در کنار اساتید و متخصصان ارتقا دهید.",""
|
||||
"src/views/Home.tsx","87","CMS editorial","<CardTitle>مقالات آموزشی</CardTitle>",""
|
||||
"src/views/Home.tsx","88","CMS editorial","<CardDescription>دسترسی به مطالب آموزشی و پژوهشی باکیفیت</CardDescription>",""
|
||||
"src/views/Home.tsx","92","CMS editorial","تازهترین مقالات تخصصی در حوزههای مختلف علوم کامپیوتر برای یادگیری و توسعه فردی.",""
|
||||
"src/views/Home.tsx","99","CMS editorial","<CardTitle>جامعه فعال</CardTitle>",""
|
||||
"src/views/Home.tsx","100","CMS editorial","<CardDescription>ارتباط با دانشجویان و اساتید علاقهمند به فناوری</CardDescription>",""
|
||||
"src/views/Home.tsx","104","CMS editorial","به جامعهای پویا بپیوندید و از فرصتهای همکاری، شبکهسازی و رشد شخصی بهرهمند شوید.",""
|
||||
"src/views/Home.tsx","115","CMS editorial","آماده عضویت هستید؟",""
|
||||
"src/views/Home.tsx","118","CMS editorial","همین حالا به جمع ما بپیوندید و از برنامهها و فرصتهای یادگیری انجمن علمی کامپیوتر دانشگاه گیلان استفاده کنید.",""
|
||||
"src/views/Home.tsx","121","code-owned UI","<Button size=""lg"" aria-label=""ثبت نام در انجمن علمی کامپیوتر"">",""
|
||||
"src/views/Home.tsx","122","code-owned UI","ثبتنام کنید",""
|
||||
"src/views/AboutUs.tsx","6","CMS editorial","// ------ دادههای قابل تنظیم ------",""
|
||||
"src/views/AboutUs.tsx","7","CMS editorial","const SITE_URL = 'https://east-guilan-ce.ir';",""
|
||||
"src/views/AboutUs.tsx","8","CMS editorial","const SITE_NAME_FA = 'انجمن علمی کامپیوتر شرق گیلان';",""
|
||||
"src/views/AboutUs.tsx","10","CMS editorial","const ABOUT_TITLE = `درباره ما | ${SITE_NAME_FA}`;",""
|
||||
"src/views/AboutUs.tsx","12","CMS editorial","'آشنایی با تاریخچه، مأموریتها و دستاوردهای انجمن علمی کامپیوتر شرق گیلان و راههای مشارکت دانشجویان در برنامههای انجمن.';",""
|
||||
"src/views/AboutUs.tsx","14","CMS editorial","'انجمن علمی کامپیوتر شرق گیلان, انجمن علمی مهندسی کامپیوتر دانشگاه گیلان، انجمن علمی علوم کامپیوتر، انجمن علمی شرق گیلان، انجمن علمی مهندسی کامپیوتر شرق گیلان، دانشکده فنی و مهندسی شرق گیلان، انجمن علمی کامپیوتر, فعالیتهای دانشجویی, انجمنهای علمی ایران, رویدادهای فناوری، برنامه نویسی، انجمن علمی دانشجویی، دانشگاه گیلان، فنی شرق';",""
|
||||
"src/views/AboutUs.tsx","17","code-owned UI","'@context': 'https://schema.org',","Schema structure or vocabulary; referenced identity values remain editorial."
|
||||
"src/views/AboutUs.tsx","26","CMS editorial","logo: `${SITE_URL}/favicon.ico`,",""
|
||||
"src/views/AboutUs.tsx","28","CMS editorial","'https://instagram.com/guilance.ir',",""
|
||||
"src/views/AboutUs.tsx","29","CMS editorial","'https://t.me/guilance',",""
|
||||
"src/views/AboutUs.tsx","30","CMS editorial","'https://t.me/guilancea'",""
|
||||
"src/views/AboutUs.tsx","46","CMS editorial","title: 'انجمنهای علمی کامپیوتر گیلان', // تیتر کلی",""
|
||||
"src/views/AboutUs.tsx","48","CMS editorial","'پیوند دانشگاه و صنعت با برگزاری رویدادها، کارگاهها و نشستهای تخصصی — با محوریت رشد مهارتهای فنی و مسیرهای شغلی.',",""
|
||||
"src/views/AboutUs.tsx","49","CMS editorial","foundedYear: '۱۴۰۴',",""
|
||||
"src/views/AboutUs.tsx","50","CMS editorial","membersApprox: '۱۰۰+',",""
|
||||
"src/views/AboutUs.tsx","51","CMS editorial","eventsCount: '۱۰+',",""
|
||||
"src/views/AboutUs.tsx","52","CMS editorial","volunteersCount: '۲۰+',",""
|
||||
"src/views/AboutUs.tsx","55","CMS editorial","// اگر چند انجمن زیرمجموعه دارید، اینجا معرفی کنید",""
|
||||
"src/views/AboutUs.tsx","58","CMS editorial","name: 'انجمن علمی مهندسی کامپیوتر دانشکدهی فنی شرق',",""
|
||||
"src/views/AboutUs.tsx","59","CMS editorial","university: 'دانشگاه گیلان',",""
|
||||
"src/views/AboutUs.tsx","60","CMS editorial","city: 'رودسر',",""
|
||||
"src/views/AboutUs.tsx","61","CMS editorial","foundedYear: '۱۳۹۲',",""
|
||||
"src/views/AboutUs.tsx","63","CMS editorial","'برگزاری رویدادهای آموزشی و صنعتی، منتورینگ دانشجویی، و اتصال دانشجویان به فرصتهای شغلی و پژوهشی.',",""
|
||||
"src/views/AboutUs.tsx","64","CMS editorial","focusAreas: ['مهندسی نرمافزار', 'هوش مصنوعی و داده', 'طراحی محصول', 'DevOps/امنیت'],",""
|
||||
"src/views/AboutUs.tsx","66","CMS editorial","website: 'https://east-guilan-ce.ir',",""
|
||||
"src/views/AboutUs.tsx","67","CMS editorial","instagram: '""https://instagram.com/guilance.ir',",""
|
||||
"src/views/AboutUs.tsx","68","CMS editorial","telegram: 'https://t.me/guilance',",""
|
||||
"src/views/AboutUs.tsx","73","CMS editorial","name: 'انجمن علمی مهندسی کامپیوتر دانشکدهی فنی',",""
|
||||
"src/views/AboutUs.tsx","74","CMS editorial","university: 'دانشگاه گیلان',",""
|
||||
"src/views/AboutUs.tsx","75","CMS editorial","city: 'رشت',",""
|
||||
"src/views/AboutUs.tsx","76","CMS editorial","foundedYear: '۱۳۵۳',",""
|
||||
"src/views/AboutUs.tsx","77","CMS editorial","about: 'برگزاری رویدادهای آموزشی و صنعتی، منتورینگ دانشجویی، و اتصال دانشجویان به فرصتهای شغلی و پژوهشی.',",""
|
||||
"src/views/AboutUs.tsx","78","CMS editorial","focusAreas: ['مهندسی نرمافزار', 'هوش مصنوعی و داده', 'DevOps'],",""
|
||||
"src/views/AboutUs.tsx","80","CMS editorial","instagram: 'https://instagram.com/ce.guilan',",""
|
||||
"src/views/AboutUs.tsx","81","CMS editorial","telegram: 'https://t.me/CSAOEF',",""
|
||||
"src/views/AboutUs.tsx","86","CMS editorial","name: 'انجمن علمی علوم کامپیوتر دانشکدهی علومپایه',",""
|
||||
"src/views/AboutUs.tsx","87","CMS editorial","university: 'دانشگاه گیلان',",""
|
||||
"src/views/AboutUs.tsx","88","CMS editorial","city: 'رشت',",""
|
||||
"src/views/AboutUs.tsx","89","CMS editorial","foundedYear: '۱۳۵۳',",""
|
||||
"src/views/AboutUs.tsx","90","CMS editorial","about: 'برگزاری رویدادهای آموزشی و صنعتی، منتورینگ دانشجویی، و اتصال دانشجویان به فرصتهای شغلی و پژوهشی.',",""
|
||||
"src/views/AboutUs.tsx","91","CMS editorial","focusAreas: ['امنیت', 'سیستمعامل', 'سختافزار'],",""
|
||||
"src/views/AboutUs.tsx","93","CMS editorial","instagram: 'https://instagram.com/csguilan',",""
|
||||
"src/views/AboutUs.tsx","94","CMS editorial","telegram: 'https://t.me/guilanCS',",""
|
||||
"src/views/AboutUs.tsx","99","CMS editorial","// کمیتهها/گروههای کاری",""
|
||||
"src/views/AboutUs.tsx","102","CMS editorial","title: 'کمیته آموزش',",""
|
||||
"src/views/AboutUs.tsx","103","CMS editorial","desc: 'برنامهریزی و اجرای دورهها و کارگاههای مهارتی، هماهنگی با مدرسین و طراحی مسیرهای یادگیری.'",""
|
||||
"src/views/AboutUs.tsx","106","CMS editorial","title: 'کمیته صنعت و اشتغال',",""
|
||||
"src/views/AboutUs.tsx","107","CMS editorial","desc: 'تعامل با شرکتها، دعوت از متخصصان صنعت، و شبکهسازی برای فرصتهای کارآموزی و استخدام.'",""
|
||||
"src/views/AboutUs.tsx","110","CMS editorial","title: 'کمیته محتوای دیجیتال',",""
|
||||
"src/views/AboutUs.tsx","111","CMS editorial","desc: 'تولید محتوای آموزشی، خبرنامه، مدیریت شبکههای اجتماعی و پوشش رسانهای رویدادها.'",""
|
||||
"src/views/AboutUs.tsx","115","CMS editorial","// راههای ارتباطی اصلی صفحه",""
|
||||
"src/views/AboutUs.tsx","118","CMS editorial","label: 'ایمیل',",""
|
||||
"src/views/AboutUs.tsx","123","CMS editorial","label: 'تلگرام',",""
|
||||
"src/views/AboutUs.tsx","125","CMS editorial","href: 'https://t.me/guilancea',",""
|
||||
"src/views/AboutUs.tsx","128","CMS editorial","label: 'اینستاگرام',",""
|
||||
"src/views/AboutUs.tsx","130","CMS editorial","href: 'https://instagram.com/guilance.ir',",""
|
||||
"src/views/AboutUs.tsx","133","CMS editorial","label: 'وبسایت',",""
|
||||
"src/views/AboutUs.tsx","135","CMS editorial","href: 'https://east-guilan-ce.ir',",""
|
||||
"src/views/AboutUs.tsx","153","CMS editorial","<meta property=""og:image"" content={`${SITE_URL}/favicon.ico`} />",""
|
||||
"src/views/AboutUs.tsx","158","CMS editorial","<meta name=""twitter:image"" content={`${SITE_URL}/favicon.ico`} />",""
|
||||
"src/views/AboutUs.tsx","168","CMS editorial","{/* آمار کوتاه */}",""
|
||||
"src/views/AboutUs.tsx","170","CMS editorial","<Stat label=""سال تأسیس"" value={ORG.foundedYear} />",""
|
||||
"src/views/AboutUs.tsx","171","CMS editorial","<Stat label=""اعضا"" value={ORG.membersApprox} />",""
|
||||
"src/views/AboutUs.tsx","172","CMS editorial","<Stat label=""رویدادها"" value={ORG.eventsCount} />",""
|
||||
"src/views/AboutUs.tsx","173","CMS editorial","<Stat label=""داوطلبان"" value={ORG.volunteersCount} />",""
|
||||
"src/views/AboutUs.tsx","178","CMS editorial","{/* درباره ما */}",""
|
||||
"src/views/AboutUs.tsx","183","CMS editorial","<CardHeader title=""ماموریت ما"" subtitle=""چرا اینجا هستیم؟"" />",""
|
||||
"src/views/AboutUs.tsx","186","CMS editorial","توانمندسازی دانشجویان با مهارتهای موردنیاز صنعت، ایجاد شبکههای حرفهای و فراهمکردن مسیرهای یادگیری",""
|
||||
"src/views/AboutUs.tsx","187","CMS editorial","پروژهمحور؛ از معرفی نقشها و مسیرهای شغلی تا تمرین مهارتهای نرم و فنی.",""
|
||||
"src/views/AboutUs.tsx","193","CMS editorial","<CardHeader title=""ارزشهای ما"" subtitle=""چه چیزهایی برایمان مهم است؟"" />",""
|
||||
"src/views/AboutUs.tsx","195","CMS editorial","<li className=""rounded-xl border p-3"">یادگیری پیوسته و اشتراک دانش</li>",""
|
||||
"src/views/AboutUs.tsx","196","CMS editorial","<li className=""rounded-xl border p-3"">کیفیت، شفافیت و مسئولیتپذیری</li>",""
|
||||
"src/views/AboutUs.tsx","197","CMS editorial","<li className=""rounded-xl border p-3"">فرصت برابر برای مشارکت</li>",""
|
||||
"src/views/AboutUs.tsx","198","CMS editorial","<li className=""rounded-xl border p-3"">ارتباط مؤثر با صنعت و جامعه</li>",""
|
||||
"src/views/AboutUs.tsx","203","CMS editorial","{/* تماس سریع */}",""
|
||||
"src/views/AboutUs.tsx","206","CMS editorial","<CardHeader title=""راههای ارتباطی"" subtitle=""با ما در ارتباط باشید"" />",""
|
||||
"src/views/AboutUs.tsx","224","CMS editorial","<CardHeader title=""ساعات پاسخگویی"" subtitle=""پشتیبانی داوطلبانه"" />",""
|
||||
"src/views/AboutUs.tsx","226","CMS editorial","<p>روزهای شنبه تا چهارشنبه، ساعت ۱۰ تا ۱۸</p>",""
|
||||
"src/views/AboutUs.tsx","227","CMS editorial","<p className=""mt-2"">پاسخها توسط تیم داوطلبان انجام میشود.</p>",""
|
||||
"src/views/AboutUs.tsx","234","CMS editorial","{/* انجمنها */}",""
|
||||
"src/views/AboutUs.tsx","237","CMS editorial","<h2 className=""text-2xl font-bold text-foreground"">انجمنها</h2>",""
|
||||
"src/views/AboutUs.tsx","238","CMS editorial","<p className=""mt-2 text-sm text-muted-foreground"">اطلاعات انجمنهای زیرمجموعه/همکار</p>",""
|
||||
"src/views/AboutUs.tsx","249","CMS editorial","{a.foundedYear && `• تأسیس: ${a.foundedYear}`}",""
|
||||
"src/views/AboutUs.tsx","267","CMS editorial","<a className=""rounded-xl border p-3 hover:bg-muted/50"" href={a.links.website} target=""_blank"" rel=""noreferrer"">وبسایت</a>",""
|
||||
"src/views/AboutUs.tsx","270","CMS editorial","<a className=""rounded-xl border p-3 hover:bg-muted/50"" href={a.links.instagram} target=""_blank"" rel=""noreferrer"">اینستاگرام</a>",""
|
||||
"src/views/AboutUs.tsx","273","CMS editorial","<a className=""rounded-xl border p-3 hover:bg-muted/50"" href={a.links.telegram} target=""_blank"" rel=""noreferrer"">تلگرام</a>",""
|
||||
"src/views/AboutUs.tsx","276","CMS editorial","<a className=""rounded-xl border p-3 hover:bg-muted/50"" href={`mailto:${a.links.email}`}>ایمیل</a>",""
|
||||
"src/views/AboutUs.tsx","286","CMS editorial","{/* کمیتهها */}",""
|
||||
"src/views/AboutUs.tsx","288","CMS editorial","<h2 className=""text-2xl font-bold text-foreground"">کمیتهها و گروههای کاری</h2>",""
|
||||
"src/views/AboutUs.tsx","301","CMS editorial","{/* پرسشهای متداول */}",""
|
||||
"src/views/AboutUs.tsx","304","CMS editorial","<h2 className=""text-2xl font-bold text-foreground"">پرسشهای متداول</h2>",""
|
||||
"src/views/AboutUs.tsx","306","CMS editorial","<FAQ q=""چطور در رویدادها شرکت کنم؟"" a=""برای ثبتنام در رویدادها ابتدا باید حسابکاربری با کددانشجویی خود ایجاد کنید و سپس از طریق صفحهی ثبتنام در رویداد موردنظرتان شرکت کنید :)"" />",""
|
||||
"src/views/AboutUs.tsx","307","CMS editorial","<FAQ q=""آیا امکان همکاری انجمنها/شرکتها هم وجود دارد؟"" a=""بله، ما همیشه آمادهی همکاری با سازمانها و انجمنهای مختلف دانشگاهها جهت توانمندسازی دانشجویان با مهارتهای موردنیاز صنعت و ایجاد شبکههای حرفهای هستیم."" />",""
|
||||
"src/views/AboutUs.tsx","308","CMS editorial","<FAQ q=""برای سخنرانی/منتورینگ به چه چیزهایی نیاز است؟"" a=""رزومه کوتاه، موضوع پیشنهادی و زمانهای دسترسپذیرتان را ارسال کنید تا هماهنگ کنیم."" />",""
|
||||
"src/views/AboutUs.tsx","313","CMS editorial","{/* نقشه و آدرس اختیاری */}",""
|
||||
"src/views/AboutUs.tsx","315","CMS editorial","<h2 className=""text-2xl font-bold text-foreground"">نشانی دانشکده</h2>",""
|
||||
"src/views/AboutUs.tsx","319","CMS editorial","<p>آدرس: گیلان، رودسر، واجارگاه، دانشکدهی فنی و مهندسی شرق گیلان</p>",""
|
||||
"src/views/AboutUs.tsx","320","CMS editorial","<p>کدپستی: ۴۴۹۱۸۹۸۵۶۶</p>",""
|
||||
"src/views/AboutUs.tsx","321","CMS editorial","<p>تلفن: ۰۱۳-۴۲۶۸۸۴۴۷</p>",""
|
||||
"src/views/AboutUs.tsx","322","CMS editorial","<p className=""mt-3"">برای هماهنگی حضوری از قبل پیام بدهید.</p>",""
|
||||
"src/views/AboutUs.tsx","327","CMS editorial","src=""https://maps.google.com/maps?q=37.06285,50.42324&hl=fa&z=16&output=embed""",""
|
||||
"src/views/AboutUs.tsx","339","CMS editorial","<h3 className=""text-xl md:text-2xl font-bold text-foreground"">مایل به همکاری هستید؟</h3>",""
|
||||
"src/views/AboutUs.tsx","340","CMS editorial","<p className=""mt-2 text-sm text-muted-foreground"">برای مشارکت داوطلبانه، سخنرانی، اسپانسری یا همکاری صنعتی به ما پیام دهید.</p>",""
|
||||
"src/views/AboutUs.tsx","342","CMS editorial","<a href=""mailto:eastguilanceassociation@gmail.com"" className=""rounded-xl border px-5 py-2 text-sm hover:bg-muted/50"">ایجاد ارتباط</a>",""
|
||||
"src/views/AboutUs.tsx","343","CMS editorial","<a href=""https://t.me/guilancea"" target=""_blank"" rel=""noreferrer"" className=""rounded-xl bg-primary px-5 py-2 text-sm text-primary-foreground"">",""
|
||||
"src/views/AboutUs.tsx","344","CMS editorial","پیام در تلگرام",""
|
||||
"src/views/AboutUs.tsx","354","CMS editorial","// --------- اجزای کوچک ---------",""
|
||||
"src/components/Navbar.tsx","54","code-owned UI","<Button className=""rounded-full px-5"">ورود / ثبتنام</Button>",""
|
||||
"src/components/Navbar.tsx","66","code-owned UI","aria-label=""منوی حساب کاربری""",""
|
||||
"src/components/Navbar.tsx","83","code-owned UI","{[user?.first_name, user?.last_name].filter(Boolean).join("" "") || user?.username || ""حساب کاربری""}",""
|
||||
"src/components/Navbar.tsx","88","code-owned UI","مشاهده پروفایل",""
|
||||
"src/components/Navbar.tsx","94","code-owned UI","تغییر یا بازیابی رمز",""
|
||||
"src/components/Navbar.tsx","101","code-owned UI","داشبورد مدیریت",""
|
||||
"src/components/Navbar.tsx","109","code-owned UI","خروج از حساب",""
|
||||
"src/components/Navbar.tsx","130","CMS editorial","<img src=""/favicon.ico"" alt=""لوگوی انجمن"" className=""h-10 w-10 object-contain"" />",""
|
||||
"src/components/Navbar.tsx","134","CMS editorial","انجمن علمی مهندسی کامپیوتر",""
|
||||
"src/components/Navbar.tsx","137","CMS editorial","دانشکدهی فنی و مهندسی شرق گیلان",""
|
||||
"src/components/Navbar.tsx","143","CMS editorial","<NavItem to=""/"">خانه</NavItem>",""
|
||||
"src/components/Navbar.tsx","144","CMS editorial","<NavItem to=""/blog"">بلاگ</NavItem>",""
|
||||
"src/components/Navbar.tsx","145","CMS editorial","<NavItem to=""/events"">رویدادها</NavItem>",""
|
||||
"src/components/Footer.tsx","19","CMS editorial","<img src=""/favicon.ico"" alt=""لوگوی انجمن"" className=""h-9 w-9 rounded"" />",""
|
||||
"src/components/Footer.tsx","20","CMS editorial","<span className=""text-xl font-bold"">انجمن علمی کامپیوتر گیلان</span>",""
|
||||
"src/components/Footer.tsx","23","CMS editorial","ترویج علم کامپیوتر، برگزاری رویدادهای تخصصی، تقویت شبکهی دانشجویی و پیوند با صنعت.",""
|
||||
"src/components/Footer.tsx","28","CMS editorial","<h4 className=""mb-3 text-base font-semibold"">لینکهای مفید</h4>",""
|
||||
"src/components/Footer.tsx","32","CMS editorial","خانه",""
|
||||
"src/components/Footer.tsx","37","CMS editorial","رویدادها",""
|
||||
"src/components/Footer.tsx","42","CMS editorial","بلاگ",""
|
||||
"src/components/Footer.tsx","47","CMS editorial","دربارهی انجمن",""
|
||||
"src/components/Footer.tsx","54","CMS editorial","<h4 className=""mb-3 text-base font-semibold"">ارتباط با ما</h4>",""
|
||||
"src/components/Footer.tsx","56","CMS editorial","<li>ایمیل: info@east-guilan-ce.ir</li>",""
|
||||
"src/components/Footer.tsx","57","CMS editorial","<li>آدرس: دانشگاه گیلان، دانشکدهی فنی و مهندسی شرق گیلان</li>",""
|
||||
"src/components/Footer.tsx","62","CMS editorial","href=""https://Instagram.com/guilance.ir""",""
|
||||
"src/components/Footer.tsx","67","CMS editorial","<Button variant=""outline"" size=""icon"" className=""h-9 w-9"" aria-label=""اینستاگرام"">",""
|
||||
"src/components/Footer.tsx","72","CMS editorial","href=""https://t.me/guilance""",""
|
||||
"src/components/Footer.tsx","77","CMS editorial","<Button variant=""outline"" size=""icon"" className=""h-9 w-9"" aria-label=""تلگرام"">",""
|
||||
"src/components/Footer.tsx","82","CMS editorial","href=""https://www.linkedin.com/in/amiirkhl/""",""
|
||||
"src/components/Footer.tsx","87","CMS editorial","<Button variant=""outline"" size=""icon"" className=""h-9 w-9"" aria-label=""لینکدین"">",""
|
||||
"src/components/Footer.tsx","91","CMS editorial","<a href=""https://x.com"" target=""_blank"" rel=""noreferrer"" className=""inline-flex"">",""
|
||||
"src/components/Footer.tsx","96","CMS editorial","aria-label=""ایکس (توییتر)""",""
|
||||
"src/components/Footer.tsx","106","CMS editorial","href=""https://trustseal.enamad.ir/?id=649977&Code=m0wWM1DFYqd4fLEnjyMU3o2pupfuqDVW""",""
|
||||
"src/components/Footer.tsx","112","CMS editorial","src=""/enamad.png""",""
|
||||
"src/components/Footer.tsx","114","CMS editorial","alt=""نماد اعتماد الکترونیکی""",""
|
||||
"src/components/Footer.tsx","126","CMS editorial","<div>© {year} انجمن علمی کامپیوتر گیلان - تمامی حقوق محفوظ است.</div>",""
|
||||
"src/components/MobileBottomNav.tsx","37","CMS editorial","label: ""خانه"",",""
|
||||
"src/components/MobileBottomNav.tsx","44","CMS editorial","label: ""رویدادها"",",""
|
||||
"src/components/MobileBottomNav.tsx","51","CMS editorial","label: ""بلاگ"",",""
|
||||
"src/components/MobileBottomNav.tsx","58","code-owned UI","label: isAuthenticated ? ""پروفایل"" : ""حساب"",",""
|
||||
"src/app/page.tsx","5","CMS editorial","const title = ""انجمن علمی کامپیوتر دانشگاه گیلان"";",""
|
||||
"src/app/page.tsx","7","CMS editorial","""با ما همراه شوید و در دنیای مهندسی و علوم کامپیوتر پیشرفت کنید. رویدادها، محتوای آموزشی و جامعهای پویا برای رشد شما فراهم است."";",""
|
||||
"src/app/page.tsx","17","CMS editorial","siteName: ""انجمن علمی کامپیوتر شرق گیلان"",",""
|
||||
"src/app/page.tsx","19","CMS editorial","images: [`${siteUrl}/favicon.ico`],",""
|
||||
"src/app/page.tsx","26","CMS editorial","images: [`${siteUrl}/favicon.ico`],",""
|
||||
"src/app/page.tsx","31","code-owned UI","""@context"": ""https://schema.org"",","Schema structure or vocabulary; referenced identity values remain editorial."
|
||||
"src/app/page.tsx","37","CMS editorial","logo: `${siteUrl}/favicon.ico`,",""
|
||||
"src/app/about/page.tsx","5","CMS editorial","const title = ""درباره ما | انجمن علمی کامپیوتر شرق گیلان"";",""
|
||||
"src/app/about/page.tsx","7","CMS editorial","""آشنایی با تاریخچه، مأموریتها و دستاوردهای انجمن علمی کامپیوتر شرق گیلان و راههای مشارکت دانشجویان در برنامههای انجمن."";",""
|
||||
"src/app/about/page.tsx","13","CMS editorial","""انجمن علمی کامپیوتر شرق گیلان"",",""
|
||||
"src/app/about/page.tsx","14","CMS editorial","""دانشگاه گیلان"",",""
|
||||
"src/app/about/page.tsx","15","CMS editorial","""انجمن علمی دانشجویی"",",""
|
||||
"src/app/about/page.tsx","16","CMS editorial","""رویدادهای فناوری"",",""
|
||||
"src/app/about/page.tsx","23","CMS editorial","siteName: ""انجمن علمی کامپیوتر شرق گیلان"",",""
|
||||
"src/app/about/page.tsx","25","CMS editorial","images: [`${siteUrl}/favicon.ico`],",""
|
||||
"src/app/about/page.tsx","32","CMS editorial","images: [`${siteUrl}/favicon.ico`],",""
|
||||
"src/app/about/page.tsx","37","code-owned UI","""@context"": ""https://schema.org"",","Schema structure or vocabulary; referenced identity values remain editorial."
|
||||
"src/app/about/page.tsx","44","CMS editorial","name: ""انجمن علمی کامپیوتر شرق گیلان"",",""
|
||||
"src/app/about/page.tsx","46","CMS editorial","logo: `${siteUrl}/favicon.ico`,",""
|
||||
"src/app/about/page.tsx","48","CMS editorial","""https://instagram.com/guilance.ir"",",""
|
||||
"src/app/about/page.tsx","49","CMS editorial","""https://t.me/guilance"",",""
|
||||
"src/app/about/page.tsx","50","CMS editorial","""https://t.me/guilancea"",",""
|
||||
"src/app/layout.tsx","23","CMS editorial","default: ""انجمن علمی کامپیوتر شرق گیلان"",",""
|
||||
"src/app/layout.tsx","24","CMS editorial","template: ""%s | انجمن علمی کامپیوتر شرق گیلان"",",""
|
||||
"src/app/layout.tsx","27","CMS editorial","""انجمن علمی کامپیوتر شرق گیلان، برگزارکننده رویدادها، کارگاهها و محتوای آموزشی برای دانشجویان و علاقهمندان فناوری."",",""
|
||||
"src/app/events/page.tsx","19","code-owned UI","const title = search ? `جستوجوی رویدادها: ${search}` : ""رویدادها"";","Query-specific title/description or search behavior; default listing introduction remains editorial."
|
||||
"src/app/events/page.tsx","21","code-owned UI","? `نتایج جستوجوی رویدادها برای ${search} در انجمن علمی کامپیوتر شرق گیلان.`","Query-specific title/description or search behavior; default listing introduction remains editorial."
|
||||
"src/app/events/page.tsx","22","CMS editorial",": ""رویدادهای جاری و گذشته انجمن علمی کامپیوتر شرق گیلان، شامل کارگاهها، مسابقات و برنامههای آموزشی."";",""
|
||||
"src/app/events/page.tsx","33","CMS editorial","siteName: ""انجمن علمی کامپیوتر شرق گیلان"",",""
|
||||
"src/app/events/page.tsx","35","CMS editorial","images: [`${siteUrl}/favicon.ico`],",""
|
||||
"src/app/blog/page.tsx","24","code-owned UI","const title = search ? `جستوجوی وبلاگ: ${search}` : ""وبلاگ"";","Query-specific title/description or search behavior; default listing introduction remains editorial."
|
||||
"src/app/blog/page.tsx","26","code-owned UI","? `نتایج جستوجوی مقالات برای ${search} در وبلاگ انجمن علمی کامپیوتر شرق گیلان.`","Query-specific title/description or search behavior; default listing introduction remains editorial."
|
||||
"src/app/blog/page.tsx","27","CMS editorial",": ""مقالات، نوشتهها و محتوای آموزشی انجمن علمی کامپیوتر شرق گیلان."";",""
|
||||
"src/app/blog/page.tsx","38","CMS editorial","siteName: ""انجمن علمی کامپیوتر شرق گیلان"",",""
|
||||
"src/app/blog/page.tsx","40","CMS editorial","images: [`${siteUrl}/favicon.ico`],",""
|
||||
|
1
tasks/evidence/2026-09-24/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
__pycache__/
|
||||
BIN
tasks/evidence/2026-09-24/about-1440.png
Normal file
|
After Width: | Height: | Size: 315 KiB |
BIN
tasks/evidence/2026-09-24/about-320.png
Normal file
|
After Width: | Height: | Size: 312 KiB |
BIN
tasks/evidence/2026-09-24/about-390.png
Normal file
|
After Width: | Height: | Size: 328 KiB |
BIN
tasks/evidence/2026-09-24/about-768.png
Normal file
|
After Width: | Height: | Size: 305 KiB |
BIN
tasks/evidence/2026-09-24/admin-390.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
tasks/evidence/2026-09-24/auth-390.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
1701
tasks/evidence/2026-09-24/backend-focused-tests.txt
Normal file
BIN
tasks/evidence/2026-09-24/blog-390.png
Normal file
|
After Width: | Height: | Size: 236 KiB |
BIN
tasks/evidence/2026-09-24/events-390.png
Normal file
|
After Width: | Height: | Size: 72 KiB |
BIN
tasks/evidence/2026-09-24/home-1440.png
Normal file
|
After Width: | Height: | Size: 172 KiB |
BIN
tasks/evidence/2026-09-24/home-320.png
Normal file
|
After Width: | Height: | Size: 161 KiB |
BIN
tasks/evidence/2026-09-24/home-390.png
Normal file
|
After Width: | Height: | Size: 157 KiB |
BIN
tasks/evidence/2026-09-24/home-768.png
Normal file
|
After Width: | Height: | Size: 168 KiB |
29
tasks/evidence/2026-09-24/local-replay.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# Bundle 0 isolated local replay
|
||||
|
||||
Replayed 2026-09-24 to 2026-09-25 with a local Redis container on `127.0.0.1:6379`, Django `config.settings.test` using the ignored SQLite `db.test.sqlite3`, Next.js dev server, and Playwright Chromium. No production database, payment gateway, SMS provider, or email service was used. The disposable data came from `create-local-baseline-fixtures.py`; the payment and OTP scripts in this directory mock external side effects.
|
||||
|
||||
## Replayed paths
|
||||
|
||||
| Journey | Happy path observed | Failure path observed |
|
||||
| --- | --- | --- |
|
||||
| Authentication | Browser: existing mobile `09198000111` → password login → profile. Isolated API: new mobile OTP verification → signup → OTP login → password reset → login with new password. | Browser stayed in auth for invalid mobile/wrong password. Isolated API rejected invalid OTP request, incorrect code, duplicate registration, and the old password after reset. |
|
||||
| Events | Browser: published events list and detail; signed-in free registration reached the success page with confirmed status and event details. | Full event had a disabled registration button and zero remaining capacity. Anonymous free registration redirected to auth. |
|
||||
| Payment | Mocked Django client: gateway request produced a pending payment; successful callback marked payment paid and registration confirmed. Browser payment result rendered the paid event, amount, and reference ID. | Mocked gateway outage returned 502 without a persisted payment; canceled callback redirected to failed state; duplicate paid attempt returned 400. Browser rendered the failed payment result. |
|
||||
| Blog | Browser opened the published fixture article with reading content, author, and comments area. Staff blog list showed the published article. | Missing article slug rendered the site's not-found view. |
|
||||
| Staff admin | Browser login as isolated staff; event list displayed fixture events and registration count. Editing the free-event title saved and the API returned the new value. At 390px the staff event list switched to cards and the menu exposed the blog route. | Empty required event title disabled Save. The earlier anonymous `/admin` replay redirected away. |
|
||||
|
||||
The staff-edited fixture title was restored after verification. These fixtures live only in the ignored SQLite test file. The mocked payment success is not proof of a live gateway checkout, and the mocked OTP replay is not proof of SMS delivery or the Google OAuth path.
|
||||
|
||||
## Backend test baseline (historical run)
|
||||
|
||||
- `python manage.py check --settings=config.settings.test`: passed, zero issues.
|
||||
- `python manage.py test apps.events.tests.integration.test_events --settings=config.settings.test --noinput`: **25 passed**.
|
||||
- `python manage.py test apps.users.tests apps.events.tests apps.payments.tests --settings=config.settings.test --noinput`: **148 tests ran, 89 errors**. Raw output: [backend-focused-tests.txt](backend-focused-tests.txt). These errors were recorded as stale tests at the time. The current pytest rerun and results are in [test-rerun-2026-09-26.md](test-rerun-2026-09-26.md) and supersede this as the current suite status. No application business logic was changed to make the historical expectations pass.
|
||||
|
||||
## Runtime observations to carry forward
|
||||
|
||||
- Event detail's second-by-second countdown produced a server/client text mismatch and React hydration warning in the dev browser.
|
||||
- The signed-in browser requested `/api/notifications/stream-token` and received HTTP 405.
|
||||
- The old footer still shows the unselected contact variants. The selected About-page contacts are recorded in the content inventory and design contract for cutover.
|
||||
|
||||
The browser replay covers the principal local auth, event, payment-result, blog-reading, and staff-edit journeys with a failure case in each. Full SMS transport, Google OAuth, and a live payment gateway need separate integration work. This file records the starting behavior; it is not approval of those external integrations or of the CMS/API contract.
|
||||
12
tasks/evidence/2026-09-24/test-rerun-2026-09-26.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# Backend test rerun — 2026-09-26
|
||||
|
||||
Reran the repository's documented pytest suites from `guilan-ace-backend` with `.venv/Scripts/python.exe` and `config.settings.test` from `pytest.ini`.
|
||||
|
||||
| Command | Result |
|
||||
| --- | --- |
|
||||
| `.venv/Scripts/python.exe -m pytest -m unit` | 79 passed, 158 deselected, 3.80s |
|
||||
| `.venv/Scripts/python.exe -m pytest -m integration` | 158 passed, 79 deselected, 17.58s |
|
||||
|
||||
Together, all 237 collected pytest tests passed. The integration run included users, events, payments, notifications, blog, and other app integration tests. No external SMS delivery, Google OAuth provider, or live payment gateway was exercised.
|
||||
|
||||
The previous `manage.py test apps.users.tests apps.events.tests apps.payments.tests --settings=config.settings.test` command discovered zero tests because the current suites are organized and marked for pytest. Its `NO TESTS RAN` result is not a passing test result; use the pytest commands above.
|
||||
70
tasks/plan.md
Normal file
@@ -0,0 +1,70 @@
|
||||
# Guilan ACE redesign and public-content CMS: implementation plan
|
||||
|
||||
Status: Bundle 0 discovery and design contract approved by the owner on 2026-09-26; product implementation has not started. This plan is shared across the frontend, backend, and deployment repositories. The executable checklist is [todo.md](todo.md). Later implementation checkpoints and production rollout approvals remain required.
|
||||
|
||||
## Outcome and boundaries
|
||||
|
||||
Redesign the public experience in this order: Home/About, authentication, events and registration, blog, then the staff-facing frontend admin. Build a Django-admin-managed content system for public editorial copy, shared identity/logo, approved images, navigation, footer/contact information, and page SEO. Editors may change bounded text in predefined Home/About sections and reorder or hide optional About sections; the owner-specified Home sequence remains fixed, and new layouts are developer work. Existing event, registration, payment, cancellation, and eligibility rules remain unchanged in the first release. Functional form labels, validation messages, permission-sensitive controls, and the staff-admin interface text remain versioned application code. Transactional email/SMS/in-app templates are a separate later phase.
|
||||
|
||||
The official association name is `انجمن علمی مهندسی کامپیوتر دانشگاه گیلان (دانشکدهی فنی و مهندسی شرق گیلان)`. Use it in official metadata and About identity; the owner approved the shorter header lockup, `انجمن علمی مهندسی کامپیوتر` with a faculty subline, in the logo-led visual direction. Preserve the recognizable existing logo until an approved replacement is supplied.
|
||||
|
||||
## Existing-system facts that shape the work
|
||||
|
||||
- Frontend: Next.js 15, React 18, Tailwind 3, Radix UI, Persian RTL. Main surfaces include `src/views/Home.tsx`, `AboutUs.tsx`, `Auth.tsx`, `Events.tsx`, `EventDetail.tsx`, `Blog.tsx`, and `Admin*` views. Home and About currently contain public copy, contact data, and SEO strings in code; About contains contradictory names, email/social links, and unverified numeric claims. Shared navigation/footer also contain static public content.
|
||||
- Backend: Django 5, Ninja API, PostgreSQL, Django Unfold admin, Redis/Celery. Events, blog, gallery, and announcements already have domain models; there is no public-page CMS. Event-specific success copy is already data-backed, and should not be duplicated in the new CMS.
|
||||
- Deployment: Docker Compose runs the backend without an automatic `migrate` step; PostgreSQL and Django media are backed up. Schema migration, media staging, and content seeding therefore need explicit, separately verified release operations.
|
||||
- The blog was recently redesigned. Audit it for coherence and accessibility before replacing components wholesale.
|
||||
|
||||
## Decisions and proposed contracts
|
||||
|
||||
1. **Public-only content boundary.** Inventory every public route and classify strings as editorial/brand/SEO, domain data, or functional UI. Only the first category moves into the CMS. Homepage/About sections use a finite, documented type registry; no arbitrary HTML or general-purpose page builder.
|
||||
2. **Publishing workflow.** Designated staff can save drafts and preview; a narrower publisher group can publish/restore a previous published revision; superusers retain full access. Public API returns only published revisions. A draft may never become visible through a cache, preview URL, or guessed identifier. Audit who changed and published each revision.
|
||||
3. **Typed content model.** A site identity/settings record holds official/short names, logo, approved contact/social links, footer, and SEO defaults. Public editorial pages have stable slugs (at least `home`, `about`, `events`, and `blog`, plus any other editorial surface found in inventory). Home/About have ordered/visible sections with approved section types; simpler route introductions and SEO use bounded fields. Prefer typed fields/validated schemas over opaque, unbounded JSON. Individual events/blog posts stay in their domain tables.
|
||||
4. **Public and preview APIs.** Add a versioned, read-only published-content endpoint with an explicit response schema and safe cache policy. Draft preview requires staff authentication and is `no-store`; publish should invalidate or quickly expire public caches. Frontend renders public content server-side where SEO needs it, with safe fallback during rollout; no permanent duplicate copy after cutover.
|
||||
5. **Images and copy.** Logos/photos are managed files with alt text, dimensions/size limits, and a documented license/approval source. Prefer actual association/campus/event material, strong Persian typography, and clear information architecture over generic gradients, fabricated stats, decorative 3D, or motion that impedes tasks. Respect `prefers-reduced-motion` and keep admin interaction mostly motion-free.
|
||||
6. **Incremental release.** Ship backend CMS and verified seed first behind the existing frontend. Switch Home/About via a reversible feature flag. Then release auth, events, blog, and frontend admin as independently testable slices. New CMS data must not alter registration or payment state.
|
||||
|
||||
## Design process and approval gates
|
||||
|
||||
Use the repository-local Impeccable workflow, **visual review before UI implementation**: review `PRODUCT.md`, compare the current Home/About with real mobile/desktop captures, and use the owner-provided references to refine the current site. Three earlier concepts were rejected by the owner on 2026-09-25; the owner approved the logo-led Home and About visual direction on 2026-09-25. Home follows the owner's order: introduction, featured events, featured blog posts, CTA, footer. Shadcn/ui and Lucide are the implementation component system; the logo supplies teal, pale gold, and charcoal. The approved direction is recorded in `DESIGN.md`; the owner approved the T05 CMS/API contract and Checkpoints A/B on 2026-09-26. Start with existing approved logo, event posters, and other available real assets; new association photography is not a dependency. Run the installed Impeccable hooks during design work; after cloning, developers must trust/enable project hooks in Codex (`/hooks`) for their environment. Hooks are review aids, not substitutes for human design and accessibility review.
|
||||
|
||||
Design acceptance is based on actual tasks and content: a student finds the next event, understands eligibility/cost, completes registration, and sees a trustworthy success/payment state; a visitor learns who the association is; a staff editor publishes safely. Test Persian line breaks, mixed-script dates/numbers, 320–1440px widths, keyboard navigation, contrast, reduced motion, loading/empty/error states, and realistic long content.
|
||||
|
||||
## Phase order and effort
|
||||
|
||||
Effort is person-days for one experienced full-time developer/designer with normal stakeholder review. It includes design, implementation, tests, and rework; it is not elapsed time from merely installing skills. Overlap is possible after the CMS contract is approved, but the requested release priority is preserved.
|
||||
|
||||
| Phase | Scope | Effort | Exit gate |
|
||||
| --- | --- | ---: | --- |
|
||||
| 0. Discovery and design contract | Content inventory, facts/assets, flow map, Impeccable concept approval | 4–5 d | Approved content matrix, Home/About direction, baseline captures |
|
||||
| 1. CMS foundation and migration | Model, roles, admin editing, published/preview APIs, seed and dry-run | 9–12 d | Published content matches approved inventory; no draft leak |
|
||||
| 2. Home/About and shared shell | Design system, pages, header/footer, responsive/SEO integration | 9–12 d | Edited content appears correctly at all target widths |
|
||||
| 3. Authentication | Login/signup/verification/reset/Google callback states, recovery UX | 5–7 d | Existing auth behavior preserved, end-to-end tests pass |
|
||||
| 4. Events and registration | Listing, details, free/paid journeys, payment/success states | 9–12 d | Existing event rules preserved and state matrix passes |
|
||||
| 5. Blog | Cohesion audit, selective refinement, reading/discovery | 4–6 d | Current blog capabilities and URLs preserved |
|
||||
| 6. Frontend staff admin | Navigation, tables/forms, role clarity, mobile usability | 7–10 d | Essential staff tasks work at phone and desktop widths |
|
||||
| 7. Release hardening | Cross-browser/a11y/performance regression, deploy rehearsal, launch | 4–7 d | Backup, smoke, rollback, and owner sign-off |
|
||||
| **Total** | | **51–71 person-days** | **About 11–15 calendar weeks for one full-time person**, allowing reviews |
|
||||
|
||||
Two developers with clear frontend/backend ownership could shorten calendar time, but not person-days proportionally; shared design/API decisions and release testing remain on the critical path. Unapproved assets, conflicting content facts, or additional business-rule changes increase the estimate.
|
||||
|
||||
## Production content migration and cutover
|
||||
|
||||
1. **Freeze and inventory.** Capture the current production pages and code strings into a versioned content manifest with stable keys, source path, intended destination field, exact text, image path/checksum, and an approval status. Separate existing domain data from static editorial text. Mark disputed contacts, affiliated-association claims, counts, and old links for owner approval; do not silently “correct” them.
|
||||
2. **Build schema and tests.** Add additive CMS tables and role permissions. Do not drop old columns or repurpose event/blog data. Test migration on an anonymized production-sized database copy, including repeated deploy/seed runs and Unicode/RTL content.
|
||||
3. **Prepare assets.** Stage approved logo and other source images into backed-up Django media, record checksums, dimensions, alt text, and target CMS records. Never reference a frontend build path as a permanent media source. Unapproved imagery may remain absent; layout must handle it.
|
||||
4. **Dry-run seed.** Provide a versioned, idempotent import command that prints create/update/skip/conflict counts and a field-level diff. It must refuse to overwrite any editor-modified content by default. Use stable keys and a seed version, log outcomes, and support a no-write validation mode. Seed approved snapshots as drafts first; publisher reviews and publishes. A Django data migration may create immutable baseline records, but media transfer and editorial approval remain explicit operations, not filesystem side effects inside a schema migration.
|
||||
5. **Production gate.** Take and verify fresh database/media backups. Deploy backend compatible with the old frontend, run `migrate` explicitly, stage media, run seed dry-run, review conflicts, then execute seed and validate API/draft permissions. This can occur before the UI cutover with no public visual change.
|
||||
6. **Switch and observe.** Deploy frontend with CMS reads behind a flag; compare rendered copy and SEO against approved manifest, test mobile/desktop and all key journeys, then switch Home/About. Monitor CMS API errors, missing media, cache staleness, and registration/payment signals before advancing to later slices.
|
||||
7. **Rollback.** For a frontend/content regression, disable CMS rendering or restore the previous frontend image and republish the prior content revision. Keep additive CMS tables and original content until the new path is stable. Database restore is a last-resort incident procedure because it can erase registrations/payments created after the backup; decide on it with an incident owner, never as the routine rollback.
|
||||
|
||||
## Verification and definition of done
|
||||
|
||||
Every task in `todo.md` has explicit acceptance and verification. At each checkpoint run backend focused tests and `python manage.py test --settings=config.settings.test`, frontend `npm run lint` and `npm run build`, then browser checks on desktop/mobile and reduced-motion/keyboard modes. Add automated tests for CMS permission, draft isolation, seeding idempotency, page content API, event/auth state-preservation, and critical browser journeys. Measure accessibility and route bundle/performance against a captured baseline rather than an invented target; budget regressions deliberately. Check Persian content with a human reviewer. A release is done only after stakeholder approval, backup restore rehearsal, documented rollback, and verified production smoke tests.
|
||||
|
||||
## Risks and decisions still requiring approval
|
||||
|
||||
- **Contacts and factual claims:** The owner selected the About-page email, Instagram, and Telegram entries on 2026-09-24. The other legacy variants remain in the inventory. Address, phone, statistics, and affiliated-association claims still need entity/currentness review before production seed publication.
|
||||
- **Approved imagery:** Existing recognizable logo and approved current assets are the baseline. Catalog their usage rights; do not generate substitute “association photos.”
|
||||
- **Editorial ownership:** Nominate actual staff and publisher accounts/group membership before rollout; document the review/restore procedure.
|
||||
- **Scope guard:** Transactional messaging templates and changes to event/payment business logic require a separately approved specification and estimate.
|
||||
32
tasks/product-review.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# Bundle 0 product truth and asset review
|
||||
|
||||
Reviewed 2026-09-24 against `guilan-ace-frontend/PRODUCT.md`, frontend source, `tasks/plan.md`, and owner replies in this task. This record separates product commitments from legacy page claims. It is the input to the visual concepts and the later seed manifest.
|
||||
|
||||
## Confirmed for concepts
|
||||
|
||||
- The site serves the computer engineering student association at the University of Guilan's East Guilan Faculty of Engineering. The plan's official name is `انجمن علمی مهندسی کامپیوتر دانشگاه گیلان (دانشکدهی فنی و مهندسی شرق گیلان)`.
|
||||
- The first Home/About viewport should explain the association before inviting event discovery. The user chose this priority on 2026-09-24.
|
||||
- Preserve the existing `public/favicon.ico` association mark. The user identified existing repository facts and assets as verified. Keep the current header's short name and faculty subline as the refinement basis; the full official name stays in About identity and metadata.
|
||||
- Use the About page's association contact set for new concepts: `eastguilanceassociation@gmail.com`, `https://t.me/guilancea`, and `https://instagram.com/guilance.ir`. The user chose About-page contacts over the Footer values on 2026-09-24.
|
||||
- Events, registration, payment, cancellation, eligibility, blog articles and post metadata remain existing backend data and rules. New CMS content controls public editorial context only.
|
||||
|
||||
## Files and provenance
|
||||
|
||||
| Asset | SHA-256 | Current use | Next approval/source action |
|
||||
| --- | --- | --- | --- |
|
||||
| `guilan-ace-frontend/public/favicon.ico` | `A5EA52EBC4DA83932457F495575BC6E397ACA324976D786C92EFC61D5A1172D8` | Association mark in navigation, footer and SEO | Find original master and record license/creator for CMS media transfer. |
|
||||
| `guilan-ace-frontend/public/enamad.png` | `1EE71330241EFA235F7CBACB62674BDC3465C4085DDC2322C5D6C34BADEC6864` | Existing footer trust seal | Verify trust-seal account and destination before treating it as editable content. |
|
||||
| `guilan-ace-frontend/src/app/fonts/Vazirmatn-variable.woff2` | See source file | Self-hosted Persian UI font | Retain as a code asset while checking its redistribution license. |
|
||||
|
||||
The concept files use a copy of the current favicon solely for portable review. No replacement logo or documentary campus photograph was generated. `public/placeholder.svg` is a generic fallback, not an association image. Dynamic event/blog images are owned by their existing records.
|
||||
|
||||
## Still pending before seed publication
|
||||
|
||||
| Claim | Evidence gap |
|
||||
| --- | --- |
|
||||
| About's `۱۴۰۴`, `۱۰۰+`, `۱۰+`, `۲۰+` statistics, association founding years `۱۳۹۲` and `۱۳۵۳` | The owner says repository facts are verified. The association each value describes and its as-of date still need mapping before an auditable seed. Keep the exact values in the inventory; the concepts do not need a statistics block. |
|
||||
| Three listed associations and their relationship to this organization | `AboutUs.tsx` mixes one East Guilan association with two Rasht associations and calls them subsidiaries/collaborators. A relationship label needs an owner decision. |
|
||||
| Committee roster, response hours, postal address, phone and map position | Present in About source and selected as contact source; confirm current operational ownership before production seeding. |
|
||||
| Personal LinkedIn URL, generic X URL, and trust seal | Existing Footer URLs are not proof that they are official association channels. Exclude from new identity until explicitly confirmed. |
|
||||
|
||||
The owner withdrew the Plan A selection and rejected the first current-derived comp on 2026-09-25. The owner then specified a content-rich Home order (intro, featured events, featured blog posts, CTA, footer), Shadcn/ui and Lucide components, and a palette based on the association logo. The new logo-led Home/About comps are pending review. The remaining claim-to-entity mappings and the CMS/API contract still need review before production seed publication and implementation.
|
||||
82
tasks/todo.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Redesign and CMS implementation checklist
|
||||
|
||||
This is an **implementation backlog**, with work-in-progress noted below and checkboxes reserved for accepted work. See [plan.md](plan.md) for scope, estimates, migration sequence, and release gates. `F`, `B`, and `D` mean frontend, backend, and deployment repository. Each item is intended to fit one focused session (S = 1–2 files; M = 3–5 files); split any item that grows larger. In addition to each item’s check, apply the definition of done: focused and regression tests, lint/build, runtime/browser check, security/rollback where relevant, and human review.
|
||||
|
||||
Bundle 0 started 2026-09-24 and was approved by the owner on 2026-09-26. Deliverables: [content inventory](content-inventory.md), [baseline](baseline-2026-09-24.md), [local journey replay](evidence/2026-09-24/local-replay.md), [product/asset review](product-review.md), [CMS/API contract](cms-api-contract-draft.md), backend [API schema](../../guilan-ace-backend/docs/content-api-schema-draft.md), and the approved Home/About visual direction linked from frontend `DESIGN.md`. The owner approved the [Home](concepts/d-logo-led-home.html) and [About](concepts/d-logo-led-about.html) direction on 2026-09-25, then approved the [Bundle 0 review](bundle0-review.md) on 2026-09-26, accepting the content boundary, recorded baseline, and CMS/API contract. T01–T05 and Checkpoints A/B are closed at discovery and contract scope. The current pytest suites pass all 237 tests; the earlier 89-error run is preserved as historical evidence. External SMS/OAuth/live-gateway checks, disputed seed claims, and production media/account assignments remain follow-up work in later gates. Bundle 1 has not started.
|
||||
|
||||
## 0. Discovery and design contract (4–5 person-days)
|
||||
|
||||
- [x] **T01 — Classify static public content (M; deps: none).** Files: F `src/views/*`, `src/components/Navbar.tsx`, `Footer.tsx`, `src/app/*`. Acceptance: every public route/string/image/SEO field is mapped to CMS editorial, existing domain data, or code-owned functional UI; conflicts and asset ownership are flagged. Verify: owner reviews the manifest against live desktop/mobile pages. Owner accepted the content boundary and exclusions in `bundle0-review.md` on 2026-09-26; uncertain claims remain excluded from the initial seed.
|
||||
- [x] **T02 — Capture flow and performance baseline (M; deps: none).** Files: D `tasks/` evidence, F test artifacts. Acceptance: route/state map covers auth, event registration/payment, blog, and staff admin; screenshots and bundle/accessibility baselines have dated device widths. Verify: manually replay each existing happy path and one failure path on staging/local. Owner accepted the recorded local baseline on 2026-09-26 with the historical test run and unexercised external paths documented; the current pytest suites passed on 2026-09-26 (see rerun record).
|
||||
- [x] **Checkpoint A (deps: T01–T02).** Content categories, current behavior, and baseline evidence reviewed; no business-rule changes inferred. Accepted 2026-09-26 with the limits documented in `bundle0-review.md`.
|
||||
- [x] **T03 — Review product truth and assets (S; deps: T01).** Files: F `PRODUCT.md`, asset inventory. Acceptance: initial product record is checked against source assets and owner input; logo sources are cataloged; conflicting contacts/statistics remain pending rather than guessed. Verify: owner signs off facts and supplies approved contact channels before production seed publication. Concept-scope sign-off: owner confirmed repository facts/assets and chose About-page contacts; claim-to-entity mapping remains a T12 seed gate.
|
||||
- [x] **T04 — Settle Home/About visual direction (M; deps: T03).** Files: F `DESIGN.md`, D static design artifacts. Acceptance: owner reviews the logo-led Home/About comps at phone and desktop widths using real approved assets; Home follows intro → featured events → featured blog posts → CTA → footer, and the component system maps to Shadcn/ui and Lucide. Verify: compare with current captures, owner references, product truth, accessibility needs, and real content lengths. Owner approved the Home and About design direction on 2026-09-25; final content, responsive behavior, and accessibility remain implementation checks.
|
||||
- [x] **T05 — Approve design and CMS/API contract (M; deps: T04, T01).** Files: F `DESIGN.md`, D architecture note, B API schema draft. Acceptance: owner accepts the logo-led direction and fixed Home content order; section types, field constraints, payloads, cache/preview behavior, and edit/publish roles are signed off. Verify: walk a draft→preview→publish→restore sequence and 320px/desktop layouts on paper. Design direction accepted 2026-09-25; owner approved the CMS/API decisions and documented paper walkthrough in `bundle0-review.md` on 2026-09-26.
|
||||
- [x] **Checkpoint B (deps: T03–T05).** Approved content contract and design direction recorded on 2026-09-26. This closes the discovery gate; later implementation and release gates still apply.
|
||||
|
||||
## 1. CMS foundation and migration (9–12 person-days)
|
||||
|
||||
- [ ] **T06 — Add site identity and page schema (M; deps: T05).** Files: B new content app models/migration/tests. Acceptance: one site identity, stable page slugs, ordered typed sections, image/alt and SEO fields exist with uniqueness/validation; migrations are additive. Verify: migration test and `python manage.py check` on a test database.
|
||||
- [ ] **T07 — Validate fields and media handling (M; deps: T06).** Files: B content validators/tests. Acceptance: URLs, section payloads, image type/size, alt text, and unsafe markup are constrained; absent optional media renders safely. Verify: invalid/oversize/malicious inputs rejected in focused tests.
|
||||
- [ ] **Checkpoint C (deps: T06–T07).** Schema and validation reviewed before permissions/API work.
|
||||
- [ ] **T08 — Implement draft, publish, and revision permissions (M; deps: T06).** Files: B content services/permissions/tests. Acceptance: staff draft, publisher publish/restore, superuser override, audit trail, and atomic published snapshot; unauthorized edits/publish fail. Verify: role-matrix and concurrent-publish tests.
|
||||
- [ ] **T09 — Configure Django admin editing workflow (M; deps: T07–T08).** Files: B content admin/forms/tests. Acceptance: editors can edit/reorder/hide only defined sections, see validation, preview draft, and identify published revision without raw JSON editing. Verify: hands-on staff/publisher Django admin walkthrough at desktop and phone widths.
|
||||
- [ ] **Checkpoint D (deps: T08–T09).** Draft cannot leak or publish by the wrong role.
|
||||
- [ ] **T10 — Expose public published-content API (M; deps: T08).** Files: B content Ninja router/schemas/tests, `config/api.py`. Acceptance: only published identity/pages appear; missing content has explicit behavior; response shape and cache headers are documented. Verify: anonymous API tests including unpublished-only data.
|
||||
- [ ] **T11 — Expose authenticated no-store preview (M; deps: T08, T10).** Files: B preview route/auth/tests. Acceptance: approved staff can preview exact draft, anonymous callers cannot, and response is uncached. Verify: permission/cache tests and a real preview URL walkthrough.
|
||||
- [ ] **Checkpoint E (deps: T10–T11).** API contract frozen for frontend integration.
|
||||
- [ ] **T12 — Produce versioned seed manifest (M; deps: T01, T06).** Files: B content seed data, D migration notes. Acceptance: stable keys, exact legacy text, source paths, media checksums, and owner-approval status documented; disputed contacts/counts are excluded from automatic publication. Verify: manifest diffed against current live pages/code and signed by content owner.
|
||||
- [ ] **T13 — Build idempotent dry-run seed command (M; deps: T12).** Files: B management command/tests. Acceptance: prints create/skip/conflict and field diffs, supports no-write mode, never overwrites editor changes by default, and seeds approved entries as drafts. Verify: run twice on a database copy; second run is no-op; altered content reports conflict.
|
||||
- [ ] **Checkpoint F (deps: T12–T13).** Seed and approval behavior demonstrated on staging-sized data before production use.
|
||||
- [ ] **T14 — Add frontend CMS adapter and cutover flag (M; deps: T10).** Files: F content fetch/types/flag tests. Acceptance: published content can be fetched server-side with typed fallback; flag defaults to legacy rendering until launch; preview is never cached publicly. Verify: integration tests with CMS available, unavailable, and stale response.
|
||||
|
||||
## 2. Home/About and shared public shell (9–12 person-days)
|
||||
|
||||
- [ ] **T15 — Establish approved visual tokens and shell (M; deps: T05, T14).** Files: F global styles, fonts, navigation/footer components. Acceptance: approved typography/colors/layout, responsive header/footer, and CMS identity/navigation/contact fields match comps; RTL/keyboard/reduced-motion work. Verify: screenshot comparison at 320/390/768/1440px and keyboard pass.
|
||||
- [ ] **T16 — Build CMS-driven Home editorial sections and domain previews (M; deps: T15).** Files: F Home view, section components, tests. Acceptance: hero/featured-section/CTA text comes from published CMS in the fixed owner-approved order; event and blog cards read existing domain APIs with truthful status, useful links, and sound empty/long layouts. Verify: editor text change appears on preview then public page only after publish; event/blog source changes update previews; visual review at all widths.
|
||||
- [ ] **Checkpoint G (deps: T15–T16).** Home concept fidelity and real content signed off before About.
|
||||
- [ ] **T17 — Build CMS-driven About sections (M; deps: T15).** Files: F About view, section components, tests. Acceptance: official identity, mission, committee/association facts, and contacts come from approved published data; unsupported claims are absent. Verify: compare rendered content to approved manifest and test visibility/reorder.
|
||||
- [ ] **T18 — Make page SEO/structured data content-driven (M; deps: T16–T17).** Files: F route metadata/SEO utilities/tests. Acceptance: canonical, title, description, OG image, and structured-data identity are consistent with published CMS and server-rendered HTML; no stale hardcoded names. Verify: inspect HTML/JSON-LD and link previews on staging.
|
||||
- [ ] **T19 — Finish Home/About interaction and accessibility pass (M; deps: T16–T18).** Files: F affected page/styles/tests. Acceptance: motion supports comprehension but does not block content, reduced-motion works, contrast/focus/read order and Persian line wraps pass. Verify: real browser desktop/mobile captures, keyboard, screen-reader spot check, and Impeccable critique against approved comp.
|
||||
- [ ] **Checkpoint H (deps: T17–T19).** Owner approves Home/About on staging; content editors can make and publish a visible change without developer help.
|
||||
|
||||
## 3. Authentication (5–7 person-days)
|
||||
|
||||
- [ ] **T20 — Simplify auth entry and navigation (M; deps: T15, T02).** Files: F Auth view/auth shell/tests. Acceptance: login/signup choice, intent, next step, and back path are clear on phone/desktop without changing backend auth rules. Verify: first-time student and returning-user walkthroughs.
|
||||
- [ ] **T21 — Clarify form, OTP, loading, and error states (M; deps: T20).** Files: F auth components/tests. Acceptance: each step has one clear action, input constraints and errors are accessible, resend/countdown are understandable, and retry does not lose valid input. Verify: keyboard, slow-network, invalid-input, and duplicate-submit tests.
|
||||
- [ ] **Checkpoint I (deps: T20–T21).** Core login/signup behavior unchanged and clear in RTL/mobile.
|
||||
- [ ] **T22 — Align recovery and verification screens (M; deps: T20).** Files: F reset/verify/callback views/tests. Acceptance: expired token, failed Google callback, success, and return-to-intent states follow same system; no dead end. Verify: browser tests for link/token variants.
|
||||
- [ ] **T23 — Auth regression gate (M; deps: T21–T22).** Files: F end-to-end tests, B focused auth tests if needed. Acceptance: login, signup, verification, reset, logout, and protected redirect pass with existing API semantics. Verify: full focused automated suite plus manual mobile smoke.
|
||||
|
||||
## 4. Events and registration (9–12 person-days)
|
||||
|
||||
- [ ] **T24 — Redesign event discovery (M; deps: T15, T02).** Files: F Events view/cards/tests. Acceptance: upcoming/past/full states, date/location/price, filters, and empty/error states are clear without changing query semantics; editorial page intro/SEO reads the published CMS record. Verify: fixture-based state matrix at phone/desktop widths and a CMS publish check.
|
||||
- [ ] **T25 — Redesign event detail and eligibility explanation (M; deps: T24).** Files: F EventDetail view/test. Acceptance: schedule, capacity/availability, prerequisites, organizer, and call to action match existing backend data and rules; no invented promise. Verify: compare UI against API fixtures for open/closed/full/free/paid cases.
|
||||
- [ ] **Checkpoint J (deps: T24–T25).** Student can decide whether an event is relevant before entering registration.
|
||||
- [ ] **T26 — Clarify registration forms and transitions (M; deps: T25).** Files: F event form/registration tests. Acceptance: field requirements, validation, duplicate/closed/full responses, and retry are legible; requests and eligibility rules unchanged. Verify: browser/API contract tests for every backend error/status.
|
||||
- [ ] **T27 — Clarify free, paid, and callback outcomes (M; deps: T26).** Files: F success/payment views/tests. Acceptance: pending, success, failure, canceled, and already-registered states show accurate next steps and do not imply payment when unconfirmed. Verify: callback replay and browser state tests against existing backend responses.
|
||||
- [ ] **T28 — Event regression gate (M; deps: T26–T27).** Files: F end-to-end tests, B existing event/payment tests. Acceptance: registration, capacity, payment, cancellation, eligibility, and notification-trigger semantics remain identical to baseline. Verify: automated state matrix and staging test event with no real charge/message side effect.
|
||||
- [ ] **Checkpoint K (deps: T26–T28).** Owner signs off registration/payment flow before broader release.
|
||||
|
||||
## 5. Blog (4–6 person-days)
|
||||
|
||||
- [ ] **T29 — Audit existing blog before editing (S; deps: T15, T02).** Files: F blog audit notes/tests. Acceptance: existing strengths and gaps in discovery, article typography, media, SEO, and interactions are recorded; no unnecessary rewrite. Verify: editorial and reader walkthrough on mobile/desktop.
|
||||
- [ ] **T30 — Apply selected blog refinements (M; deps: T29).** Files: F Blog/list/detail components/tests. Acceptance: visual system is coherent, article reading and navigation improve, existing URLs/actions/content remain intact; editorial listing intro/SEO reads the published CMS record. Verify: screenshot/keyboard review with long Persian article and code block plus a CMS publish check.
|
||||
- [ ] **T31 — Blog regression gate (M; deps: T30).** Files: F blog tests/SEO. Acceptance: listing, category/tag navigation, article render, share/interactions, and metadata still work. Verify: browser and API contract checks.
|
||||
|
||||
## 6. Frontend staff admin (7–10 person-days)
|
||||
|
||||
- [ ] **T32 — Map staff roles and mobile task priorities (M; deps: T02, T15).** Files: F admin IA/spec. Acceptance: top tasks for event manager, blog editor, publisher, and general staff are documented; access is not confused with visual hiding. Verify: role-based task walkthrough with actual members.
|
||||
- [ ] **T33 — Restructure admin navigation and overview (M; deps: T32).** Files: F AdminLayout/Dashboard/tests. Acceptance: navigation and summaries work at phone/tablet/desktop, with no off-screen controls or meaningless dashboard clutter. Verify: responsive screenshots and keyboard navigation.
|
||||
- [ ] **Checkpoint L (deps: T32–T33).** At least one staff member completes top tasks at 390px and desktop widths.
|
||||
- [ ] **T34 — Make tables, forms, and confirmations responsive (M; deps: T33).** Files: F admin event/user/blog shared patterns/tests. Acceptance: filters, bulk actions, destructive confirmations, and long forms remain visible and operable at 320px; dense data has a deliberate mobile pattern. Verify: real-device/viewport walkthrough of create/edit/search/confirm tasks.
|
||||
- [ ] **T35 — Expose roles and failure states clearly (M; deps: T34).** Files: F admin auth/empty/error components/tests. Acceptance: permission denial, save conflict, loading, empty, and server error states explain next action without exposing unauthorized actions. Verify: role matrix and forced-failure browser tests.
|
||||
- [ ] **T36 — Admin regression gate (M; deps: T34–T35).** Files: F admin browser tests, B permission tests if affected. Acceptance: event, user, blog, and metadata management still work for authorized users across target widths. Verify: staff UAT plus automated smoke.
|
||||
|
||||
## 7. Release hardening and production cutover (4–7 person-days)
|
||||
|
||||
- [ ] **T37 — Cross-site quality gate (M; deps: T19, T23, T28, T31, T36).** Files: F/B tests and D QA record. Acceptance: lint/build/tests pass, critical routes meet accessibility/SEO/performance budgets against baseline, no critical mobile/RTL defect remains. Verify: CI plus Chrome/Firefox/Safari-equivalent checks where available and reduced-motion/keyboard review.
|
||||
- [ ] **T38 — Rehearse migration, backup, and rollback (M; deps: T13, T37).** Files: D runbook/scripts, B seed command. Acceptance: staging clone has tested `migrate`, media stage, seed dry-run/apply, restore of published revision, frontend flag rollback, and verified backup recovery path. Verify: record commands, checksums, timings, and pass/fail evidence.
|
||||
- [ ] **Checkpoint M (deps: T37–T38).** Owner approves release checklist; production remains untouched until gate passes.
|
||||
- [ ] **T39 — Production CMS seed and phased cutover (M; deps: T38).** Files: D runbook/observability, production state. Acceptance: verified fresh backup, additive backend migration, approved assets/drafts, publisher approval, flagged frontend release, and smoke checks occur in order. Verify: compare public text/SEO to approved manifest; check health, API errors, media, auth, registration/payment signals.
|
||||
- [ ] **T40 — Observe and close release (S; deps: T39).** Files: D release notes/incident log. Acceptance: defined observation window ends without unresolved critical defect; known issues and next-phase messaging/business-rule requests are recorded. Verify: owner signs off live mobile/desktop journeys and rollback readiness.
|
||||