├── .gitignore ├── LICENSE ├── README.md ├── generate-static.sh ├── netcrafter.php ├── partials ├── footer.php ├── header.php └── html.php ├── plugins └── .gitkeep ├── public ├── index.php ├── made-with-netcrafter.gif ├── netcrafter.gif └── styles.css └── serve-website.sh /.gitignore: -------------------------------------------------------------------------------- 1 | static/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Chris Kempson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #  2 | Fire up your single-core 500Mhz CPU, double-click on your entirely legal copy of Frontpage/Dreamweaver, ready your GIFs, and lovingly craft your small part of the Internet with finger generated HTML and your new best friend - Netcrafter! 3 | 4 | Netcrafter is a ~~religious cult~~, ~~life-philosophy~~, way of building websites that unashamedly slaps you in the face with [HTML - the future of the Internet](https://blog.neocities.org/blog/2015/02/27/we-are-the-future.html). The magic of Netcrafter is made possible by a scripting language that has started to gain traction in today's World Wide Web known as [PHP](https://web.archive.org/web/20000301133004/http://php.net/) (Personal Home Page) language. With Netcrafter you'll be churning out cool websites before the dot-com bubble has even burst! 5 | 6 | **Scientific Facts:** 7 | * Netcrafter is lighter than air and fits inside a [single PHP file](https://github.com/chriskempson/netcrafter/blob/master/netcrafter.php) less than 100 SLOC's long and takes up just a few KBs on your floppy disk! 8 | * Depending of the nature of your ~~adult website~~ life modelling appreciation website, you'll hopefully have no need for PHP on your server of the webs. Just [generate static HTML](#generate-static-html) and be on your merry way to _server-side scripting-less nirvana™_. 9 | * Recent entirely-fabricated studies show, users of Netcrafter may have lower stress levels and may experience a boost in the production of endorphins. [1](#addendum) 10 | 11 | ## Up and running before your dial-up has time to sync! 12 | Shove this in your post-PHP-CLI-installed terminal: 13 | 14 | git clone git@github.com:chriskempson/netcrafter.git my-first-website 15 | cd my-first-website 16 | ./serve-website.sh 17 | 18 | Next, point a modern browser (e.g. Netscape Navigator, Internet Explorer) at http://localhost:8000. Now, marvel (in awestruck silence) at the breathtakingly stunning welcome page. 19 | 20 | ## The lowdown 21 | An ultra minimalist, ultra simple way of creating the next generation of HTML/CSS/JS websites by hand. 22 | Essentially the core philosophy of Netcrafter boils down to this: 23 | 24 | - Partials - Reusable, small HTML snippets (a la your old friend SSI) 25 | - Meta Data - Attach and retrieve information to your HTML pages using \ tags! 26 | - Plugins - Power up your HTML with quick and dirty PHP hacks 27 | - Directories - Simply use real directories to structure your website 28 | - Static HTML - Blazingly fast, next-gen static content generator called WGET 29 | 30 | ### Partials 31 | Partials are little snippets of HTML you can reuse across multiple pages just like your friend SSI. 32 | 33 | ```php 34 | = partial('navigation') ?> 35 | ``` 36 | ### Meta 37 | You can add meta data to your HTML pages with... meta tags. 38 | 39 | ```html 40 | 41 | ``` 42 | 43 | You can get meta data for the current html page anywhere in your site with: 44 | 45 | ```php 46 | = meta('date') ?> 47 | ``` 48 | 49 | Or grab all available meta data as an array with: 50 | 51 | ```php 52 | = meta() ?> 53 | ``` 54 | 55 | You might also want to grab meta data for another file: 56 | 57 | ```php 58 | = meta_from_file('about.php', 'date') ?> 59 | ``` 60 | 61 | Or grab all available meta as an array with: 62 | 63 | ```php 64 | = meta_from_file('about.php') ?> 65 | ``` 66 | 67 | ### Plugins 68 | Plugins are simple to use in any of your HTML pages: 69 | ```php 70 | = years_since('1985') ?> 71 | ``` 72 | 73 | ### Directories 74 | Want to add a new page? Just add a new directory with an index.php inside it. 75 | 76 | An example directory structure might look like: 77 | 78 | website 79 | | partials/ 80 | | - html.php 81 | | - footer.php 82 | | - header.php 83 | | - navigation.php 84 | | plugins/ 85 | | years-since/ 86 | | - plugin.php 87 | | publc/ 88 | | about/ 89 | | - index.php 90 | | - index.php 91 | | - styles.css 92 | ! - webcrafter.php 93 | 94 | An example HTML page might look like: 95 | ```php 96 | 97 | 98 |
You are surfing the information highway!
105 | 106 | 107 | ``` 108 | 109 | ### Generate Static HTML 110 | Generate static html and check for broken internal links with: 111 | 112 | ./generate_static.sh 113 | 114 | Provided your box has wget installed (slap your wrist if it doesn't), this will export a static version of your website to a `static` directory. You can now ssh, rsync, ftp, telnet your site up your server. 115 | 116 | Why not get a huge 1GB of ad-free hosting by grabbing a free account at [Neocities](https://neocities.org) and adding the following to the `./generate_static.sh` script 117 | 118 | neocities push $STATIC_DIR 119 | 120 | ## Writing Plugins 121 | To create a new ~~quick and dirty PHP hack~~ beautifully authored plugin, just add a new directory with a name of your very own choosing to the plugins directory and create a new `plugin.php` file within. All you need to do now is add some lovely code to your shiny new plugin. e.g. a file called `plugins/years_since/plugin.php` might contain the following: 122 | 123 | ```php 124 | 128 | * 129 | * @param string $string Text to be converted to a date 130 | * 131 | * @return string 132 | */ 133 | function years_since($date) { 134 | $date = date('Ymd', strtotime($date)); 135 | $diff = date('Ymd') - $date; 136 | return substr($diff, 0, -4); 137 | } 138 | ``` 139 | 140 | ## What the Netcrafter? 141 | I used a few static content generators before but I was always forgetting the [tens](https://learn.cloudcannon.com/jekyll-cheat-sheet/) and [hundreds](https://gohugo.io/documentation/) of features, variables and commands and soon became tired of having to search through documentation. I just wanted to build an HTML website, I didn't care for learning about the varied nuances of a static content generator! So I ended up building my own consisting of a single PHP file and a couple of scripts weighing in at a few KBs. 142 | 143 | Initially I set about trying to make a website with HTML/CSS alone like I used to back in the 90's, even saying hello again to that old shady customer Mr. SSI. However, it wasn't long before I saw sense and decided to include a scripting language choosing PHP since it runs on all of my toasters (and my neighbours fridge, (and her neighbours kettle or so I'm told)). However, as HTML is the focus here and since I firmly believe that perfection is achieved not when there is nothing left to add, but when there is nothing left to take away, I tried to use as little PHP as possible when building this. 144 | 145 | For the past year or so I've been enjoying using what is now Netcrafter, or rather, I've been enjoying working on my HTML websites and not having to even think about the fact that I'm using Netcrafter. Now is perhaps the time to share my little creation in the hopes that other HTML lovers will find a place in their heart and their servers for Netcrafter. 146 | 147 | Get Netcrafting! /end cheesy sign-off 148 | 149 | --- 150 | 151 | ### Addendum 152 | 1 Although trends may have suggested that Netcrafter use may be addictive, it is important to gain a sense of perspective regarding this matter, therefore I would like to draw your attention to the fact that, as of yet, there have been no cases in which Netcrafter was proven to be a contributing factor to the death of an individual. 153 | -------------------------------------------------------------------------------- /generate-static.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # generate-static.sh - chriskempson.com 4 | # 5 | # Generates a static version of a locally hosted website and warns the user 6 | # of any broken internal links. 7 | 8 | STATIC_DIR="./static" 9 | DOMAIN="127.0.0.1" 10 | PORT="8000" 11 | 12 | # Uncommenting this will create a version that works offline without being 13 | # hosted locally as links such as 'pages/about' will become 14 | # 'pages/about/index.php' and so on. 15 | # PORTABLE="--convert-links" 16 | 17 | # Off we go 18 | printf "\n---- Scraping site with WGET...\n\n" 19 | 20 | # Delete the previous scrape 21 | rm --force --recursive $STATIC_DIR/* 22 | 23 | # Build the static site by scraping localhost with wget and save the output 24 | # of wget for processing with grep 25 | RESULT=$(wget --recursive --page-requisites --no-parent --no-host-directories \ 26 | --execute robots=off --domains $DOMAIN --directory-prefix=$STATIC_DIR \ 27 | --restrict-file-names=nocontrol \ 28 | $PORTABLE \ 29 | http://$DOMAIN:$PORT/robots.txt \ 30 | http://$DOMAIN:$PORT \ 31 | 2>&1) 32 | 33 | # Display broken links 34 | # Shows 4 lines above match so we can see the requested URL that has an issue 35 | echo "$RESULT" | grep -B4 -i "failed\|error"; 36 | 37 | # Display stats 38 | # For the curiously minded 39 | echo "$RESULT" | grep -i "^finished\|^downloaded" 40 | 41 | # The shows over 42 | printf "\n---- Static site was exported to $STATIC_DIR\n\n" 43 | -------------------------------------------------------------------------------- /netcrafter.php: -------------------------------------------------------------------------------- 1 | (.*)<\/title>/siU", 74 | file_get_contents($file), 75 | $title 76 | ); 77 | if (isset($title[1])) $file_meta['title'] = $title[1]; 78 | 79 | // Merge meta arrays 80 | $file_meta = array_merge($file_meta, get_meta_tags($file)); 81 | 82 | if ($name) return $file_meta[$name]; 83 | else return $file_meta; 84 | } 85 | 86 | // **** PLUGINS ************************************************************* 87 | // Plugins must follow the convention plugin_path/plugin_folder/plugin.php 88 | // Any plugin that outputs text must return text not echo it. 89 | foreach (glob(PLUGIN_PATH . '*/plugin.php') as $filename) 90 | { 91 | include $filename; 92 | } 93 | 94 | // **** INIT **************************************************************** 95 | 96 | // Deliver a 404 if a file doesn't exist when no filename is requested 97 | if (!is_file(DOCUMENT_ROOT . $_SERVER["REQUEST_URI"]. '/index.php')) { 98 | http_response_code(404); 99 | die('File ' . $_SERVER["REQUEST_URI"] . '/index.php not found.'); 100 | } 101 | 102 | // Get the ball rolling with the first partial 103 | partial('html'); -------------------------------------------------------------------------------- /partials/footer.php: -------------------------------------------------------------------------------- 1 |