16 KiB
Sanaz Goodarzi — project context
Last updated: 2026-09-15. Read this file before making changes. Update it on each prompt when requirements, decisions, implementation, or verification status change. Never replace the original migration objective with a follow-up styling request.
User requirements (authoritative)
- Rebuild the site running at
http://sanaz-goodarzi.local:8000/in real Next.js, Persian (lang="fa"), RTL (dir="rtl"). - Treat original site content as valid; correct obvious visual, navigation, spelling, and UX defects.
- Implement all public pages as static pages now. The user will supply API documentation later.
- Use Swiper for sliders/carousels. Do not substitute a custom slider.
- Keep the original charcoal, gold, and white palette. Improve mobile hamburger spacing.
- Fully responsive layouts for mobile, tablet, desktop; support narrow screens, touch targets, keyboard focus, and reduced motion.
- User supplied images in root
img/, and permitted copying/moving them. Render the copy inpublic/img/with the original filenames/subdirectories. Keep the supplied originals intact. - Dynamic areas use clearly marked thumbnails/previews until real API content is provided. Never present invented projects, project dates, locations, metrics, or successful form submissions as real.
- Footer bottom Meshkee credit must follow
https://safeteb.com/, including the logo, exact English text, link, and animated border. - Latest typography instruction: use the user's files in
public/fonts/(the user called it “font”). Main headings use Bold 700; everything else uses Light 300. Do not return to Vazirmatn, Shabnam, or a remote font CDN. - Keep development and output in this local workspace. No publication was requested.
- This architecture website has no product catalog or store. Ignore all product, store-item, cart, checkout, order, payment, marketplace, and shop-login instructions in this and future backend prompts unless the user explicitly reverses this requirement.
Stack and running
- Next.js App Router, React, plain CSS, lucide-react icons, Swiper.
next.config.mjs:output: 'export',trailingSlash: true, unoptimized image output.npm run dev: development athttp://localhost:3000(original site remains on port 8000).npm run build: exports production files intoout/.npm start: servesout/locally; optionalPORTenvironment variable.npm run lint: ESLint / Next recommended rules.- Use Node 24 LTS (
.nvmrc), minimum 20.9. This machine's default Laragon Node is 18.8.scripts/runtime.mjsuses the already-installed Codex Node runtime as a Windows fallback when needed. No runtime is downloaded. package-lock.jsonis authoritative for installed versions. Do not run a new scaffold or replace this project with Vinext/Sites templates.
Public routes
| Route | Implementation |
|---|---|
/ |
Full-viewport hero plus five source-matched category panels; vertical Swiper on desktop, normal stacked scrolling on mobile; no footer |
/ourservices/ |
Five text cards in a two-column grid overlapping the 690px source subheader; one column on mobile |
/aboutus/ |
Source bird-image hero with three colored icons, biography with circular photo, image/progress section, accessible FAQ |
/contactus/ |
Three source-matched contact columns and centered single-column static form; four offices and real contacts |
/portfolios/ |
Category filtering with URL query state; clearly labeled category thumbnails |
/portfolios/residential/ |
Static residential preview |
/portfolios/beauty/ |
Static beauty salon preview |
/portfolios/commercial/ |
Static office/commercial preview |
/portfolios/landscape/ |
Static landscape preview |
/portfolios/facade/ |
Static facade preview |
/portfolios/[id]/[titleFaSlug]/ |
Canonical API portfolio details generated at build time from by-id, with hover zoom, lightbox gallery, and related work |
/blog/ |
API blog listing; a thumbnail empty state appears while no posts are published |
/blog/[id]/[titleSlug]/ |
Canonical API blog details generated at build time from by-id, with CMS SEO and JSON-LD when supplied |
| unknown route | Persian 404 page |
No blog link/page was found in the original public navigation. Do not invent a blog or articles simply because the original brief mentioned blogs as an example of dynamic content.
Source-matched visual structure (2026-09-06)
- The user rejected the earlier free redesign. Preserve the original layout, imagery, section order and proportions; fix only clear UX/content defects and apply explicit follow-ups.
- Home: full-height image 1 hero; five half-image/half-text panels, images on the left, text on the right, alternating white/black backgrounds and large gold V/B/O/L/F letters at the seam. No extra introduction, about strip or contact CTA.
- Use hamburger navigation at every viewport size, with comfortable top/right spacing and the supplied gold logo at the left. Keep the animated dark fullscreen menu.
- About progress values 68, 25, 36 and 82 were verified in the original DOM; they are source data, not invented metrics.
- Portfolio source eventually returned a backend TLS connection error to its upstream portfolio service. Do not copy its debug output or fabricate unavailable project records.
Source findings
- Read original home, about, and services in browser, and contact page through HTTP. Original navigation exposes the five main routes above.
- Original
/portfoliosfailed to finish loading in the browser and a bounded HTTP request timed out. Portfolio records therefore were not verified. Current images represent categories only, not named projects. - Original home incorrectly labeled the facade service as office/commercial. Corrected to طراحی نما.
- Original services page repeated office copy under landscape. Replaced with the matching landscape copy from original home.
- Original footer/navigation/category/social links frequently pointed to
/or#; replaced with meaningful routes and verified contact destinations. - Original admin/editor controls are not public site functionality and are intentionally excluded.
- Original logo URL returned a Git LFS pointer, not an image. It was removed. The user subsequently supplied the actual
public/Logo.png(case-sensitive path), now rendered by the shared Brand component in the header, mobile menu, and footer with the header wordmark hidden to match the source. Preserve its gold colors, transparency, and aspect ratio. - Original Shabnam CDN did not resolve. User then supplied IRANYekan fonts; these supersede all prior font decisions.
Files and boundaries
lib/content.js: verified source text, navigation, five services, biography, FAQs, four offices, three phones, two emails, Instagram.lib/portfolio.js: explicitisPlaceholder: truerecords andgetPortfolioItems()adapter boundary.components/home-experience.js: active home implementation. Vertical Swiper at min-width 900px and min-height 650px; otherwise stacked sections. Mode changes remount Swiper so mousewheel initialization remains correct. Six navigation dots, keyboard support, reduced motion, and inactive desktop slides marked inert.components/hero.jsis a legacy unused component.components/shell.js: shared header, native dialog mobile menu, footer. Dialog provides modal keyboard behavior; closes on Escape, backdrop, close button, or navigation. Scroll is locked while open.components/contact-form.js: validates locally; never sends or stores data. Status explicitly states no message was sent. The send API is pending.components/portfolio-grid.js: category filter and URL query sync, including browser back/forward.app/globals.css: base tokens, accessibility, shared components and animation rules.app/reference.css, imported afterward, owns source-matching layout and responsive overrides at 1200, 899 and 650px. Shared subheaders use the original image without any overlay and dark titles.app/layout.js:next/font/localwithiranyekanweblightfanum.woffat 300 andiranyekanwebboldfanum.woffat 700.public/meshkee-logo.png: genuine logo retrieved from safeteb.com. Credit links tohttps://meshkee.comand readsDesigned And Developed By/Meshkee E-Commerce Team.public/img/slider/1.jpg: charcoal/gold hero; 2 residential; 3 beauty; 4 office/commercial; 5 landscape; 6 facade. Other images retain original paths.img/frames/holds supplied frame references, not project portfolio records.
API integration next steps
Backend contract received 2026-09-15: base https://api.meshkee.com/api/v1, tenant sanazgoodarzi.ir, official documentation https://api.meshkee.com/docs/website.
Tenant SEO prompt 6d011d374a2bb32e88d778c8 supersedes the earlier generic slug-only detail URL guidance. Public CMS detail URLs use numeric/string ID plus a Persian title slug: /blog/{id}/{titleSlug} and /portfolios/{id}/{titleFaSlug}. The page resolves content through the matching by-id endpoint; the title segment is for readable canonical URLs.
- Read the user's API documentation; do not invent URLs, tokens, schemas, or authentication.
- Replace the portfolio adapter and remove preview badges only for actual records. Preserve category IDs or map API values explicitly.
- Current detail slugs are exported by
generateStaticParams. New API slugs require a rebuild, or an explicitly agreed change to client-side routing/server rendering. - Keep client secrets out of browser bundles. Decide static fetch-at-build vs client fetch based on the real API and freshness requirements.
- Contact form is connected to
POST /tenants/sanazgoodarzi.ir/contact-submissionswith title/name/email/cellNumber/text. It resets and displays success text plus toast only after HTTP success; failures preserve entered values. - Mark preview detail pages
noindexuntil populated. Review metadata when real content is connected.
Verification status
- Dependencies installed; npm audit at install reported zero vulnerabilities.
- Development home compiled and HTTP returned 200; preview opened at localhost:3000.
- Initial lint found no errors and one config export warning; the warning has been corrected.
- Final
npm run buildpassed using Next.js 16.3.4, including all 10 public content routes and the generated not-found route. All are static/SSG exports. - Final
npm run lintpassed with zero errors and zero warnings. scripts/verify-export.mjspassed: 10 HTTP routes, 37 linked local assets/files, valid signatures for both IRANYekan WOFF files, Persian RTL markup, the Meshkee credit, and a real HTTP 404 with the Persian not-found page.- Preview tab at
http://localhost:3000/was marked as the deliverable; the source site on port 8000 was preserved. Usenpm run devfor continued editing, ornpm startfor the exported static preview. Do not start both on the same port. - Browser QA performed on desktop home hero/category slides (including mousewheel), source-matched about/services, and 390x844 mobile home, services, contact and fullscreen menu. Mobile services/contact showed no horizontal overflow. Home footer absence and inner-page footer presence checked. Build, lint and export verification passed again after the latest footer/subheader changes.
- SEO prompt verification on 2026-09-15: production build and lint passed.
scripts/verify-seo.mjspassed for all 6 crawlable static pages (unique title/description, exactly one H1, canonical URL, meaningful image alt) and confirmed the generated config contains exactly 6 static routes.scripts/verify-export.mjspassed all 11 current exported/preview routes. API blogs and portfolios were empty, so placeholder static params are noindex and will be replaced by real ID/title params on a build after CMS publication.
Change log
-
SEO prompt
6d011d374a2bb32e88d778c8: changed CMS detail links and static params to tenant-specific ID + Persian-title canonical URLs; added unique descriptions and canonical metadata to all crawlable static pages; added CMS-first detail metadata and meaningful OG image alt text; confirmed one H1 per implemented page; and added build-time route scanning that writespublic/meshkee/sitemap-config.json. Never add localpublic/sitemap.xmlorpublic/robots.txt; production nginx proxies them to Meshkee. Product/category sitemap instructions remain excluded by explicit user requirement. -
Backend prompt
579d72949e25b19a25256699: connected blog and portfolio public APIs with empty-state thumbnails; added API detail routes, portfolio lightbox/hover zoom/related row, contact submission behavior, customer account detection from shared cookies plus/auth/me, and API branding with localLogo.pngfallback. API state at implementation: branding URLs null, blogs 0, portfolios 0. Product/store features were explicitly excluded by the user. -
Latest steering during reference matching: remove Footer entirely from the home route only; retain it on all other routes. Remove the subheader overlay, keep the source photo unobscured, and use dark titles/English subtitles. This explicitly supersedes the earlier 80% black overlay instruction.
-
Logo follow-up: integrated user-supplied
public/Logo.pngin the shared header/footer/mobile-menu brand. Responsive widths preserve the original 462×473 aspect ratio; intrinsic dimensions reserve layout space and alt text identifies the brand. -
Latest subheader instruction supersedes the light-overlay design: all shared page headings now use a uniform black
rgba(0,0,0,0.8)photo overlay and white titles, descriptions, English eyebrows, breadcrumbs, and link states at every breakpoint. Font weights and responsive sizing are preserved. -
Scroll animation correction: replaced late WAAPI opacity resets with pre-armed CSS transitions on offscreen elements only. Already-visible content is never hidden; entrances begin 48px before viewport entry, move 16px, and run once. Mutation processing checks added subtrees instead of rescanning the full page on Swiper updates. Reduced-motion changes and cleanup reveal prepared content; focused content stays visible. No Animate.css dependency needed for these small opacity/transform transitions. This supersedes the previous viewport WAAPI implementation. Production build and lint passed after the scroll correction.
-
Animation follow-up: added progressively enhanced, once-per-element viewport entrances (including filtered portfolio cards), hero/subheader text entrances, and subtle button/icon feedback. Mobile dialog slides in from the right in 440ms and closes in 260ms; backdrop fades and links enter sequentially. Native dialog stays modal and scrolling stays locked until exit completes; Escape is intercepted to animate before closing. Reduced-motion users get immediate menu changes and no reveal effects.
components/page-motion.jsowns observers and cancels animations on unmount/preference changes. Production build and lint both passed after this change. -
Subheader readability follow-up: added a consistent high-opacity warm-white photo overlay at every breakpoint, explicit charcoal heading/body colors, darker gold eyebrow, and readable 13px breadcrumb/eyebrow and 16px description sizes. Preserved IRANYekan Bold headings / Light remaining text. This applies to all shared
PageHeadingsections. -
Initial request: created the Next.js static migration, source content mapping, Swiper, shared navigation/footer, responsive public pages, and API placeholders.
-
Image follow-up: copied supplied
img/topublic/img/without renaming source files. -
Responsive follow-up: mobile/tablet/desktop layouts, hamburger spacing, dialog navigation, touch targets, fluid grids/images.
-
Font follow-up: switched to supplied IRANYekan local Light/Bold fonts and recorded the weight rule.