Answer from a front-end perspective:
Don't listen to everyone saying it can't be done, because an experimental San Francisco State University web service I co-wrote in 1996 finally went to Internet heaven a couple years ago, and never needed a single browser compatibility fix in that time; that's almost half of your 40-year goal. And this JavaScript-based front-end I made in 1998 for a Stanford Research Institute project was replaced with something flashier a few years later, but there's no reason the original UI couldn't still be running today with minor compatibility fixes.
The trick is to ensure your app uses only widely-supported W3C/ECMA standards and has a clean design under your control. While a lot of web apps written to the trendy 90s-era technology won't work well or at all today, 90s-era web apps written to major standards still do. They may look passé, but they work.
The goal here isn't to write a web app that will go up on their server and remain there for 40 years without anyone touching it again. It's to build a foundation that can still be in use decades down the line, which can grow to support new features without having to be rebuilt from scratch.
First of all, you have to code to official standards and only to official standards. No JavaScript features not part of a ratified ECMAScript standard; ES5.1 is the current version and is generally supported so that's safe to target. Likewise, current versions of HTML5, CSS, and Unicode are good. No experimental JavaScript, CSS3 or HTML features (the ones with vendor-prefixes or without 100% agreement between browsers). And no browser-specific compatibility hacks. You can start using a new feature once it's in the standard and everyone supports it without prefixes.
ES5 support would mean dropping IE8 or earlier, which I suggest anyway since it requires browser-specific hacks which will be useless in a couple of years. I'd suggest ES5's Strict Mode for the best chance at longevity, which actually sets your baseline browser compatibility at IE10 and recent versions of everyone else. Those browsers also have native support for many of HTML5's form validation and placeholder features, which will be useful for a very long time.
New editions of ECMAScript maintain compatibility with older versions, so it'll be much easier to adopt upcoming features if your code is written according to current standards. For instance, classes defined using the upcoming class
syntax will be fully interchangeable with classes defined with the current constructor.prototype
syntax. So in five years a developer can rewrite classes into the ES6 format on a file-by-file basis without breaking anything -- assuming, of course, that you also have good unit tests.
Second, avoid trendy JavaScript app frameworks, especially if they change the way you code your app. Backbone was all the rage, then SproutCore and Ember were, and now Angular's the framework everyone loves to promote. They may be useful, but they also have something in common: they often break apps and require code changes when new versions come out and their longevity is questionable. I recently updated an Angular 1.1 app to 1.2, and quite a bit had to be rewritten. Likewise, going from Backbone 2 to 3 requires a lot of HTML changes. Standards are slow-moving for a reason, but these frameworks move fast and things breaking periodically are the cost.
Plus, new official standards often leave old frameworks obsolete, and when that happens those frameworks either mutate (with breaking changes) or are left behind. You know what's going to happen to all the world's competing promise libraries once ECMAScript 6 is ratified and all browsers support its standardized Promise class? They'll become obsolete and their developers will stop updating them. If you picked the right framework your code might adapt well enough, and if you guessed poorly you'll be looking at a major refactoring.
So if you're thinking of adopting a third-party library or framework, ask yourself how hard it'll be to remove in the future. If it's a framework like Angular that can't ever be removed without rebuilding your app from scratch, that's a good sign it can't be used in a 40-year architecture. If it's a third-party calendar widget that you abstracted with some custom middleware, replacing it would take a few hours.
Third, give it a good, clean app structure. Even if you aren't using an app framework you can still take advantage of developer tools, build scripts, and a good clean design. I'm personally a fan of Closure Toolkit's dependency management because it's lightweight and its overhead is completely removed upon building your app. LessCSS and SCSS are also great tools for organizing your stylesheets and building out standards-based CSS stylesheets for release.
You can also organize your own code into single-use classes with an MVC structure. That will make it much easier to come back several years into the future and know what you were thinking when you wrote something, and to replace only those parts that need it.
You should also follow the W3C's advice and keep presentational information completely out of your HTML. (That includes cheats like giving elements presentational class names, like "big-green-text" and "two-columns-wide".) If your HTML is semantic and CSS is presentational, it'll be much easier to maintain and adapt it to new platforms in the future. It'll also easier to add support for specialized browsers for blind or disabled people.
Fourth, automate your tests and make sure you have near-full coverage. Write unit tests for every class, whether server-side or in JavaScript. On the front end, make sure each class performs according to its spec in every supported browser. Automate these tests from your build bot for every commit. This is important for both longevity and reliability, since you can catch bugs early even when current browsers obscure them. Both Jasmine and Google Closure's JSUnit based testing frameworks are good.
You'll also want to run full UI functional tests, which Selenium/WebDriver are good at. Basically, you write a program that steps through your UI and uses it as if a person were testing it. Wire those up to the build bot as well.
Lastly, as others have mentioned your data is king. Do think through your data storage model and make sure it's built to last. Make sure that your data schema is solid, and make sure that's tested thoroughly as well on every commit. And make sure your server architecture is scalable. This is even more important than anything you do on the front end.