Skip to content

codezelat/regent-web

Repository files navigation

Regent Technologies Website

Production website and small admin CMS for Regent Technologies, an industrial blade sharpening and tooling support company in Moratuwa, Sri Lanka.

The public site covers services, products, industries, FAQ, contact, legal pages, and an About page. The private admin area lives only under /hidden-admin and manages products, services, FAQ, and the admin profile. Public pages can render without a database by using seeded fallback content; write actions and admin pages require production services.

Stack

  • Next.js App Router with Server Components and Metadata API
  • Better Auth for admin email/password authentication
  • Drizzle ORM with Neon Postgres
  • Cloudflare R2 presigned uploads for product and service images
  • Resend for password reset and contact emails
  • Cloudflare Turnstile for contact form protection
  • Google Analytics 4 through @next/third-parties/google
  • Dynamic sitemap, robots rules, canonical metadata, Open Graph/Twitter metadata, and JSON-LD structured data

Local Setup

npm install
npm run dev

Open http://localhost:3000.

Copy .env.example to .env.local and fill only the services you are testing locally. Public pages can build without a database, but admin actions require DATABASE_URL.

For local admin testing, point DATABASE_URL to a local Postgres database, run migrations, then seed the admin account. For production, replace the same DATABASE_URL value with Neon.

Required Environment

Core production:

NEXT_PUBLIC_SITE_URL="https://www.regenttech.lk"
NEXT_PUBLIC_GA_MEASUREMENT_ID="optional-public-ga4-measurement-id"
DATABASE_URL="postgresql://..."
BETTER_AUTH_URL="https://www.regenttech.lk"
BETTER_AUTH_SECRET="generate-a-32-byte-or-longer-secret"

Local Postgres example:

DATABASE_URL="postgresql://postgres:postgres@localhost:5432/regent"
BETTER_AUTH_URL="http://localhost:3000"
BETTER_AUTH_SECRET="use-a-local-32-byte-or-longer-secret"

Email:

RESEND_API_KEY="..."
RESEND_FROM_EMAIL="Regent Technologies <noreply@your-domain.com>"

Turnstile:

NEXT_PUBLIC_TURNSTILE_SITE_KEY="..."
TURNSTILE_SECRET_KEY="..."

Use both keys from the same Cloudflare Turnstile widget and add the production domain in Cloudflare. For local development, leave both Turnstile values empty to bypass the challenge. Do not set only TURNSTILE_SECRET_KEY; the server will reject submissions because the browser cannot produce a token without NEXT_PUBLIC_TURNSTILE_SITE_KEY.

Cloudflare R2:

R2_ACCOUNT_ID="..."
R2_ACCESS_KEY_ID="..."
R2_SECRET_ACCESS_KEY="..."
R2_BUCKET="..."
R2_PUBLIC_BASE_URL="https://cdn.example.com"

First admin seed only:

ADMIN_EMAIL="..."
ADMIN_INITIAL_PASSWORD="..."

Do not commit real admin credentials or filled env files.

SEO Coverage

  • Page titles use the pattern Page Title - Regent Technologies.
  • Public pages have canonical URLs, descriptions, Open Graph, and Twitter card metadata.
  • Search and paginated product result URLs are noindexed while canonicalizing to /products.
  • Product detail pages include Product JSON-LD and breadcrumb JSON-LD; the FAQ page includes FAQPage and breadcrumb JSON-LD; the root layout includes LocalBusiness and WebSite JSON-LD.
  • Product and industry listing pages include ItemList JSON-LD that matches the visible page content.
  • /sitemap.xml includes public static pages, industry detail pages, published product detail pages, and crawlable image sitemap entries for key page/product images.
  • /robots.txt allows public content and blocks /hidden-admin/ and /api/.
  • Google Analytics loads only on public routes. /hidden-admin, password reset, and dashboard routes do not load the Google tag.
  • Legal pages are noindexed because they are required trust content, not search landing pages, and they are intentionally left out of the sitemap.

Database

Generate a migration after schema changes:

npm run db:generate

Apply migrations:

npm run db:migrate

Seed the initial admin, products, services, and FAQ:

npm run db:seed

The seed script is idempotent and reads the admin email/password from env. Sign-up is disabled during normal runtime.

Admin

  • Login: /hidden-admin
  • Dashboard: /hidden-admin/dashboard
  • Products: /hidden-admin/dashboard/products
  • Services: /hidden-admin/dashboard/services
  • FAQ: /hidden-admin/dashboard/faqs
  • Profile: /hidden-admin/dashboard/profile

Product fields:

  • name and description are required.
  • slug, metaTitle, and metaDescription auto-fill when left blank.
  • Up to 3 images are supported.
  • R2 uploads are available when R2 env vars are configured.
  • Admin search and pagination run client-side from server-rendered data, so records remain searchable without exposing a public API.

Service fields:

  • title, description, image, cta, modalIntro, details, and bestFor are required.
  • slug auto-fills from the title when left blank.
  • Service cards power both /services and the home page service section.
  • Service details are entered one per line and render in the public service modal.

FAQ fields:

  • question and answer are required.
  • FAQ records can be searched, sorted by sortOrder, published/unpublished, edited, and deleted from the custom admin UI.

Admin UX:

  • Product, service, and FAQ create/edit/delete flows use custom modal UI, not native browser confirmation dialogs.
  • Validation and duplicate-slug errors return inline messages in the modal instead of raw app error screens.
  • Data-driven public and admin routes include route-level loading skeletons that match the surrounding layout.

Deployment Order

  1. Add all production env vars in Vercel.
  2. Run npm run db:migrate against Neon.
  3. Run npm run db:seed once with admin seed env vars present.
  4. Remove seed-only env vars from Vercel after the admin account exists.
  5. Deploy and verify /, /products, /industries, /contact, /faq, and /hidden-admin.
  6. Submit both the contact form and a product inquiry once with production Turnstile keys enabled.
  7. Check admin product, service, and FAQ create/edit/delete flows after deployment.

Production Review

Before release, check these routes on desktop and mobile widths:

  • /
  • /about
  • /services
  • /products
  • /products/precision-blade-sharpening
  • /industries
  • /industries/woodworking-industry
  • /contact
  • /faq
  • /hidden-admin
  • /hidden-admin/dashboard
  • /hidden-admin/dashboard/products
  • /hidden-admin/dashboard/services
  • /hidden-admin/dashboard/faqs

License

This repository is proprietary software. See LICENSE.md.

Verification

npm run lint
npm run typecheck
npm run build
npm audit --audit-level=high

Do not run npm audit fix --force without reviewing the resulting dependency graph. This project uses narrow package overrides for vulnerable transitive packages when the direct dependencies are already on their latest compatible versions.

About

Production website and small admin CMS for Regent Technologies, an industrial blade sharpening and tooling support company in Moratuwa, Sri Lanka.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages