3 saved 4 bytes

# JavaScript (ES6), 130 130  126 bytes

L=>W=>L.every(a=>a.every(x=>(W+'').match(x,a.map(y=>s+='|'+x+y))),p=s=1)&W.every(w=>w&&(+p||w==p.slice(-1))&w=>w&&p|w==p&!w.match(s,p=w.slice(-1)))

W.every(w =>              // for each word w in W[]:
w && (                //   is this word at least 3 characters long?
p | +p ||                 //  // unless this is it the 1stfirst word,? make(p sure= that:1)
w == p.slice(-1) &             //   or does it startsstart with the last letter of the previous word?
) &      !w.match(               //   and finally make sure that: ...
!w.match(  s,                    //     ... it doesn't contain any invalid pair of letters
p = w.slice(-1)       //     and update p =to the last letter of w
)                       //   update pend toof wmatch()
)                         // end of every()


# JavaScript (ES6), 130 bytes

L=>W=>L.every(a=>a.every(x=>(W+'').match(x,a.map(y=>s+='|'+x+y))),p=s=1)&W.every(w=>w&&(+p||w==p.slice(-1))&!w.match(s,p=w))


Try it online!

W.every(w =>              // for each word w in W[]:
w && (               //   is this word at least 3 characters long?
+p ||                 //   unless this is the 1st word, make sure that:
w == p.slice(-1)   //   it starts with the last letter of the previous word
) &                     //   and finally make sure that:
!w.match(s,             //   it doesn't contain any invalid pair of letters
p = w)      //   update p to w
)                         // end of every()


# JavaScript (ES6),  130  126 bytes

L=>W=>L.every(a=>a.every(x=>(W+'').match(x,a.map(y=>s+='|'+x+y))),p=s=1)&W.every(w=>w&&p|w==p&!w.match(s,p=w.slice(-1)))


Try it online!

W.every(w =>              // for each word w in W[]:
w &&                 //   is this word at least 3 characters long?
p |                     //   is it the first word? (p = 1)
w == p &             //   or does it start with the last letter of the previous word?
!w.match(               //   and finally make sure that ...
s,                    //     ... it doesn't contain any invalid pair of letters
p = w.slice(-1)       //     and update p to the last letter of w
)                       //   end of match()
)                         // end of every()

2 added a commented version

### Step 1

We first iterate over $$\L\$$ to build a pipe-separated string $$\s\$$ consisting of all invalid pairs of letters. While doing so, we also make sure that each letter appears at least once in some word.

L.every(a =>              // for each group of letter a[] in L[]:
a.every(x =>            //   for each letter x in a[]:
(W + '')              //     coerce W[] to a string
.match(               //     and test whether ...
x,                  //       ... x can be found in it
a.map(y =>          //       for each letter y in a[]:
s += '|' + x + y  //         append '|' + x + y to s
)                   //       end of map()
)                     //     end of match()
),                      //   end of inner every()
p = s = 1               //   start with p = s = 1
)                         // end of outer every()


### Step 2

We now iterate over $$\W\$$ to test each word.

W.every(w =>              // for each word w in W[]:
w && (               //   is this word at least 3 characters long?
+p ||                 //   unless this is the 1st word, make sure that:
w == p.slice(-1)   //   it starts with the last letter of the previous word
) &                     //   and finally make sure that:
!w.match(s,             //   it doesn't contain any invalid pair of letters
p = w)      //   update p to w
)                         // end of every()


### Step 1

We first iterate over $$\L\$$ to build a pipe-separated string $$\s\$$ consisting of all invalid pairs of letters. While doing so, we also make sure that each letter appears at least once in some word.

L.every(a =>              // for each group of letter a[] in L[]:
a.every(x =>            //   for each letter x in a[]:
(W + '')              //     coerce W[] to a string
.match(               //     and test whether ...
x,                  //       ... x can be found in it
a.map(y =>          //       for each letter y in a[]:
s += '|' + x + y  //         append '|' + x + y to s
)                   //       end of map()
)                     //     end of match()
),                      //   end of inner every()
p = s = 1               //   start with p = s = 1
)                         // end of outer every()


### Step 2

We now iterate over $$\W\$$ to test each word.

W.every(w =>              // for each word w in W[]:
w && (               //   is this word at least 3 characters long?
+p ||                 //   unless this is the 1st word, make sure that:
w == p.slice(-1)   //   it starts with the last letter of the previous word
) &                     //   and finally make sure that:
!w.match(s,             //   it doesn't contain any invalid pair of letters
p = w)      //   update p to w
)                         // end of every()

1

# JavaScript (ES6), 130 bytes

Takes input as (letters)(words). Returns $$\0\$$ or $$\1\$$.

L=>W=>L.every(a=>a.every(x=>(W+'').match(x,a.map(y=>s+='|'+x+y))),p=s=1)&W.every(w=>w&&(+p||w==p.slice(-1))&!w.match(s,p=w))


Try it online!