# WWW Modernization Migration Analysis ## Goal Define a realistic path to migrate the legacy `www/` surface away from JSP and PHP toward a modern Node + Vue application without attempting a risky rewrite-in-place. The recommended strategy is incremental: 1. keep the current legacy application running as the system of record 2. introduce a modern Node + Vue web layer beside it 3. migrate page families one slice at a time 4. retire JSP and PHP only after each slice has a proven replacement ## Executive Summary The `www/` layer is not just a collection of templates. It is a mixed runtime where rendering, session handling, business rules, and request-scoped data assembly are tightly coupled inside JSP pages and shared includes. Representative examples in this repository: - `www/fotoCR.jsp` mixes HTML, session beans, request beans, taglibs, and inline Java for race search and FaceAI launch metadata. - `www/_inc_header.jsp` holds shared navigation, login-dependent UI, language switching, and archive links. - `www/gallery1.jsp` and `www/gallery2.jsp` are JSP wrappers around older PHP gallery implementations. - `www/faceai_handoff.php` shows that the current PHP layer is mostly a thin integration bridge, not the core application runtime. - `faceai/` already proves that a modern Node + Vue application can coexist with the legacy site in this repository. That means the migration is feasible, but it should be treated as a strangler migration, not a rewrite. The first milestone should not be the race photo page or account flow. Those surfaces are too entangled with the existing Java session model and request beans. The first milestone should be the smallest public-facing page family that lets the team stand up the modern shell, deployment model, routing, and shared UI primitives with minimal business risk. ## What The Current Legacy Surface Looks Like ## 1. JSP is the primary runtime for the public site The public JSP pages commonly depend on: - session-scoped beans such as `utenteLogon`, `cart`, `lang`, and `attivita` - request-scoped beans such as `CR`, `bean`, `list`, `user`, and `cartStatus` - custom JSP taglibs under `WEB-INF` - shared includes such as `_inc_header.jsp`, `_inc_footer.jsp`, `_inc_head.jsp`, `_inc_cookie.jsp`, and `_inc_lang.jsp` This is important because a Node replacement cannot simply port the HTML. It must replace or proxy the data-loading and session-aware behavior currently injected by the JSP runtime. ## 2. PHP exists, but mostly as a sidecar or archive layer The PHP files in `www/` appear to fall into two main groups: - FaceAI bridge endpoints such as `faceai_handoff.php`, `faceai_return.php`, and `faceai_config.php` - older gallery/archive implementations such as `gallery1.php` and `gallery2.php` The PHP layer is not the main source of identity or page composition. The core public experience is still driven by Java session state and JSP rendering. ## 3. Shared layout and auth state are centralized in includes The current header include is effectively part layout, part auth adapter, part navigation registry. Migrating individual pages without first defining a modern replacement for the shared shell will create duplicated work. ## 4. Public and admin should be treated as separate migration programs The `www/admin/` tree shows much heavier use of request beans and CRUD-style JSP pages. That surface should not be bundled into the first modernization wave. Recommended scope split: - Wave 1: public site pages under `www/` - Wave 2: account, cart, and purchase flows - Wave 3: admin pages under `www/admin/` ## What A Modern Node + Vue Migration Actually Requires Moving to Node + Vue is not only a frontend change. It requires replacing four legacy runtime responsibilities. ## 1. Presentation layer replacement Replace JSP-rendered HTML with Vue-rendered pages and components. ## 2. Composition layer replacement Replace shared includes and taglib-driven composition with a modern shared shell: - header - footer - language switcher - login/account state widgets - SEO metadata handling - analytics and cookie consent hooks ## 3. Session and trust boundary replacement The modern app should not try to directly consume the legacy Java session cookie. That is the same constraint already identified for FaceAI. Instead, use a bridge strategy: - legacy remains source of truth for auth and membership state - Node receives a signed bootstrap payload or token - Node establishes its own session or signed server-side state ## 4. Data access replacement Any migrated page that currently relies on request beans or taglibs will need one of these strategies: - a new legacy-backed JSON endpoint - a Node adapter that calls an existing legacy endpoint - a shared read model or cache built specifically for migrated pages For the first phases, the safest approach is a thin Node BFF that talks to legacy-owned data sources instead of immediately rewriting all backend logic. ## Recommended Target Architecture ## Recommended runtime Use a Node-hosted Vue application for the public web layer. Two workable variants: 1. Nuxt 3 on Node 2. Express BFF plus Vue 3 frontend, similar in spirit to `faceai/` Recommendation: - for marketing pages, SEO pages, event listing, and route-by-route incremental replacement, Nuxt 3 is the stronger fit because it gives server rendering, routing, metadata, and hybrid rendering out of the box - if the team wants to stay very close to the current FaceAI stack, an Express BFF plus Vue frontend is still workable, but it will need extra SSR or pre-render decisions for SEO-sensitive pages For the plan below, the important decision is not the exact framework. The key is to use a Node server with a Vue UI and a BFF layer that can coexist with the legacy app during migration. ## Proposed logical architecture - modern web app: Node + Vue public shell and migrated pages - BFF layer: session bootstrap, legacy adapters, route guards, feature flags - shared UI package: header, footer, buttons, forms, typography, language switcher - contracts package: route payloads, auth/session bootstrap schema, event and gallery DTOs - legacy bridge endpoints: small trusted endpoints on the old stack for auth bootstrap and targeted data reads until the old backend is retired ## Routing model Adopt strangler routing from the start. Examples: - legacy continues serving most routes - selected routes are forwarded to the new Node app - migrated pages link back to legacy routes for anything not yet moved - the cutover is managed by route manifest and feature flags, not by a single big switch ## Recommended repository shape Create a new top-level workspace area for the modern public site instead of mixing it into `faceai/`. Suggested structure: ```text site-modern/ apps/ web/ bff/ packages/ ui/ contracts/ config/ docs/ ``` This keeps FaceAI independent while allowing shared contracts or UI conventions later. ## Migration Principles 1. Do not rewrite backend business rules before proving the new web shell. 2. Do not start with the highest-coupling pages. 3. Keep auth and membership checks on the legacy side until the replacement is explicit and tested. 4. Prefer adapter endpoints and signed handoff over trying to share `JSESSIONID` semantics. 5. Migrate by page family, not by random file order. 6. Keep the same URLs where practical, but use route-by-route cutover. 7. Treat public, commerce, and admin as separate tracks. ## Suggested Migration Order ## Phase 0: Inventory And Contracts Objective: make the migration measurable before writing the new app. Deliverables: - route inventory for public pages, account pages, archive pages, and admin pages - page-family grouping by coupling and risk - list of shared includes and what state they require - auth/session bootstrap contract between legacy and Node - language and SEO requirements inventory - asset inventory for CSS, JS, images, and fonts still required by public pages Expected findings: - static content pages are lowest-risk - event and listing pages are medium-risk - race photo pages are high-risk - login, cart, payment, and admin are highest-risk ## Phase 1: Bare Essentials Scaffold Objective: stand up the modern app without changing critical business behavior. Build the following first: - a Node-hosted Vue application with production build, preview, and deployable runtime - reverse-proxy or route-switch support so selected URLs can be served by the new app - a shared layout shell with header, footer, cookie banner hook, and language switcher placeholder - a minimal BFF service with healthcheck, feature flags, and structured logging - a legacy session bootstrap endpoint that can tell the Node app whether the user is anonymous or authenticated - error pages, not found handling, and analytics hooks This phase should produce a working but small app that can render one safe public route in production-like conditions. ## Phase 2: First Small Slice Objective: migrate one low-risk public page family end to end. Recommended first slice: - `cookies.jsp` and `cookies-en.jsp` - optionally `privacy.jsp` and `privacy-en.jsp` Why this is the right first slice: - low business risk - low dependence on request beans compared with race pages - exercises bilingual routing and layout - validates SEO, metadata, deployment, rollback, and monitoring - proves the new header/footer shell without needing cart, payment, or race search logic Alternative first slice if you want something more visible: - `associazione.jsp` and `associazione-en.jsp` That is still reasonable, but it likely pulls slightly more shared layout behavior and content formatting into scope than a policy page. What to complete in this phase: - route parity for the chosen page pair - modern content source for both languages - link compatibility with the rest of the legacy site - smoke tests for anonymous navigation - deployment rollback path for only those routes ## Phase 3: Shared Public Shell Objective: stop rebuilding layout logic page by page. Extract and implement a reusable modern shell for: - top navigation - account/login entry points - archive navigation - footer - cookie and consent surfaces - language switcher This is the point where the new app becomes a real replacement surface instead of a one-off page host. Important constraint: Do not fully reimplement legacy login in this phase. Only expose login state and links through a bootstrap or adapter mechanism. ## Phase 4: Public Listing Pages Objective: move pages that are mostly read-only and SEO-sensitive before touching the transactional core. Candidate page families: - association and informational pages - event listing pages - news or content pages - archive landing pages This phase should also define the content model for text-heavy pages so the team stops editing JSP files for editorial content. ## Phase 5: Archive And Gallery Modernization Objective: retire the PHP gallery islands. Current signal from the repo: - `gallery1.jsp` and `gallery2.jsp` are wrappers around PHP pages - the PHP archive logic likely depends on filesystem-oriented directory browsing behavior This should be its own dedicated phase because the archive looks simple from the outside but is likely coupled to directory layout and photo-serving assumptions. Recommended approach: - first model the archive data shape in a BFF adapter - then replace the PHP rendering with Vue pages - keep legacy file serving or image URLs until archive behavior is fully matched ## Phase 6: Race Pages And Search Flow Objective: move the public race experience after the modern shell and read models are already proven. This includes pages like `fotoCR.jsp`, which are high-coupling because they currently depend on: - request beans for race and listing state - session-aware account checks - existing JavaScript search functions - existing modal/download behavior - FaceAI launch metadata already embedded in JSP Recommended approach: - first move race-page rendering to the new app - keep downloads and final entitlement checks on the legacy side initially - expose race data and result sets through a BFF or dedicated JSON contract - treat FaceAI as an already-existing modern island that the new public shell can link to cleanly This phase is where the new app starts replacing the most valuable legacy experience, but it should not happen before the earlier scaffolding phases are complete. ## Phase 7: Account, Cart, And Checkout Objective: replace user-sensitive flows only after the public shell is stable. This phase will likely require explicit decisions about: - account source of truth - payment integration ownership - renewal and membership rules - session lifecycle across legacy and modern routes This is not a safe first wave. It is a later migration once the route-switching and session bootstrap patterns are proven. ## Phase 8: Admin Modernization Objective: move `www/admin/` as a separate program. The admin surface should probably be treated as a standalone back-office application with its own priorities, permissions, and page patterns. It does not need to block public-site modernization. ## Concrete First Implementation Plan If the team wants to start now and keep the first move small, the recommended first implementation is: ## Step 1 Create the new modern site workspace and deployment path. Deliver: - Node + Vue app scaffold - BFF service scaffold - route manifest for migrated URLs - CI build and deploy pipeline ## Step 2 Implement the shared public shell. Deliver: - modern header - modern footer - shared typography and spacing tokens - bilingual route structure - feature flag to switch specific pages between legacy and modern ## Step 3 Add minimal legacy bootstrap support. Deliver: - endpoint for auth state bootstrap - signed payload contract for user language and basic identity state - integration tests proving anonymous and logged-in header rendering ## Step 4 Migrate one low-risk page family. Deliver: - `cookies` page in both languages, or `privacy` if preferred - same URL shape or controlled redirect strategy - smoke tests - rollback switch ## Step 5 Migrate one slightly more complex public content page. Deliver: - `associazione` in both languages - real shared shell reuse - proof that future public pages can follow the same pattern After those five steps, the team will have a real migration foundation rather than a prototype. ## What Will Be Hard ## 1. Auth and session continuity The legacy site identity is still rooted in Java session state. Replacing JSP without an explicit trust bridge will fail. ## 2. Shared server-side state hidden inside includes The header and other includes are not pure view fragments. They depend on beans and request/session state. ## 3. Page beans and taglibs Many pages are really thin shells over server-side Java objects. Those contracts need to be rediscovered and exposed in a modern form. ## 4. SEO and URL preservation A pure SPA would be the wrong choice for much of the public site. Server rendering or pre-rendering is needed for migrated public routes. ## 5. Archive behavior The older PHP galleries are probably more coupled to directories and legacy assumptions than they look from the JSP wrappers. ## What Will Be Easier Than It Looks ## 1. Standing up a parallel modern app The repository already has a working modern precedent in `faceai/`, including Node runtime, Vue frontend, and Docker-based local integration. ## 2. Migrating static and content-heavy pages Many public informational pages can move early once the shared shell exists. ## 3. Route-by-route rollout Because the legacy and modern apps can coexist, the migration does not need a freeze or a single cutover date. ## Recommended Non-Goals For The First Wave Do not do these first: - full login replacement - cart and payment rewrite - admin rewrite - race search rewrite - direct database rewrites for everything at once - a pure client-only SPA for the public site ## Suggested Success Criteria For The First 6 To 8 Weeks - modern app scaffold is live in a production-like environment - one to two low-risk bilingual public page families run from the new app - shared header/footer shell exists and is reusable - legacy auth bootstrap contract exists - route switching and rollback are proven - observability exists for both legacy and modern paths ## Recommended Final Direction Yes, moving the `www/` part toward Node + Vue is a sound direction, but only if it is implemented as a staged strangler migration. The right first move is not to reimplement `fotoCR.jsp` or the account stack. The right first move is to establish the new runtime, shared shell, routing model, and auth bootstrap, then migrate a low-risk bilingual page family, then expand into public listing pages, then tackle archives, then move the race/photo experience, and only after that consider account, checkout, and admin. If the team follows that order, the migration is practical. If the team starts with the race page or tries to replace JSP and PHP everywhere at once, the risk goes up sharply and the delivery cadence will slow down.