Foundation-emails: Best Practice - Multiple Clients / Project Setup?

Created on 14 Feb 2017  路  30Comments  路  Source: foundation/foundation-emails

What's best practice for setting up multiple clients?

Should I just clone the repository for every client / project or is there a way to setup the src directory to handle multiple clients or projects?

Most helpful comment

Hi @Creativenauts,

this project is not abandoned. We are currently working on Foundation Sites and will also work on Foundation Emails again.

All 30 comments

@xstortionist Cloning the entire thing for each client will work, but with all the node modules required I quickly steered clear of that option. In my situation, I'm creating email campaigns for one main company, but often create them for different global regions. I adopted a file naming convention that includes the country code and language to keep things straight.

That said, another developer here added another parameter to the gulp file such that I could redefine the src directory with a command line parameter when firing up the build/watch process. I'll go back to find the code, or you can experiment yourself. I imagine this would be a useful tactic for handling multiple clients.

@davehoran thank you. I would greatly appreciate knowing exactly how others are setting this up without having to clone the repository for every new client. I dredd that! LOL!

@davehoran current problem I'm having right now is gulp fails if I'm not using "app.scss"

I'm looking to have a file directory similar to how I currently have the pages directory setup.

structure

I'm also running into an issue with the layouts directory. I'm looking to have custom layouts based on template variations that I use for A/B testing which requires different css. Do you know if it's possible for "layout:" to include nested folders?

subject: Possible Opportunity Physical Therapist Assistant
layout: clients/insearch-medical/option-a
---

This gets me closer to where I need to be at:

gulp.src('src/pages//.html')
gulp.src('src/assets/scss/
/.scss')

Only thing left I need to figure out is the whole layout: having ability to include sub folders.

@xstortionist You are correct, you can modify the gulpfile to look in other places. I'll have to look into the app.scss issue, as you should be able to change the references to the file in the layout. I do believe there was an issue with the layout subfolders.

@rafibomb Was this feature of having subfolders for layouts been added in already, or is it part of the release plan?

@davehoran I have corrected the app.scss issue by modifying the gulp file.

Sub folders actually work but the naming convention needs to be unique.

For example, you could not have two files with the same name in two different sub folders. I have created a sub folder for "clients/insearch-medical/im-option-a.html" and if I use "layout: im-option-a" it works as expected but would be nice to have the ability to call the sub-folders directly to help minimize confusion when I have other developers helping me out with this project.

meh, now i seem to have created some sort of inline loop. Had to gitbash to delete thousands of directories that were created.

If anyone has solution for this, I would love to hear it. Cloning repo is 28k files and about 170mb.

I have this setup and working. Modified gulp file to only build based on a specific folder structure. Works great and haven't had a problem with it thus far.

Awesome.

@xstortionist If you can, post your gulp file so others can find it later when they run into the same issues.

@davehoran I will once I get this fully ironed out. I'm still running into issues here and there. For example, I cannot get inliner to recognize background-image, it refuses to replace assets/img directory and I use them for all of my hero headers.

@xstortionist Do you have the tag in place to handing the background images?
http://foundation.zurb.com/emails/docs/wrapper.html

When you say replace the assets/img dir, you talking about the dist/assets/img dir? TBH, I've managed the images in production separately. I get the images sized and such properly for the templates I'm using, then upload them to the CDN we have setup (Azure). I then have a page variable that contains the CDN path.

Because of this, I have removed the image processing from the gulp functions I call. I'm sure I'm missing out on some image compression, etc. So there is room for improvement in my own process.

@davehoran for now I just hardcode the background image from my AWS S3 Bucket.

Here is my gulp file you requested. All you do is create "campaigns" directory in root of project and then create folder for each campaign / client / project. From there, just copy the src file that comes from the repo and paste that into your "campaign > project" folder.

Console Command: npm start -- --campaign="project"

import gulp     from 'gulp';
import plugins  from 'gulp-load-plugins';
import browser  from 'browser-sync';
import rimraf   from 'rimraf';
import panini   from 'panini';
import yargs    from 'yargs';
import lazypipe from 'lazypipe';
import inky     from 'inky';
import fs       from 'fs';
import siphon   from 'siphon-media-query';
import path     from 'path';
import merge    from 'merge-stream';
import beep     from 'beepbeep';
import colors   from 'colors';

const $ = plugins();

// Look for the --production flag
const PRODUCTION = !!(yargs.argv.production);
const EMAIL = yargs.argv.to;

// Declar var so that both AWS and Litmus task can use it.
var CONFIG;

var campaign_root = 'campaigns';
var campaign = campaign_root + '/' + yargs.argv.campaign;

// Build the "dist" folder by running all of the above tasks
gulp.task('build',
  gulp.series(clean, pages, sass, images, inline));

// Build emails, run the server, and watch for file changes
gulp.task('default',
  gulp.series('build', server, watch));

// Build emails, then send to litmus
gulp.task('litmus',
  gulp.series('build', creds, aws, litmus));

// Build emails, then send to EMAIL
gulp.task('mail',
  gulp.series('build', creds, aws, mail));

// Build emails, then zip
gulp.task('zip',
  gulp.series('build', zip));

// Build emails, then zip
gulp.task('zip',
  gulp.series('build', zip));

// Delete the "dist" folder
// This happens every time a build starts
function clean(done) {
  rimraf(campaign+'/dist', done);
}

// Compile layouts, pages, and partials into flat HTML files
// Then parse using Inky templates
function pages() {
  return gulp.src(campaign+'/src/pages/**/*.html')
    .pipe(panini({
      root: campaign+'/src/pages',
      layouts: campaign+'/src/layouts',
      partials: campaign+'/src/partials',
      helpers: campaign+'/src/helpers',
      data: campaign+'/src/data'
    }))
    .pipe(inky())
    .pipe(gulp.dest(campaign+'/dist'));
}

// Reset Panini's cache of layouts and partials
function resetPages(done) {
  panini.refresh();
  done();
}

// Compile Sass into CSS
function sass() {
  return gulp.src(campaign+'/src/assets/scss/**/*.scss')
    .pipe($.if(!PRODUCTION, $.sourcemaps.init()))
    .pipe($.sass({
      includePaths: ['node_modules/foundation-emails/scss']
    }).on('error', $.sass.logError))
    .pipe($.if(PRODUCTION, $.uncss(
      {
        html: [campaign+'/dist/**/*.html']
      })))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(campaign+'/dist/css'));
}

// Copy and compress images
function images() {
  return gulp.src(campaign+'/src/assets/img/**/*')
    .pipe($.imagemin())
    .pipe(gulp.dest(campaign+'/./dist/assets/img'));
}

// Inline CSS and minify HTML
function inline() {
  return gulp.src(campaign+'/dist/*.html')
    .pipe($.if(PRODUCTION, inliner(campaign+'/dist/css/app.css')))
    .pipe(gulp.dest(campaign+'/dist'));
}

// Start a server with LiveReload to preview the site in
function server(done) {
  browser.init({
    server: campaign+'/dist'
  });
  done();
}

// Watch for file changes
function watch() {
  gulp.watch(campaign+'/src/pages/**/*.html').on('all', gulp.series(pages, inline, browser.reload));
  gulp.watch([
    campaign+'/src/layouts/**/*',
    campaign+'/src/partials/**/*']).on('all', gulp.series(resetPages, pages, inline, browser.reload));
  gulp.watch([
    campaign+'/../scss/**/*.scss',
    campaign+'/src/assets/scss/**/*.scss']).on('all', gulp.series(resetPages, sass, pages, inline, browser.reload));
  gulp.watch(campaign+'/src/assets/img/**/*').on('all', gulp.series(images, browser.reload));
}

// Inlines CSS into HTML, adds media query CSS into the <style> tag of the email, and compresses the HTML
function inliner(css) {
  var css = fs.readFileSync(css).toString();
  var mqCss = siphon(css);

  var pipe = lazypipe()
    .pipe($.inlineCss, {
      applyStyleTags: false,
      removeStyleTags: false,
      applyLinkTags: true,
      removeLinkTags: true
    })
    .pipe($.replace, '<!-- <style> -->', `<style>${mqCss}</style>`)
    .pipe($.replace, '<link rel="stylesheet" type="text/css" href="css/option-a.css">', '')
    .pipe($.htmlmin, {
      collapseWhitespace: true,
      minifyCSS: true
    });

  return pipe();
}

// Ensure creds for Litmus are at least there.
function creds(done) {
  var configPath = './config.json';
  try { CONFIG = JSON.parse(fs.readFileSync(configPath)); }
  catch(e) {
    beep();
    console.log('[AWS]'.bold.red + ' Sorry, there was an issue locating your config.json. Please see README.md');
    process.exit();
  }
  done();
}

// Post images to AWS S3 so they are accessible to Litmus and manual test
function aws() {
  var publisher = !!CONFIG.aws ? $.awspublish.create(CONFIG.aws) : $.awspublish.create();
  var headers = {
    'Cache-Control': 'max-age=315360000, no-transform, public'
  };

  return gulp.src([
      campaign+'/./dist/assets/img/**/*',
      campaign+'/./dist/css/**/*'
    ])
    // publisher will add Content-Length, Content-Type and headers specified above
    // If not specified it will set x-amz-acl to public-read by default
    .pipe(publisher.publish(headers))

    // create a cache file to speed up consecutive uploads
    //.pipe(publisher.cache())

    // print upload updates to console
    .pipe($.awspublish.reporter());
}

// Send email to Litmus for testing. If no AWS creds then do not replace img urls.
function litmus() {
  var awsURL = !!CONFIG && !!CONFIG.aws && !!CONFIG.aws.url ? CONFIG.aws.url : false;

  return gulp.src(campaign+'/dist/**/*.html')
    .pipe($.if(!!awsURL, $.replace(/=('|")(\/?assets\/img)/g, "=$1"+ awsURL)))
    .pipe($.litmus(CONFIG.litmus))
    .pipe(gulp.dest(campaign+'/dist'));
}

// Send email to specified email for testing. If no AWS creds then do not replace img urls.
function mail() {
  var awsURL = !!CONFIG && !!CONFIG.aws && !!CONFIG.aws.url ? CONFIG.aws.url : false;

  if (EMAIL) {
    CONFIG.mail.to = [EMAIL];
  }

  return gulp.src(campaign+'/dist/*.html')
    .pipe($.if(!!awsURL, $.replace(/=('|")(\/?assets\/img)/g, "=$1"+ awsURL)))
    .pipe($.mail(CONFIG.mail))
    .pipe(gulp.dest(campaign+'/dist'));
}

// Copy and compress into Zip
function zip() {
  var dist = campaign+'/dist';
  var ext = '.html';

  function getHtmlFiles(dir) {
    return fs.readdirSync(dir)
      .filter(function(file) {
        var fileExt = path.join(dir, file);
        var isHtml = path.extname(fileExt) == ext;
        return fs.statSync(fileExt).isFile() && isHtml;
      });
  }

  var htmlFiles = getHtmlFiles(dist);

  var moveTasks = htmlFiles.map(function(file){
    var sourcePath = path.join(dist, file);
    var fileName = path.basename(sourcePath, ext);

    var moveHTML = gulp.src(sourcePath)
      .pipe($.rename(function (path) {
        path.dirname = fileName;
        return path;
      }));

    var moveImages = gulp.src(sourcePath)
      .pipe($.htmlSrc({ selector: 'img'}))
      .pipe($.rename(function (path) {
        path.dirname = fileName + '/' + path.dirname;
        return path;
      }));

    return merge(moveHTML, moveImages)
      .pipe($.zip(fileName+ '.zip'))
      .pipe(gulp.dest(campaign+'/dist'));
  });

  return merge(moveTasks);
}

Thanks. Nice work!

Hi! How this solution works with:
npm run build
npm run mail
npm run zip
?
thnks

@konstantinklepikov see the Gulp file above from @DerekBesa

@KonstantinKlepikov i have an updated file which I will show code below to streamline my workflow a bit.

use command: npm start -- --client="your-folder-name"

import gulp     from 'gulp';
import plugins  from 'gulp-load-plugins';
import browser  from 'browser-sync';
import rimraf   from 'rimraf';
import panini   from 'panini';
import yargs    from 'yargs';
import lazypipe from 'lazypipe';
import inky     from 'inky';
import fs       from 'fs';
import siphon   from 'siphon-media-query';
import path     from 'path';
import merge    from 'merge-stream';
import beep     from 'beepbeep';
import colors   from 'colors';

const $ = plugins();

// Look for the --production flag
const PRODUCTION = !!(yargs.argv.production);
const EMAIL = yargs.argv.to;

// Declar var so that both AWS and Litmus task can use it.
var CONFIG;

/*-------------------------------------------------------------------------|
| Client Folder Variables                                                  |
|--------------------------------------------------------------------------|
| Project has been modified to allow client folders                        |
|-------------------------------------------------------------------------*/

var campaign_root = 'clients';
var campaign = campaign_root + '/' + yargs.argv.client;

/*-------------------------------------------------------------------------|
| Path Variables                                                           |
|--------------------------------------------------------------------------|
| Added project variables for ease of use                                  |
|-------------------------------------------------------------------------*/

// Base Paths
var basePaths = {
  src   : campaign+'/src/',
  dest  : campaign+'/dist/'
};

// Paths
var paths = {
  pages: {
    src       : basePaths.src + 'pages/**/*.html',
    root      : basePaths.src + 'pages',
    layouts   : basePaths.src + 'layouts',
    partials  : basePaths.src + 'partials',
    helpers   : basePaths.src + 'helpers',
    data      : basePaths.src + 'data'
  },
  sass: {
    src       : basePaths.src + 'assets/scss/**/*.scss',
    dest      : basePaths.dest + 'css',
    html      : basePaths.dest + '**/*.html',
  },
  images: {
    src       : basePaths.src + 'src/assets/img/**/*',
    dest      : basePaths.dest + './assets/img'
  },
  inline: {
    src       : basePaths.src + '*.html',
    css       : basePaths.dest + 'css/app.css'
  }
};

/*-------------------------------------------------------------------------|
| Start Zurb Gulp Tasks                                                    |
|--------------------------------------------------------------------------|
| This is the default tasks from zurb email repository                     |
|-------------------------------------------------------------------------*/

// Build the "dist" folder by running all of the below tasks
gulp.task('build',
  gulp.series(clean, pages, sass, images, inline));

// Build emails, run the server, and watch for file changes
gulp.task('default',
  gulp.series('build', server, watch));

// Build emails, then send to litmus
gulp.task('litmus',
  gulp.series('build', creds, aws, litmus));

// Build emails, then send to EMAIL
gulp.task('mail',
  gulp.series('build', creds, aws, mail));

// Build emails, then zip
gulp.task('zip',
  gulp.series('build', zip));

// Delete the "dist" folder
// This happens every time a build starts
function clean(done) {
  rimraf(basePaths.dest, done);
}

/*-------------------------------------------------------------------------|
| Compile Pages                                                            |
|--------------------------------------------------------------------------|
| Compile layouts, pages, and partials into flat HTML files                |
| Then parse using Inky templates                                          |
|-------------------------------------------------------------------------*/

function pages() {
  return gulp.src(paths.pages.src)
    .pipe(panini({
      root: paths.pages.root,
      layouts: paths.pages.layouts,
      partials: paths.pages.partials,
      helpers: paths.pages.helpers,
      data: paths.pages.data
    }))
    .pipe(inky())
    .pipe(gulp.dest(basePaths.dest));
}

/*-------------------------------------------------------------------------|
| Reset Cache                                                              |
|--------------------------------------------------------------------------|
| Reset Panini's cache of layouts and partials                             |
|-------------------------------------------------------------------------*/

function resetPages(done) {
  panini.refresh();
  done();
}

/*-------------------------------------------------------------------------|
| Sass Task                                                                |
|--------------------------------------------------------------------------|
| Compile Sass into CSS                                                    |
|-------------------------------------------------------------------------*/

function sass() {
  return gulp.src(paths.sass.src)
    .pipe($.if(!PRODUCTION, $.sourcemaps.init()))
    .pipe($.sass({
      includePaths: ['node_modules/foundation-emails/scss']
    }).on('error', $.sass.logError))
    .pipe($.if(PRODUCTION, $.uncss(
      {
        html: [paths.sass.html]
      })))
    .pipe($.if(!PRODUCTION, $.sourcemaps.write()))
    .pipe(gulp.dest(paths.sass.dest));
}

/*-------------------------------------------------------------------------|
| Image Tasks                                                              |
|--------------------------------------------------------------------------|
| Copy and compress images                                                 |
|-------------------------------------------------------------------------*/

function images() {
  return gulp.src([paths.images.src])
    .pipe($.imagemin())
    .pipe(gulp.dest(paths.images.dest));
}

/*-------------------------------------------------------------------------|
| Inline Tasks                                                             |
|--------------------------------------------------------------------------|
| Inline CSS and minify HTML                                               |
|-------------------------------------------------------------------------*/

function inline() {
  return gulp.src(paths.inline.src)
    .pipe($.if(PRODUCTION, inliner(paths.inline.css)))
    .pipe(gulp.dest(basePaths.dest));
}

/*-------------------------------------------------------------------------|
| Live Reload                                                              |
|--------------------------------------------------------------------------|
| Start a server with LiveReload to preview the site in                    |
|-------------------------------------------------------------------------*/

function server(done) {
  browser.init({
    server: basePaths.dest
  });
  done();
}

/*-------------------------------------------------------------------------|
| Watch Tasks                                                              |
|--------------------------------------------------------------------------|
| Watch for file changes                                                   |
|-------------------------------------------------------------------------*/

function watch() {
  gulp.watch(paths.pages.src).on('all', gulp.series(pages, inline, browser.reload));
  gulp.watch([paths.pages.layouts+'/**/*', paths.pages.partials+'/**/*']).on('all', gulp.series(resetPages, pages, inline, browser.reload));
  gulp.watch([campaign+'../scss/**/*.scss', paths.sass.src]).on('all', gulp.series(resetPages, sass, pages, inline, browser.reload));
  gulp.watch(paths.images.src).on('all', gulp.series(images, browser.reload));
}

/*-------------------------------------------------------------------------|
| CSS Inliner                                                              |
|--------------------------------------------------------------------------|
| Inlines CSS into HTML, adds media query CSS into                         |
| the <style> tag of the email, and compresses the HTML                    |
|-------------------------------------------------------------------------*/

function inliner(css) {
  var css = fs.readFileSync(css).toString();
  var mqCss = siphon(css);

  var pipe = lazypipe()
    .pipe($.inlineCss, {
      applyStyleTags: false,
      removeStyleTags: true,
      preserveMediaQueries: true,
      removeLinkTags: false
    })
    .pipe($.replace, '<!-- <style> -->', `<style>${mqCss}</style>`)
    .pipe($.replace, '<link rel="stylesheet" type="text/css" href="css/app.css">', '')
    .pipe($.htmlmin, {
      collapseWhitespace: true,
      minifyCSS: true
    });

  return pipe();
}

/*-------------------------------------------------------------------------|
| Litmus Credentials                                                       |
|--------------------------------------------------------------------------|
| Ensure credentials for Litmus are at least there.                        |
|-------------------------------------------------------------------------*/

function creds(done) {
  var configPath = './config.json';
  try { CONFIG = JSON.parse(fs.readFileSync(configPath)); }
  catch(e) {
    beep();
    console.log('[AWS]'.bold.red + ' Sorry, there was an issue locating your config.json. Please see README.md');
    process.exit();
  }
  done();
}

/*-------------------------------------------------------------------------|
| AWS S3 Image Upload                                                      |
|--------------------------------------------------------------------------|
| Post images to AWS S3 so they are accessible to Litmus and manual test   |
|-------------------------------------------------------------------------*/

function aws() {
  var publisher = !!CONFIG.aws ? $.awspublish.create(CONFIG.aws) : $.awspublish.create();
  var headers = {
    'Cache-Control': 'max-age=315360000, no-transform, public'
  };

  return gulp.src(paths.images.dest+'/**/*')
    // publisher will add Content-Length, Content-Type and headers specified above
    // If not specified it will set x-amz-acl to public-read by default
    .pipe(publisher.publish(headers))

    // create a cache file to speed up consecutive uploads
    //.pipe(publisher.cache())

    // print upload updates to console
    .pipe($.awspublish.reporter());
}

/*-------------------------------------------------------------------------|
| Litmus Email Testing                                                     |
|--------------------------------------------------------------------------|
| Send email to Litmus for testing.                                        |
| If no AWS creds then do not replace img urls.                            |
|-------------------------------------------------------------------------*/

function litmus() {
  var awsURL = !!CONFIG && !!CONFIG.aws && !!CONFIG.aws.url ? CONFIG.aws.url : false;

  return gulp.src(basePaths.dest+'**/*.html')
    .pipe($.if(!!awsURL, $.replace(/=('|")(\/?assets\/img)/g, "=$1"+ awsURL)))
    .pipe($.litmus(CONFIG.litmus))
    .pipe(gulp.dest(basePaths.dest));
}

/*-------------------------------------------------------------------------|
| Send Test Email                                                          |
|--------------------------------------------------------------------------|
| Send email to specified email for testing.                               |
| If no AWS creds then do not replace img urls.                            |
|-------------------------------------------------------------------------*/

function mail() {
  var awsURL = !!CONFIG && !!CONFIG.aws && !!CONFIG.aws.url ? CONFIG.aws.url : false;

  if (EMAIL) {
    CONFIG.mail.to = [EMAIL];
  }

  return gulp.src(basePaths.dest+'**/*.html')
    .pipe($.if(!!awsURL, $.replace(/=('|")(\/?assets\/img)/g, "=$1"+ awsURL)))
    .pipe($.mail(CONFIG.mail))
    .pipe(gulp.dest(basePaths.dest));
}

/*-------------------------------------------------------------------------|
| Build Zip File                                                           |
|--------------------------------------------------------------------------|
| Copy and compress into Zip                                               |
|-------------------------------------------------------------------------*/

function zip() {
  var dist = 'dist';
  var ext = '.html';

  function getHtmlFiles(dir) {
    return fs.readdirSync(dir)
      .filter(function(file) {
        var fileExt = path.join(dir, file);
        var isHtml = path.extname(fileExt) == ext;
        return fs.statSync(fileExt).isFile() && isHtml;
      });
  }

  var htmlFiles = getHtmlFiles(dist);

  var moveTasks = htmlFiles.map(function(file){
    var sourcePath = path.join(dist, file);
    var fileName = path.basename(sourcePath, ext);

    var moveHTML = gulp.src(sourcePath)
      .pipe($.rename(function (path) {
        path.dirname = fileName;
        return path;
      }));

    var moveImages = gulp.src(sourcePath)
      .pipe($.htmlSrc({ selector: 'img'}))
      .pipe($.rename(function (path) {
        path.dirname = fileName + path.dirname.replace('dist', '');
        return path;
      }));

    return merge(moveHTML, moveImages)
      .pipe($.zip(fileName+ '.zip'))
      .pipe(gulp.dest('dist'));
  });

  return merge(moveTasks);
}

Nice work Derek...and commented code!!

thank you. Maybe you know, how use command
npm run mail -- --folder="project"
for sending of one testing message (i think, you understand about what i talk: when project contain more than one html file, if i use npm run mail, zurb send on testing all mails, that be in project

I see this setup as being more useful than the default version. Any way you, @DerekBess, could make a PR, fork the project, or put this all in a Gist with more info? Running the code you have here is throwing errors because my "dist/css/app.css" does not exist. I really like what you've done. Thanks.

@oktalk Hi Justin,

There are still some quirks I'm trying to figure out. This is not the most updated version that I have, so perhaps I will create a fork for anyone who is interested in this style of setup.

I can't figure out how why .replace is not working when sending a test email. The files are getting uploaded to amazon S3 no problem but the img sources never get replaced. So I'm not sure exactly how to correct that issue at this point in time as I am by no means a javascript developer. I dabble in javascript and learn as I go along.

Other then that, what you are experiencing with app.css I believe I combated in a recent version of a project I had been working on but I have been too slammed to get back to that project. When I get it finished up I'll fork and hopefully some folks with a stronger javascript and gulp development knowledge can help optimize the crap I've done here, Heh :)

Awesome. You can ping me if you get stuck.

@oktalk that would be awesome to have some help on this. Been a lot of trial and error. I got this working well for my projects but few quirks are just bugging the crap out of me.

@DerekBess Want to mention that I love this look of this and would love to see a fork or gist for this. I'm a complete gulp/node noob but happy to help however I can.

@DerekBess - any chance you could share your current gulpfile for posterity? I'm getting errors attempting to run foundation related commands, such as foundation watch and foundation build.

$ foundation build -- --project="project-name"

[15:35:06] Error: File not found with singular glob: /Applications/MAMP/htdocs/foundation-email/projects/undefined/src/assets/scss/app.scss

My gulpfile substitutes "project" for "campaign". You can see in the error path above, the "undefined" directory which suggests the project variable isn't getting set in the command.

IF however I run: $ npm start -- --project="project-name"

It runs similar to foundation watch.

Thoughts?

ps - I think there's an error in your inline function. I modified my gulpfile to include a paths.inline.dest:

inline: {
src : basePaths.src + '.html',
dest : basePaths.dest + '
/.html',
css : basePaths.dest + 'css/app.css'
}

Then in inline:

function inline()
{
// first path formerly paths.inline.src
return gulp.src(paths.inline.dest)
.pipe($.if(PRODUCTION, inliner(paths.inline.css)))
.pipe(gulp.dest(basePaths.dest));
}

I haven't used foundation emails in a while as I haven't had an email project recently. I'll clone the repo tomorrow and mess around with it a bit. Last time I used it I had issues with sending emails for each client project. How ever I have brushed up on my JavaScript a bit since then.

@Creativenauts

Thanks for the code!
For some reason the inliner was not working on build and it was doing my head in but i finally found why it was not working. So in the paths object > inline > src should be set to basePaths.dest rather than basePaths.src.

// Paths
var paths = {
  pages: {
    src       : basePaths.src + 'pages/**/*.html',
    root      : basePaths.src + 'pages',
    layouts   : basePaths.src + 'layouts',
    partials  : basePaths.src + 'partials',
    helpers   : basePaths.src + 'helpers',
    data      : basePaths.src + 'data'
  },
  sass: {
    src       : basePaths.src + 'assets/scss/**/*.scss',
    dest      : basePaths.dest + 'css',
    html      : basePaths.dest + '**/*.html',
  },
  images: {
    src       : basePaths.src + 'src/assets/img/**/*',
    dest      : basePaths.dest + './assets/img'
  },
  inline: {
    src       : basePaths.dest + '*.html', //Changed from src to dest
    css       : basePaths.dest + 'css/app.css'
  }
};

@Creativenauts

Thanks for the code!
For some reason the inliner was not working on build and it was doing my head in but i finally found why it was not working. So in the paths object > inline > src should be set to basePaths.dest rather than basePaths.src.

// Paths
var paths = {
  pages: {
    src       : basePaths.src + 'pages/**/*.html',
    root      : basePaths.src + 'pages',
    layouts   : basePaths.src + 'layouts',
    partials  : basePaths.src + 'partials',
    helpers   : basePaths.src + 'helpers',
    data      : basePaths.src + 'data'
  },
  sass: {
    src       : basePaths.src + 'assets/scss/**/*.scss',
    dest      : basePaths.dest + 'css',
    html      : basePaths.dest + '**/*.html',
  },
  images: {
    src       : basePaths.src + 'src/assets/img/**/*',
    dest      : basePaths.dest + './assets/img'
  },
  inline: {
    src       : basePaths.dest + '*.html', //Changed from src to dest
    css       : basePaths.dest + 'css/app.css'
  }
};

Honestly, you may be better off using MJML because this repo seems to abandoned.

Hi @Creativenauts,

this project is not abandoned. We are currently working on Foundation Sites and will also work on Foundation Emails again.

Was this page helpful?
0 / 5 - 0 ratings