Production website for Sogn Contracting LLC, a licensed general contractor in Bandon, Oregon. Built and maintained by Preston Winters at Winters Code.
Live: sogncontracting.com
A static-rendered Next.js 14 site for a Bandon-Oregon construction company. Built to:
- Show 30+ years of work without slowing anyone down
- Pass Lighthouse 95+ on real Coos County phones (slow LTE, older Androids)
- Stay maintainable by one person, forever
- Cost nothing to run beyond the domain
No CMS. No tracking. No paid SaaS dependencies. Photos in public/projects/, copy in config/site.ts, deploys to Cloudflare Pages.
| Layer | Choice | Why |
|---|---|---|
| Framework | Next.js 14 (App Router, static export) | Prerendered HTML, no server costs |
| Styling | CSS modules + global tokens | No Tailwind, no runtime CSS-in-JS, zero JS for styling |
| Images | Next <Image> with unoptimized + manual srcset |
Build-time WebP variants, no image proxy needed |
| Forms | Static <form> POST to a Cloudflare Worker |
No third-party form service |
| Hosting | Cloudflare Pages | Free tier covers this site forever |
| Analytics | None | Owner doesn't need them |
| CSP | Per-page SHA-256 hash via scripts/csp-postprocess.mjs |
Strict CSP, no unsafe-inline, passes Lighthouse Best-Practices |
Lighthouse, real device, mobile profile:
| Metric | Score |
|---|---|
| Performance | 95+ |
| Accessibility | 100 |
| Best Practices | 100 |
| SEO | 100 |
Tested via PageSpeed Insights.
app/ # Next 14 App Router pages
page.tsx # Home
services/ # /services
gallery/ # /gallery (filtered project grid)
api/contact/ # form submit handler
components/ # React components, one CSS module each
config/
site.ts # Single source of truth: name, contact, credentials, meta
projects.ts # Gallery project data (before/after pairs, descriptions)
public/projects/ # WebP photos at 4 widths (400/800/1200/1600)
scripts/
csp-postprocess.mjs # Per-page CSP hash injection on build
npm install
npm run dev # http://localhost:3000npm run build # produces .next/ with CSP-processed HTML
npm run start # serve the build locallyCloudflare Pages picks up npm run build automatically on push to main. Build command: npm run build. Output directory: .next.
This site is built so one person can update it in 5 minutes:
- New project photos: drop WebPs in
public/projects/<slug>/, add the entry toconfig/projects.ts, push. - Phone, address, credentials change: edit
config/site.ts, push. - Content edits: edit the relevant component (
components/AboutSection.tsx,components/Hero.tsx).
All changes deploy automatically via Cloudflare Pages on push to main.
Built by Preston Winters at Winters Code, Bandon Oregon. Custom websites and apps for Oregon coast businesses.
For business questions about the site or Sogn Contracting's work: sogncontracting.com.
For questions about the code or how it was built: [email protected].
MIT. See LICENSE.
The code is open source. The Sogn Contracting brand, logo, project photography, and business copy are property of Sogn Contracting LLC and not covered by this license.
