Get Started

Behind the Build: How We Built nr-designs.ca (And Where AI Fit In)

We hand-built our agency site from scratch — custom 3D scenes, scroll choreography, accessible markup, and a production AWS stack. Here's how we did it, and where AI played a supporting role.

We wrote a piece recently about why vibe coding can’t take you from prototype to production. The response was strong — probably because it hit a nerve for anyone who’s tried to ship AI-generated code to real users.

Some people read that and assumed we’re anti-AI. We’re not. We use AI tools in our workflow. But there’s a difference between using a tool and depending on one.

Our own website — the one you’re reading this on — was designed, architected, and built by hand. AI sped up some of the tedious parts. The decisions, the craft, and the engineering that makes it actually work? That was us.

Here’s the full breakdown.

What we built

Before anything else, let’s talk about what’s under the hood. This isn’t a template. It isn’t a page builder export. Every line of code was intentional.

Main site (frontend):

  • React 19 with TypeScript
  • Vite 7 for builds and dev server
  • Three.js / React Three Fiber for custom 3D hero scenes on every page
  • GSAP + ScrollTrigger for choreographed scroll animations
  • Framer Motion for UI transitions
  • Lenis for smooth scrolling
  • Custom CSS throughout — no framework, no utility classes

Blog:

  • Astro (separate build, pre-rendered static HTML)
  • MDX for content authoring
  • Zero JavaScript by default — loads in under a second

Backend:

  • AWS SAM (Lambda + API Gateway)
  • DynamoDB for data
  • S3 + CloudFront for hosting and CDN
  • CloudFormation for infrastructure-as-code

Deployment:

  • Automated build scripts with pre-rendering for SEO
  • Custom sitemap generation
  • Static HTML generated at build time for search engine visibility

Every architectural choice here was made deliberately. We chose React + Vite over Next.js because this site needs client-side 3D Canvas rendering and complex scroll interactions — neither plays well with server-side rendering. We chose Astro for the blog because content pages should be static HTML with zero JavaScript overhead. We split the frontend and blog into separate builds because they have fundamentally different requirements.

AI doesn’t make those calls. That’s experience.

The craft: what made this site what it is

Custom 3D scenes

The homepage hero features a 3D wireframe assembly — geometric shapes that drift through space, lock into formation, then idle with subtle motion. Every service page has its own unique Three.js scene.

We designed each scene’s geometry, choreographed the assembly timing, and hand-tuned the post-processing (bloom, vignette) to match the site’s blueprint aesthetic. The easing curves, the drift patterns, the exact moment shapes snap into place — that’s all us, iterated through dozens of test runs.

The real work was performance. Getting these scenes to hold 60fps on a $200 Android phone required serious optimization:

  • Memoized all geometries with useMemo to prevent per-frame allocation
  • Merged construction line geometries into a single buffer geometry
  • Capped device pixel ratio at 1.5
  • Tuned bloom and vignette passes to minimize GPU overhead
  • Tested on real mid-range devices, not just our development machines

A working 3D scene is easy. A 3D scene that’s beautiful and fast on real hardware is engineering.

Scroll choreography

The site uses a scroll-storytelling approach. As you scroll, elements reveal, parallax, and transition in a coordinated sequence. This involves GSAP ScrollTrigger with precise start/end trigger points, scrub values, stagger timings, and easing curves — all synchronized across multiple elements.

We spent days on this. Scrolling through the page dozens of times, adjusting timing by fractions of a second, fine-tuning the parallax depth on the hero’s content layer vs. the 3D canvas layer vs. the annotation elements. These are subjective decisions that determine whether a site feels polished or feels off. There’s no shortcut.

Accessibility by design

Every interactive element was built with accessibility in mind from the start — not patched in afterward.

The hero is a good example. The visible heading uses a decorative typewriter effect cycling through phrases like “digital experiences,” “stunning websites,” “mobile apps.” But screen readers don’t need to watch words type out. So we built a <span className="sr-only"> containing the full, meaningful heading text, and marked the decorative version with aria-hidden="true".

That pattern is everywhere: proper semantic HTML instead of div soup, keyboard navigation that works on every interactive element, focus management on modals and route changes, WCAG-compliant color contrast ratios. These aren’t extras. They’re requirements.

The blueprint design language

The entire site follows a custom blueprint/wireframe visual language — construction annotations, dimension markers, coordinate labels, grid backgrounds, a deep navy and electric blue palette. This isn’t a theme we downloaded. Every visual element — the BlueprintAnnotation component, the GridBackground, the WireframeReveal, the ConstructionProgress indicator — was designed and built as a custom React component.

Maintaining this visual language consistently across the homepage, five service pages, legal pages, and the blog required constant attention. Every new section had to feel like it belonged to the same system.

Copy and voice

Every word on this site was written by a human. Every headline, every service description, every blog post — including this one.

Our voice is direct, data-backed, and occasionally blunt. We’ll tell you to save your money if that’s the honest advice. That doesn’t come from a prompt. It comes from experience and opinions.

Where AI played a supporting role

We’d be dishonest if we said AI wasn’t part of the process. It was — in the same way a good power tool is part of building a house. The carpenter still designs the house, cuts the joints, and makes sure it’s level.

Boilerplate and scaffolding

When we needed a new component, AI generated the initial skeleton — the TypeScript interface, the basic JSX structure, the hook patterns. This saved us from writing the same useState / useRef / useEffect boilerplate for the hundredth time.

Every scaffold was then rewritten to fit our animation system, our design language, and our accessibility requirements. The scaffold saved maybe 10 minutes per component. The real work — making it actually good — took hours.

Math and procedural code

AI is genuinely good at trigonometry. When we needed sine/cosine oscillation patterns for the 3D scene drift, or lerp functions for assembly transitions, or eased timing curves — AI could produce correct math quickly. We’d describe the motion we wanted, get a starting formula, then tune it by hand until it looked right.

Debugging assistance

When TypeScript threw a wall of errors after a React Three Fiber upgrade, AI helped parse the type mismatches. When a GSAP ScrollTrigger wasn’t firing on the right scroll position, AI helped narrow down the issue. It’s a good rubber duck — patient and fast.

Image asset exploration

We used AI image generation to explore visual concepts early in the design process. It was useful for mood exploration and quick direction checks. Final assets still required careful art direction, multiple regeneration rounds, and manual editing to match our palette and aesthetic.

What AI can’t do (and why it matters for your project)

Here’s the part that’s relevant if you’re a business owner thinking about your next website.

AI can’t make architectural decisions. It would have given us Next.js for everything on this project. That would have been wrong. Choosing the right framework, the right rendering strategy, the right hosting model — these decisions determine whether a site is fast, maintainable, and cost-effective. They require understanding trade-offs in context, not in the abstract.

AI can’t make a site accessible. Every time we’ve seen AI-generated HTML, it has accessibility gaps — missing aria labels, wrong semantic elements, no focus management, broken keyboard navigation. Accessibility isn’t a layer you add later. It’s a way of building.

AI can’t optimize for real-world performance. It generates code that works. Not code that’s fast. The difference between a 3D scene that runs and one that holds 60fps on a budget phone is hours of profiling, memoization, and device testing. AI doesn’t do that work.

AI can’t design. It can replicate patterns. It can’t create a cohesive visual language, maintain it across 15+ pages, or make the hundred subjective decisions per day that determine whether a site feels crafted or generated.

AI can’t write in your voice. If your website copy sounds like it could belong to any company in your industry, it’s not doing its job. Voice comes from a real person with real opinions.

The bottom line

We built this site. We’re proud of it. AI helped around the edges — saving time on boilerplate, speeding up math, and assisting with debugging. That’s what good tools do.

But the architecture, the 3D scenes, the scroll choreography, the accessibility, the design system, the performance optimization, the copy — that’s craft. That’s what separates a website that works from a website that works for your business.

When you hire a builder, you’re not paying for their tools. You’re paying for the years of experience that tell them which tool to use, when to use it, and when to put it down and do the work by hand.

That’s what we do at NR Designs. Let’s talk about your project.