Because HTML, CSS, and JS continue becoming more awesome, we don’t always need a framework these days. But not using a framework shouldn’t mean that other things (not related to design/dev) become more complicated. Arjan is a simple node js tool kit that helps you take your static (html/css/js) projects to production with the minimum overhead, lowest cost, and best performance. Arjan features an easy to use CLI (made to resemble git) with intuitive commands for each tool in the kit. Because it is NOT a framework, Arjan basically has No barriers to entry.
Load is an acronym for localize, optimize, audit, deploy. Four things that we repeatedly do to our static site projects. Since these four things aren’t related to the design or the development process of the website, they may fall outside of the expertise of a regular design firm causing a higher overhead.
Arjan uses several popular node js modules and builds some functionalities on top/besides them to help you LOAD effectively, with 0 overhead. Its CLI is fast and easy to use/integrate into your current process.
With all the APIs and new features that have been and continue being added to the web, including the support for ES6 syntax it seems that vanilla js will always continue becoming more usable and powerful. So in the end, if this is what the browser is using, and its super powerful, unless we have a very specific reason, why should we be using something else that compiles into something else that then compiles into the vanilla js that the browser understands??!
the purpose of the load workflow is to allow to continue doing what your doing (i.e. using HTML5, CSS3 and VanillaJS) and help you take your projects to production with the minimum amount of overhead. Avoid learning any new frameworks. Avoid having to constantly download and maintain many things at once. Avoid having to pay for a service to do all these things for you.
you only have to do this once (when you install arjan for the first time).
npm i -g arjan-cliarjan init IAM_USER_NAME AWS_REGION -g. this will pop open a browser window with the AWS console.~/.aws/credentials on mac/linux or in C:\Users\USER_NAME\.aws\credentials on windows. [profilename]
aws_access_key_id = <YOUR_ACCESS_KEY_ID>
aws_secret_access_key = <YOUR_SECRET_ACCESS_KEY>
before being able to use arjan in a particular project you must:
cd project_patharjan init AWS_PROFILE AWS_REGION (without the -g flag)now you can run any of the LOAD commands (All of the commands are always meant to be run from the root of your project). for more info check out the CLI’s README or run arjan --help. For more information on each of the commands check out their respective sections in the docs or run arjan COMMAND --help
when you run the init command (without the -g flag) it creates some directories and files inside your project. after that, each of the commands will also generate some directories/files. bellow is a depiction of how a simple project that only consists of an index.html file would look after its undergone the LOAD commands (localize, optimize, audit, deploy). In th eexample the file was translated into spanish.
|--index.html
|--es/
| |--index.html
|--dep_pack/
| |--index.html
| |--es/
| | |--index.html
|--arjan_config/
| |--optimize_config.json
| |--audit_config.json
| |--changesets/
| |--locales/
| | |--en/
| | | |--index.json
| | |--es/
| | | |--index.json
| |--exports/
| | |--csv/
filePath.substr(0, filePath.lastIndexOf(".")).replace(/\//g, '_')Arjan Localize is node module for automatically localizing and translating html sites. It features a powerful CLI command that allows you to localize multiple pages into multiple languages with a single command. It has a modular API Since it can export content into popular formats like JSON and CSV, it may also work as a very basic content management solution for html sites.
Localization consists of adapting a product to a particular locality or region. Even though machine translation services like google translate and amazon translate have gotten impressively good, there still are several scenarios were manual intervention is needed. If you are expanding your digital product/service into a new region its important to get everything perfect. Complex grammar rules and slang often cause errors in the translation making some manual intervention or at least revision necessary. Also a project that has been correctly localized will have way better SEO. Additionally text content might not be the only thing that you want to localize; you might also need to use different images/videos and hyperlinks in your different versions.
A common practice is to create JSON files called locales that contain the text content of site/app. then instead of using words in your file you use variables that read from the locale object. This way content modification dont have to be made directly in the code. In genral this makes your internationalized project easier to maintain.
Arjan uses the id attributes already present in your html as the keys in the locale. The parser in arjan localize gets all the existing IDs of html elements with text content, and saves them in the locale. If the element didnt have an ID arjan automatically creates an ID for the object with the following format: The first 12 characters of the text, replacing spaces with underscores and adding the translation index at the end.
Arjan localize also helps you to automatically translate your JSON locales and files in up to 54 different languages. It uses AWS’s neural machine translation system which is used in amazon.com.
There’s three ways in which you can use arjan localize. The three are listed bellow with their pros and cons.
Arjan translate has a GUI at [arjan.tools/translate](http://arjan.tools/trans;ate.html). The GUI is a form with a dropzone made with super easy forms which features a node.js lambda function as its backend. The GUI is pretty limited as you cant update your translations but its good for a one time job especially if you dont like using the terminal.
cd SITE_NAMEarjan init SITE_NAME Refer to the provider setup section if you haven't used any of the cloud translation APIs.arjan translate SITE_NAME [FILENAME]the translate command generates 2 or 3 things
Once you have translated your doc you can improve all of your translations by working directly on your neatly organized JSON locale files and running the translate command with the —update flag (-u).
Arjan translations is bi-directional meaning that you can also work on the output HTML files and then run the translate command with the —backwards (-b) flag to update your JSON files.
You can also generate a single CSV file with all the translations for your site by running the translate command with the —export flag (-e). if you use both the —export and —backwards flags you can update the CSV with site data. if you provide the filename arg only translations for that file will be included in the CSV.
npm i arjan-localizeconst arjanTranslate = require('arjan-translate')
//REGION is the AWS region of your IAM role ex. 'use-east-1'
//PROFILE is the name of your desired AWS IAM profile ex. 'deafult'
arjanTranslate.Build('REGION', 'PROFILE', function(err, data){
if(err) console.log(err)
else {
//FROM is the language code of your origin file ex. 'en'
//TO is the language code of your destination file ex. 'es'
arjanTranslate.TranslateSite('FROM', 'TO');
}
})
translate locale considers that you can have 3 different routing formats for a multilingual HTML site. Lets take the following file for example: blog/posts/post1.html
blog/posts/article1/en.htmlen/blog/posts/article1.htmlblog/posts/article1/es.htmlThe example compares arjan with i18n; Lets suppose our input is an en.html file with the following content:
<section>
<h1 id="title1">Arjan is super cool</h1>
</section>
After running the translate command we would get the following output:
{ "title1":"Arjan is super cool" }<h1 id="title1"> Arjan is super cool </h1><h1 id="title1"> {{arjan.t('title1)}} </h1>Lets suppose that our input string didnt have an id attribute:
{ "arjan_is_sup1":"Arjan is super cool" }<h1 id="arjan_is_sup1"> Arjan is super cool </h1><h1> {{arjan.t('arjan_is_sup1')}} </h1>Notice that an id with the first 12 characters of the string is created. Caps are lower-cased and spaces are replaced with underscores. A number with the index of the translations is inserted at the end (in case there’s another string that starts with the same 12 chars)
HTML5 option (Coming Soon)if you are using html5 elements in your page (nav, header, section, footer) you can add the html5 option in the translate command. This will generate objects with ids of html5 elements (nav, header, section, footer) and will insert translations as children of the object they belong to. suppose were still using the example above without ids:
{ "section1":{"arjan_is_sup":"Arjan is super cool" }}<section id="section1">
<h1 id="section1_arjan_is_sup"> Arjan is super cool </h1>
</section>
<section>
<h1> {{arjan.t('section1.arjan_is_sup')}} </h1>
</section>
You can use the HTML translate tag to tell arjan if you dont want to translate a particular element by setting translate="no" in your element
| Language | Language Code |
|---|---|
| Afrikaans | af |
| Albanian | sq |
| Amharic | am |
| Arabic | ar |
| Azerbaijani | az |
| Bengali | bn |
| Bosnian | bs |
| Bulgarian | bg |
| Chinese (Simplified) | zh |
| Chinese (Traditional) | zh-TW |
| Croatian | hr |
| Czech | cs |
| Danish | da |
| Dari | fa-AF |
| Dutch | nl |
| English | en |
| Estonian | et |
| Finnish | fi |
| French | fr |
| French (Canada) | fr-CA |
| Georgian | ka |
| German | de |
| Greek | el |
| Hausa | ha |
| Hebrew | he |
| Hindi | hi |
| Hungarian | hu |
| Indonesian | id |
| Italian | it |
| Japanese | ja |
| Korean | ko |
| Latvian | lv |
| Malay | ms |
| Norwegian | no |
| Persian | fa |
| Pashto | ps |
| Polish | pl |
| Portuguese | pt |
| Romanian | ro |
| Russian | ru |
| Serbian | sr |
| Slovak | sk |
| Slovenian | sl |
| Somali | so |
| Spanish | es |
| Spanish (Mexico) | es-MX |
| Swahili | sw |
| Swedish | sv |
| Tagalog | tl |
| Tamil | ta |
| Thai | th |
| Turkish | tr |
| Ukrainian | uk |
| Urdu | ur |
| Vietnamese | vi |
Arjan Optimize helps you optimize all of your static assets with a single command. It takes into account several of the modern web dev directives and uses some of the most popular node modules for minification/compression of assets with a couple of neat features of its own.
Most CDN’s like cloudfront, allow you to compress file off the fly using GZIP. So why should you minify? Essentially minification and compression are two different techniques that can be used to reduce filesize. One technique doesnt override the the other and for optimal result you should use both. If you want to learn more about minification/gzip compression and their differences, CSS Tricks’s Chris Coyier gives a great exaplanation in this article.
Arjan optimize scans your current directory recursively and for each file with a different module depending on the files MIME type. Arjan Optimize uses:
| Input | Module used | Output | options | reason used |
|---|---|---|---|---|
| html | html-minifier | html | options | best compression |
| css | csso | css | [options](https://www.npmjs.com/package/csso#minifysource-options) | [best](http://goalsmashers.github.io/css-minification-benchmark/) overall size+speed+compression |
| js | terser | js | Parse, Compress, Mangle | support for ES6, best speed & compression |
| svg | svgo | svg | options | most widely used open source option |
| jpeg | sharp | jpeg | options | fastest option |
| png | sharp | png | options | fastest option |
| webp | sharp | webp | options | fastest option |
| gif | sharp | png | options | fastest option |
| tiff | sharp | tiff | options | fastest option |
The webp option in Arjan Optimize does 2 things:
suppose we have the following image tag:
<img src="img/arjan-logo.png" class="img-fluid">
this will be replaced by:
<picture>
<source type="image/webp" srcset="img/arjan-logo.png">
<source type="image/png" srcset="img/arjan-logo.png">
<img src="img/arjan-logo.png" class="img-fluid">
</picture>
USAGE
$ arjan optimize [FILENAME]
ARGUMENTS
FILENAME name of the file i.e. index.html
OPTIONS
-c, --css minifiy css using cssnano -h, --html compress html using html-minifier -i, --images compress images and if possible maintain the format, otherwise its converted to png. -j, --js minify js using uglify js
-w, --webp saves a webp version of each image, then replaces each image instance in the html files with a picture tag.Arjan audit is a simple node module that helps automate the auditing process of static sites during the dev process using Google’s lighthouse 6.
Often times when building a site, the page speed test is one of the last things we do. Sometimes theres a surprise and the score is not that good. To avoid these surprises you can use Arjan Audit in your dev process or even integrate it into your tests.
Arjan audit uses [express](https://expressjs.com/) to serve your site and google chrome-launcher to make a headless launch of google chrome and retrieve the audits from lighthouse 6. Arjan then parses the results returned by lighthouse and returns an organized subset of the results. When used from the CLI, Arjan returns a console report that adds colors and recomendations based on your threshold value.
the threshold value is a number from 0 to 1 that represents your personal threshold for what you consider a decent enough site. the default is .8 (a B) 10 points above from this score is great, anything bellow isn't acceptable. this threshold value will filter out recommendations and add colors to your scores in the report.
arjan initarjan auditconst Audit = require('arjan-audit')
Audit('./', 'index.html', 8080, .7)
.then(data=> console.log(data))
.catch(err=>console.log(err))
the audit report is a subset of data from the JSON response of lighthouse 6. for more information on the parameters of lighthouse 6 see this link
{
"lh5_score":float,
"lh6_score":float,
"main_metrics":{
"metric":{
"title":"string",
"score":float,
"description":"string"
}
},
"improvements":{
"improvement":{
"title":"title",
"score":float,
"description":"description",
"details":{}
}
}
}
| Audit | Weight |
|---|---|
| First Contentful Paint | 20% |
| Speed Index | 27% |
| First Meaningful Paint | 7% |
| Time to Interactive | 33% |
| First CPU Idle | 13% |
Google recently recalculated the score of what they consdier a healthy fats site. The new LCP metric was introduced and the score weights and metrics were changed. for mor einformation check out Google’s Web Vitals
| Audit | Weight |
|---|---|
| First Contentful Paint | 15% |
| Speed Index | 15% |
| Largest Contentful Paint | 25% |
| Time to Interactive | 15% |
| Total Blocking Time | 25% |
| Cumulative Layout Shift | 5% |
Arjan deploy is a tool that helps you deploy static websites to the AWS cloud using Cloudformation. The tool is modular and can be used with the Arjan CLI, or programmatically in your own node.js project. Arjan Deploy gives you several different options to deploy your static sites in AWS and it also helps you import existing AWS projects, or individual resources into your websites project.
It turns out things get a bit trickier than expected when throwing in a CDN with HTTPS into the equation. As of now, to host a static site with HTTPS in AWS it requires more than one template and/or the use of multiple operations in the SDK.
Generally static sites in the cloud consist of an object storage solution (i.e. S3), a DNS (from your domain name provider or your cloud provider) a CDN or cache distribution network, and optionally may contain a digital certificate. Arjan Gives you options to add the following resources to your stack depending on your needs.
root: an s3 bucket for the root domaindns: Adds a Route53 Hosted zone to your stack. cdn: Adds an AWS Cloudfront distribution to your sites stack. More about Cloudfront.https: creates a digital certificate for your domain with AWS ACM. If you have a route53 DNS it will automatically verify your certificate. Else you must manually verify your certificate with your DNS provider. www: a reroute bucket for wwwcd your_projectarjan init PROFILE REGIONarjan deploy DOMAIN createarjan deploy DOMAIN update prod this will add a route53 DNS, a cloudfront distribution and a verified SSL ceritifcate to your stack.arjan deploy DOMAIN create prod from the start.In order to deploy a production site you must have already purchased a domain from a domain name registrar and you should have their respective interface open in order to create DNS records or transfer nameservers. there are several popular options out there; we like to use namecheap because as the name suggests it, its cheap, and it also has great service.
For an easier development workflow we have defined some setups that include dev, test and prod (production). you can customize these by additionally providing flags.
dev → test → prodAmazon Route 53 provides highly available and scalable Domain Name System (DNS), domain name registration, and health-checking web services. It is designed to give developers and businesses an extremely reliable and cost effective way to route end users to Internet applications by translating names like example.com into the numeric IP addresses, such as 192.0.2.1, that computers use to connect to each other.
AWS Route53 has a $0.50/month cost (6$ a year). Its a better option than a standard DNS because:
You can only use an external DNS if you include the CDN option and exclude the route53 option. If you are using an external DNS a CNAME record pointing to the root will invalidate all other records pointing to the root; so if you have other records pointing to your root, for example mail exchange (MX) records to send/receive email with your custom domain you will have to perform some additional steps.
Instead of pointing the CNAME record to the root, you can point to the CNAME to the www subdomain. Then you can create a reroute or FWD record in your DNS provider console to reroute all http requests coming in to the root to the www.
You can check out the following links to learn how to reroute requests in major DNS providers
sh-session
$ npm install -g arjan-cli
$ arjan COMMAND
running command...
$ arjan (-v|--version|version)
arjan-cli/0.1.0 linux-x64 node-v12.13.1
$ arjan --help [COMMAND]
USAGE
$ arjan COMMAND
...
Describe the command here
USAGE
$ arjan audit
OPTIONS
-d, --dir=dir Directory path to serve. default is root (relative to the path in which you run the
command)
-f, --file=file Path of the page you want to audit. default is index.html
-p, --port=port Port used for the test server. Default is 8080.
-t, --threshold=threshold Integer value from 0 to 1 that represents what you consider to be an acceptable lighthouse
score for your site. Its very similar to what you would consider an acceptable school test
grade.
DESCRIPTION
...
Extra documentation goes here
_See code: src/commands/audit.js_Describe the command here
USAGE
$ arjan deploy SITE ACTION [SETUP]
ARGUMENTS
SITE name of the site i.e. yoursite.com
ACTION (create|update|import|delete|upload) choose an action to perform. you can create, update, import your stack or
upload files to your bucket.
SETUP (dev|test|prod|custom) [default: dev] setup for the site - dev, test, production or custom
OPTIONS
-c, --cdn creates a CloudFront distribution for your site.
-e, --error=error [default: error.html] name of the error document
-h, --https creates and validates a TLS certificate for your site. If you arent using a route53 DNS you must
create a CNAME record manually in your DNS.
-i, --index=index [default: index.html] name of the index document. default is index.html
-r, --route53 creates a Hosted Zone in route 53. Have your current DNS provider page open and ready to add a
custom DNS.
-u, --upload=upload name of a specific file you want to upload to your site. all uploads all of the files
-w, --www creates a www s3 bucket that reroutes requests to the index.
DESCRIPTION
...
Extra documentation goes here
_See code: src/commands/deploy.js_display help for arjan
USAGE
$ arjan help [COMMAND]
ARGUMENTS
COMMAND command to show help for
OPTIONS
--all see all commands in CLI
_See code: @oclif/plugin-help_Describe the command here
USAGE
$ arjan init [REGION] [PROFILE]
ARGUMENTS
REGION [default: us-east-1] AWS Region
PROFILE [default: default] AWS Profile
OPTIONS
-a, --audit builds required files/dirs for arjan audit
-d, --deploy builds required files/dirs for arjan deploy
-l, --localize builds required files/dirs for arjan localize
-o, --optimize builds required files/dirs for arjan optimize
DESCRIPTION
...
Extra documentation goes here
_See code: src/commands/init.js_Describe the command here
USAGE
$ arjan localize LANGUAGE [FILES]
ARGUMENTS
LANGUAGE origin language of the file/s.
FILES name of the file you want to translate -only html files accepted. Use all to translate all of your html
files (default).
OPTIONS
-b, --backwards Update JSON locale accoridng to changes made in the HTML file. Must be used together with
the update flag.
-c, --create Create locale/s for your site. When used with translate flags, it generates a translated
version of the locale and the HTML.
-e, --export Creates a CSV file for your JSON locale.
-i, --import Update JSON locale from changes made in the CSV file
-t, --translate=translate desired translation language. You may apply this flag multiple times to translate into
multiple languages.
-u, --update Update HTML file accoridng to changes made in the JSON locale.
DESCRIPTION
...
Extra documentation goes here
_See code: src/commands/localize.js_Describe the command here
USAGE
$ arjan optimize [FILENAME]
ARGUMENTS
FILENAME name of the file i.e. index.html
OPTIONS
-c, --css minifiy css using cssnano
-h, --html compress html using html-minifier
-i, --images compress images and if possible maintain the format. otherwise its converted to png.
-j, --js minify js using uglify js
-w, --webp saves a webp version of each image, then replaces each image instance in the html files with a picture
tag.
DESCRIPTION
...
Extra documentation goes here
_See code: src/commands/optimize.js_Describe the command here
USAGE
$ arjan upload
OPTIONS
-n, --name=name name to print
DESCRIPTION
...
Extra documentation goes here
_See code: src/commands/upload.js_
csvToJson(lang, csv)
scanFolder(currentDirPath, outputDir, ignorePaths, callback)contents: string
- outputDir: string: output directory in which to copy the file to.
compressImages(filePath, output, imageArr, svgoConfig)
compressWebp(filePath, outputDir)
replaceWebp(imgPath, html)
## Arjan AuditrunAudit(dir, index, port, threshold)index: string: path of the file you want to audit; typically index.html.
- port: int: desired port number to use in the audit.
deployStack(domainName, template, existingResources, importAction)
createChangeSet(stackName, template, existingResources, importAction)
requestCertificate(domainName)
validateCertificate
createCertificate
importCertificate(domain, template, existingResources, https, route53, certArn)
stackExists(stackName)
bucketExists(domainName)
distributionExists
certificateExists(domainName)
hostedZoneExists(domainName)
newHostedZone(stackName)