How to build custom UI that works both for users that have opted in to Lightning Experience and users that have not?

I just went through this exercise for a basic configuration page. Here is what I found out for a basic example:

  1. Liberal use of Javascript Remoting in place of submit elements (commandButton, commandLink, etc) along with calling actionfunctions in the handler to perform partial page refreshes

  2. Two VF Pages were required in order to show the page within Classic and inside LEX if you want the header or sidebar in classic:

     <apex:page showHeader="true" showSidebar="true">
         <apex:include page="LEXPAGENAME"/>
     </apex:page>
    
  3. You sill have to create your own JS to control the when and how to display elements like alerts / modals / etc. Some you can do with class names, other you have to use css. jQuery is helpful.

  4. I used a mix of mostly html tags with the occasional outputPanel with render attributes.

Doing it this way created a page that displayed and worked both inside of Classic and LEX as expected.

NOTE None of this used the Lightning Component framework and DID use the SLDS but it did "look" like lightning. If you are going to use Lightning Components you will have to do the lightning check and do double work to have it work in both UI's. Seems the interim is to make VF "Look" like lightning for now

Example of the same Wrapper page with embedded SLDS Page shown in both Classic then LEX

Classic enter image description here enter image description here enter image description here

LEX

enter image description here enter image description here enter image description here

For both UI's simply use the main wrapper page. In LEX it will strip off the header and sidebar automatically. So while you need a Wrapper page and a child page you only use the wrapper page in the tab..


Sharing Visualforce Pages Between Classic and Lightning Experience

Salesforce recommends that, wherever possible, you create Visualforce pages that behave correctly whether they run in Salesforce Classic or Lightning Experience. The benefits in terms of reduced complexity in your organization’s code and configuration are obvious. And there are a number of contexts, such as Visualforce overrides of standard actions, where you don’t have a choice. An action override always uses the same page, whether you’re running in Salesforce Classic, Lightning Experience, or Salesforce1.

It’s perfectly reasonable, though, to want slightly or significantly different behavior or styling that’s based on the user experience context in which the page is running. In Winter ’16 the ability to detect the current user experience context is extremely limited, but it should cover the essentials.

Detecting the context

There’s a technique that has proven reasonably reliable, and covers the most essential use case. The technique depends on detecting the presence of a JavaScript utility object that’s unique to Lightning Experience and Salesforce1.

function isLightningExperienceOrSalesforce1() {
    return((typeof sforce != 'undefined') && sforce && (!!sforce.one));
}

if( isLightningExperienceOrSalesforce1() ) {
    // Do something for Lightning Experience
}
else {
    // Use classic Visualforce
}