Code Monkey home page Code Monkey logo

ssg's Introduction

Statamic Static Site Generator

Generate static sites with Statamic.

Installation

You can install the Static Site Generator package with the following command:

php please install:ssg

The command will install the statamic/ssg package via Composer, optionally publish the configuration file and prompt you if you wish to install the spatie/fork package for running multiple workers.

Usage

Run the following command:

php please ssg:generate

Your site will be generated into a directory which you can deploy however you like. See Deployment Examples below for inspiration.

Multiple Workers

For improved performance, you may spread the page generation across multiple workers. This requires Spatie's Fork package. Then you may specify how many workers are to be used. You can use as many workers as you have CPU cores.

composer require spatie/fork
php please ssg:generate --workers=4

Routes

Routes will not automatically be generated. You can add any additional URLs you wish to be generated by adding them to the urls array in the config file.

'urls' => [
    '/this-route',
    '/that-route',
],

You can also exclude single routes, or route groups with wildcards. This will override anything in the urls config.

'exclude' => [
    '/secret-page',
    '/cheat-codes/*',
],

Dynamic Routes

You may add URLs dynamically by providing a closure that returns an array to the addUrls method.

use Statamic\StaticSite\SSG;

class AppServiceProvider extends Provider
{
    public function boot()
    {
        SSG::addUrls(function () {
            return ['/one', '/two'];
        });
    }
}

Pagination Routes

Wherever pagination is detected in your antlers templates (eg. if you use the paginate param on the collection tag), multiple pages will automatically be generated with /articles/page/2 style urls.

You may configure a custom routing style in config/statamic/ssg.php:

'pagination_route' => '{url}/{page_name}/{page_number}',

Post-generation callback

You may optionally define extra steps to be executed after the site has been generated.

use Statamic\StaticSite\SSG;

class AppServiceProvider extends Provider
{
    public function boot()
    {
        SSG::after(function () {
            // eg. copy directory to some server
        });
    }
}

Glide Images

The default configuration of Statamic is to have Glide use "dynamic" images, which means that the glide tag will only output URLs. The images themselves will be generated when the URLs are visited. For a static site, this no longer makes sense since it will typically be deployed somewhere where there is no dynamic Glide route available.

By default, the SSG will automatically reconfigure Glide to generate images into the img directory whenever glide tags are used. This is essentially Glide's custom static path option.

You can customize where the images will be generated:

'glide' => [
    'directory' => 'images',
],

If you are using a custom glide disk, you can tell the SSG to leave it alone:

'glide' => [
    'override' => false,
],

And then copy the images over (or create a symlink) after generating has completed:

SSG::after(function () {
    $from = public_path('img');
    $to = config('statamic.ssg.destination').'/img';

    app('files')->copyDirectory($from, $to);
    // or
    app('files')->link($from, $to);
});

Triggering Command Failures

If you are using the SSG in a CI environment, you may want to prevent the command from succeeding if any pages aren't generated (e.g. to prevent deployment of an incomplete site).

By default, the command will finish and exit with a success code even if there were un-generated pages. You can tell configure the SSG to fail early on errors, or even on warnings.

'failures' => 'errors', // or 'warnings'

Deployment Examples

These examples assume your workflow will be to author content locally and not using the control panel in production.

Deploy to Netlify

Deployments are triggered by committing to Git and pushing to GitHub.

  • Create a site in your Netlify account
  • Link the site to your desired GitHub repository
  • Add build command php please ssg:generate (if you need to compile css/js, be sure to add that command too and execute it before generating the static site folder. e.g. npm install && npm run build && php please ssg:generate).
  • Set publish directory storage/app/static

After your site has an APP_URL...

  • Set it as an environment variable. Add APP_URL https://thats-numberwang-47392.netlify.com

Finally, generate an APP_KEY to your .env file locally using php artisan key:generate and copy it's value, then...

  • Set it as an environment variable. Add APP_KEY [your app key value]

S3 Asset Containers

If you are storing your assets in an S3 bucket, the .envs used will need to be different to the defaults that come with Laravel, as they are reserved by Netlify. For example, you can amend them to the following:

# .env
AWS_S3_ACCESS_KEY_ID=
AWS_S3_SECRET_ACCESS_KEY=
AWS_S3_DEFAULT_REGION=
AWS_S3_BUCKET=
AWS_URL=

Be sure to also update these in your s3 disk configuration:

// config/filesystems.php
's3' => [
    'driver' => 's3',
    'key' => env('AWS_S3_ACCESS_KEY_ID'),
    'secret' => env('AWS_S3_SECRET_ACCESS_KEY'),
    'region' => env('AWS_S3_DEFAULT_REGION'),
    'bucket' => env('AWS_S3_BUCKET'),
    'url' => env('AWS_URL'),
],

Deploy to Vercel

Deployments are triggered by committing to Git and pushing to GitHub.

  • Create a new file called ./build.sh and paste the code snippet below.
  • Run chmod +x build.sh on your terminal to make sure the file can be executed when deploying.
  • Import a new site in your Vercel account
  • Link the site to your desired GitHub repository
  • Add build command ./build.sh
  • Set output directory to storage/app/static
  • Add environment variable in your project settings: APP_KEY <copy & paste from dev>

Code for build.sh

Add the following snippet to build.sh file to install PHP, Composer, and run the ssg:generate command:

#!/bin/sh

# Install PHP & WGET
yum install -y amazon-linux-extras
amazon-linux-extras enable php7.4
yum clean metadata
yum install php php-{common,curl,mbstring,gd,gettext,bcmath,json,xml,fpm,intl,zip,imap}
yum install wget

# INSTALL COMPOSER
EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)"
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")"

if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ]
then
    >&2 echo 'ERROR: Invalid installer checksum'
    rm composer-setup.php
    exit 1
fi

php composer-setup.php --quiet
rm composer-setup.php

# INSTALL COMPOSER DEPENDENCIES
php composer.phar install

# GENERATE APP KEY
php artisan key:generate

# BUILD STATIC SITE
php please ssg:generate

Deploy to Surge

Prerequisite: Install with npm install --global surge. Your first deployment will involve creating an account via command line.

  • Build with command php please ssg:generate
  • Deploy with surge storage/app/static

Prerequisite: Follow the instructions to get started with Firebase hosting

  • Once hosting is set up, make sure the public config in your firebase.json is set to storage/app/static
  • (Optionally) Add a predeploy config to run php please ssg:generate
  • Run firebase deploy

ssg's People

Contributors

akoepcke avatar davidsneal avatar duncanmcclean avatar jackmcdade avatar jacksleight avatar jasonvarga avatar jesseleite avatar joshuablum avatar jsbls avatar michaellindahl avatar simonhamp avatar tao avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ssg's Issues

Non-static method Statamic\StaticSite\Generator::after() should not be called statically

I tried adding the post generator function to my AppServiceProvider as the documentation suggests but I ran into an issue:

ErrorException  : Non-static method Statamic\StaticSite\Generator::after() should not be called statically

  at /.../app/Providers/AppServiceProvider.php:21
    17|     {
    18|         // Statamic::script('app', 'cp');
    19|         // Statamic::style('app', 'cp');
    20| 
  > 21|         Generator::after(function () {
    22|             // eg. copy directory to some server
    23|         });
    24|     }

  Exception trace:

  1   Illuminate\Foundation\Bootstrap\HandleExceptions::handleError("Non-static method Statamic\StaticSite\Generator::after() should not be called statically", "/.../app/Providers/AppServiceProvider.php", [])
      /.../app/Providers/AppServiceProvider.php:21

  2   App\Providers\AppServiceProvider::boot()
      /.../vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:32

Additional URLs doesn't handle query strings

Related to issue #10 and pagination. I believe the additional URLs doesn't pass any query string variables and it's returning 404s.

    'urls' => [
        'foo',            // works
        'bar'             // works
        'bar?page=1',     // 404
    ],

I came across this when trying to generate the pagination partials statically, and I believe it's because it's requesting bar?page=1 literally and that route doesn't exist.

[✔] /
[✔] /foo
[✔] /bar
[✘] /bar?page=1 (Resulted in 404)

The routes I used for testing in web.php are as follows:

Route::get('/foo', function () { return 'foo'; });
Route::statamic('/bar', 'news._pagination', ['layout' => null]);

SSG from the Control Panel as well as SSG specific content, not full site

Hi all,

Firstly apologies if this is the wrong place/method for discussion on a feature for SSG. I've posted to statamic forum too (here) but doesnt look too lively there.

The below stuff makes reference to example repo I've setup here: https://github.com/mmltonge/statamic-ssg

The reason for the above is that I'm currently trying to make the case for statamic at my workplace but to appeal to our clients we need the SSG to work from the UI and to work a bit differently. The features missing were:

  1. Ability to generate to 2 destinations (a preview & live directory)
  2. Ability to generate from the control panel, so that an 'author' could generate content they've made
  3. Ability to generate specific content - so that on a site with thousands of pages (or much less, or much more), you dont need to do a full regen just because you made one new entry.
  4. Ability to generate content from parent down (so everything with a specific collection)

With those needs in mind, I have create an example repo where I've met the needs of 2, 3 and 4 -- and 1 will be pretty straight forward I just haven't done it yet.

The bit that's bugging me -- the way the menu links are generated, ideally only 'SSG Site' would sit in the navigation, and SSG Collection & SSG Entry would be within the section of the page specific to them. So SSG Entry would sit next to Save & Publish, for example. Does anyone have a pointed on how I can add elements into the main areas like that?

Would also be nice to figure out how to stream response of generate() to dashboard, rather than loading a view.

I can also see an obvious issue with timeout for larger generates doing it this way, so would need to handle full site generation by dispatching the normal command I'd assume, rather than running as I have it here.

Ideally this could somehow be made part of the official SSG package, but I'm limited in my knowledge of how this functionality could be added to it properly, rather than as I've done.

Call to a member function absoluteUrl() on null

It seems like since updating I'm having an issue with this absoluteUrl method:

Gathering content to be generated...

   Error

  Call to a member function absoluteUrl() on null

  at vendor/statamic/cms/src/Routing/Routable.php:59
     55▕
     56▕     public function absoluteUrlWithoutRedirect()
     57▕     {
     58▕         $url = vsprintf('%s/%s', [
  ➜  59▕             rtrim($this->site()->absoluteUrl() ?? '/', '/'),
     60▕             ltrim($this->uri(), '/'),
     61▕         ]);
     62▕
     63▕         return $url === '/' ? $url : rtrim($url, '/');

      +5 vendor frames
  6   [internal]:0
      Illuminate\Support\Collection::Illuminate\Support\Traits\{closure}(Object(Statamic\StaticSite\Page))

      +23 vendor frames
  30  please:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

If I do a quick modification to the function to test $this->site() is not null before calling ->absoluteUrl() then it seems to work not throw this error anymore.

   public function absoluteUrlWithoutRedirect()
   {
       $absoluteUrl = '/';
       if ($this->site()) { $absoluteUrl = $this->site()->absoluteUrl(); }

       $url = vsprintf('%s/%s', [
           rtrim($absoluteUrl, '/'),
           ltrim($this->uri(), '/'),
       ]);

       return $url === '/' ? $url : rtrim($url, '/');
   }

But after over-coming the first one I'm also getting this error on random pages during generation... so $site is null is causing a larger issue in other classes too?

   Error

  Call to a member function handle() on null

  at vendor/statamic/ssg/src/Generator.php:355
    351▕     }
    352▕
    353▕     protected function updateCurrentSite($site)
    354▕     {
  ➜ 355▕         Site::setCurrent($site->handle());
    356▕         Cascade::withSite($site);
    357▕
    358▕         // Set the locale for dates, carbon, and for the translator.
    359▕         // This is what happens in Statamic's Localize middleware.

      +22 vendor frames
  23  please:37

As well as this one at the end:

[✔] Generated 2105 content files

   TypeError

  Cannot access offset of type string on string

  at vendor/statamic/ssg/src/Generator.php:270
    266▕         Partyline::line("\x1B[1A\x1B[2K[✔] Generated {$results->sum('count')} content files");
    267▕
    268▕         if ($results->sum('skips')) {
    269▕             $results->reduce(function ($carry, $item) {
  ➜ 270▕                 return $carry->merge($item['errors']);
    271▕             }, collect())->each(function ($error) {
    272▕                 Partyline::line($error);
    273▕             });
    274▕         }

      +18 vendor frames
  19  please:37
      Illuminate\Foundation\Console\Kernel::handle()

Generator outputting different results than dev server

Hi! First of all, my experience with Statamic 3 so far has been nothing but enjoyable. Thanks a ton for making such a flexible system 😄

My issue:

When developing locally and previewing using php artisan serve my website behaves as normal.

When I build using ssg the pages output is not the right template.

Sourcecode: https://github.com/nehero/ozzie.sh
Live: https://ozzie.sh

The home page on local is using the right template as seen here:

Screen Shot 2020-08-30 at 12 31 20 PM

And at the source level you can see that it is overriding the template via a field:

https://github.com/nehero/ozzie.sh/blob/master/content/collections/pages/home.md

But after generating it is displaying this:

Screen Shot 2020-08-30 at 12 31 26 PM

Which is the content from a different collection called "projects"

https://github.com/nehero/ozzie.sh/blob/master/content/collections/projects/unix-time-converter.md

Let me know if there is any more info I can provide!

Bug with redirect & mounted collection on Netlify

I found when I had a page with a redirect in my pages collection to an entry in another collection (that was mounted to the redirect in my pages collection) I got a redirect loop when deployed to Netlify. However it did work fine locally.

To get around this I set up a navigation for my main navigation instead and used a link instead of an entry to link directly to the entry in the other collection and have custom link text (on the entry title).

Every page but the home generates HTML

For some reason my homepage is the only page that doesn't have HTML get generated.

My repo is public here on a branch for netlify: https://github.com/austriker27/davidalindahl__3.0/tree/netlify

With my SSG config here: https://github.com/austriker27/davidalindahl__3.0/blob/netlify/config/statamic/ssg.php
I looked at the statamic official starters and didnt see any key differences in my versus yours ssg.php files.

Here's my ENV has the APP_URL and PHP_VER

I tried adding APP_NAME to see if that helped as well.

This is deployed here:
https://elated-hugle-e6394a.netlify.app/

Support redirects?

If you have redirect routes like:

Route::permanentRedirect('somewhere', 'over/the/rainbow');

We should support generation of a meta redirect/refresh.

This could require that the user manually adds the redirect URLs to their urls config 👍

Install errors and "There are no commands defined in the "ssg" namespace"

composer require statamic/ssg

Using version ^0.2.0 for statamic/ssg
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
PHP Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar:///usr/local/bin/composer/src/Composer/DependencyResolver/RuleWatchGraph.php on line 52

Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in phar:///usr/local/bin/composer/src/Composer/DependencyResolver/RuleWatchGraph.php on line 52

php please ssg:generate

There are no commands defined in the "ssg" namespace.

On another site, I got the same but ran the ssg:generate command again and it ran with no problem

Multiple blueprints use using the same template with different fieds leak data

If multiple blueprints use the same template but don't have all the same fields, it is possible for data from one collection to leak into another.

The result of this for me was data from one page showing up on another.

The temp patch was to cross-add the missing types to the inverse pages and my problem was fixed

Config for additional URLs

We support exclude URLs but we should also support explicit additional URLs in case Statamic isn't aware of them.

SSG sometimes doesn't format dates properly

This might be a bit difficult to replicate... but I have a Github action that runs SSG daily to update the website. Sometimes it generates {{ date }} properly as September 24th, 2021 and sometimes it just prints the timestamp 2021-09-24 00:00:00.

For example:

Screenshot 2021-10-09 at 23 18 51

Screenshot 2021-10-09 at 23 18 43

I don't notice anything in the logs that's different, and the sync happens daily at the same time so nothing changes between them except new content being added.

If I do re-run the Github Action it generates the page with the normal formatted dates, so nothing changes between runs but it prints the date randomly.

TrustedProxies causes issue generating pages with custom routes

I encounter an error with SSG when generating custom pages defined in the routes files, the issue is caused by TrustedProxies middleware in Laravel.

On my site I have a custom view generated for an index for each year.

Route::statamic('articles/{year}', 'articles.years.show', [
    'layout' => 'default',
])->where('year', '[0-9]+');

In my SSG config, I loop through the article years from the start date to the current year and manually include these pages to be generated:

<?php

for ($year = 1972; $year <= date("Y"); $year ++) {
    $yearIndexes[] = "/articles/{$year}";
}

return [

    ...

    /*
    |--------------------------------------------------------------------------
    | Additional URLs
    |--------------------------------------------------------------------------
    |
    | Here you may define a list of additional URLs to be generated,
    | such as manually created routes.
    |
    */

    'urls' => array_merge(
        [
            // other urls to include
        ],
        $yearIndexes,
    ),

When I generate the static website, I encounter this error:

[✔] /articles
Generating /articles/1972...

   TypeError

  Argument 2 passed to Symfony\Component\HttpFoundation\IpUtils::checkIp4() must be of the type string, null g
iven, called in /Users/tao/Code/www.statamic/vendor/symfony/http-foundation/IpUtils.php on line 46


  at vendor/symfony/http-foundation/IpUtils.php:62
     58▕      * @param string $ip IPv4 address or subnet in CIDR notation
     59▕      *
     60▕      * @return bool Whether the request IP matches the IP, or whether the request IP is within the CI
DR subnet
     61▕      */
  ➜  62▕     public static function checkIp4(?string $requestIp, string $ip)
     63▕     {
     64▕         $cacheKey = $requestIp.'-'.$ip;
     65▕         if (isset(self::$checkedIps[$cacheKey])) {
     66▕             return self::$checkedIps[$cacheKey];

      +51 vendor frames
  52  please:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(S
ymfony\Component\Console\Output\ConsoleOutput))

I can overcome this error by commenting out the Laravel middleware... but this isn't ideal and wondering if there's a more elegant way to solve this in the SSG code.

For reference this is my TrustedProxies.php file:

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var array
     */
    protected $proxies = '*';

    /**
     * The headers that should be used to detect proxies.
     *
     * @var string
     */
    protected $headers = Request::HEADER_X_FORWARDED_ALL;
}

Video tag included on every page generated

I have a very simple default page template which I use for many collections, and I check if a video exists with the video tag and display it at the top of the page. I generated the static site and one of the videos from a file appeared on every single page using this template. Which I don't quite understand how but it's an interesting problem. So even collections that don't have a video tag in the blueprint at all, now have the same video at the top of the page, so the data must not have been cleared from a previous page?

{{ if video }}
  <div class="featured flex mt-16">
    {{ if video | is_embeddable }}
      <!-- Youtube and Video -->
      <iframe src="{{ video | embed_url }}" width="100%" height="500px" allowfullscreen></iframe>
    {{ else }}
      <!-- Other HTML5 video types -->
      <video src="{{ video | embed_url }}" allowfullscreen></video>
    {{ /if }}
  </div>
{{ /if }}

<section class="featured flex">
  <div class="w-3/4">
    <article>
      <div class="header">
        <h1>{{ title }}</h1>
        <h4 class="subtitle">{{ date }}</h4>
      </div>
      {{ content }}
    </article>
  </div>
</section>

Custom route, external data source

Yo,

is it possible to generate routes from slug using an external api as data source? I don't know what {slug} will be, since it's coming from an external source.

// routes/web.php

Route::statamic('product/{slug}', 'product.show');

If so, not sure how to define it in the config since I don't know the exact url that needs to be generated.

Thanks,

Slow when using Reponsive Images addon

Related to #55

The responsive images seems to generate more variants than I would have expected. Need to work out why, and really understand the rationale behind which variants should be generated and make the ssg use those somehow.

The addon has to do with browser size. Since there's no browser, we might need to fake something.

(@riasvdv - You don't have to spend any time on this, but if any of this sounds familiar to you, a tip in the right direction would be helpful)

Unknown Issue: FieldtypeRepository not found

The log is as follows:

Gathering content to be generated...
[✔] Gathered content to be generated
Generating 6031 content files...
Generating /wiki/leitmotif

...

   Error 

  Class "Facades\Statamic\Fields\FieldtypeRepository" not found
  at vendor/statamic/cms/src/Fields/Field.php:75
     71▕     }
     72▕ 
     73▕     public function fieldtype()
     74▕     {
  ➜  75▕         return FieldtypeRepository::find($this->type())->setField($this);
     76▕     }
     77▕ 
     78▕     public function display()
     79▕     {
      +37 vendor frames 
  38  please:37
      Illuminate\Foundation\Console\Kernel::handle()

Generating /api/partials/wiki/strength

...

[✔] Generated 3016 content files
[✔] /home/runner/work/cms/cms/public/assets copied to /home/runner/work/cms/cms/storage/app/static/assets
[✔] /home/runner/work/cms/cms/public/css copied to /home/runner/work/cms/cms/storage/app/static/css
[✔] /home/runner/work/cms/cms/public/js copied to /home/runner/work/cms/cms/storage/app/static/js
[✔] /home/runner/work/cms/cms/public/vendor copied to /home/runner/work/cms/cms/storage/app/static/vendor
[✔] /home/runner/work/cms/cms/public/favicons copied to /home/runner/work/cms/cms/storage/app/static/favicons
[✔] /home/runner/work/cms/cms/public/favicon.ico copied to /home/runner/work/cms/cms/storage/app/static/favicon.ico
[✔] /home/runner/work/cms/cms/public/robots.txt copied to /home/runner/work/cms/cms/storage/app/static/robots.txt
[✔] /home/runner/work/cms/cms/public/mix-manifest.json copied to /home/runner/work/cms/cms/storage/app/static/mix-manifest.json
[✔] /home/runner/work/cms/cms/public/my.webmanifest copied to /home/runner/work/cms/cms/storage/app/static/my.webmanifest
Static site generated into /home/runner/work/cms/cms/storage/app/static

I'll investigate more and see if I can find any more information about the issue.

Syntax error when updating Statamic and Statamic SSG

I'm getting the following syntax error when updating Statamic/SSG

I'm running composer update statamic/cms --with-all-dependencies

which results in this error:

Symfony\Component\Debug\Exception\FatalThrowableError  : syntax error, unexpected '=>' (T_DOUBLE_ARROW), expecting ')'
at /starter-kit-cool-writings/vendor/statamic/ssg/src/Generator.php:287

Can you help?

Statamic Multi-site not working correctly

I've created a simple example repository with Statamic Multi-site for two languages to demonstrate some problems using SSG.

Screenshot 2021-01-01 at 12 30 30
Screenshot 2021-01-01 at 12 53 08

Some things that work on Statamic but are currently not working correctly on the static site:

  • The Italian homepage doesn't update the navbar active state (where "current_uri" == "url")
  • The nav doesn't know which site it's on (urls don't update: "/news" vs "/it/news")
  • The background colour doesn't change based on {{ site:handle }}
  • Locales tag logic on the "news/show" layout doesn't work with locale:handle == site:handle on both sites
  • The Italian "/it/news" page doesn't show Italian news articles
  • Related news on Italian News article doesn't show Italian news articles
  • The trans tag {{ trans:news.related }} doesn't work on "news/show" layout
  • The trans tag on the homepage doesn't work either {{ trans:news.welcome }}
  • *News articles produce page__news--dinosaur-angels from url segments (in body class), but break on static site for different languages: page__it--news

Doesn't work with a base_url of "/"

Is there a reason we can't support a scheme/host-less URL pattern? I have it kinda working locally but am running in an odd URL generation bug where the base is /:/.

The primary issue lies in Request.php – it'll throw undefined index errors because there won't be a scheme or host.

URL segments leaking from a generated file to the next ones

I have a website that I just migrated from Statamic 2 to Statamic 3 and I am trying to generate a static version of it.
The css classes of body depend on the segments of the URL.

In layout.antlers.html:

...
<body class="template-{{ template }} page-{{ if segment_1 }}{{ segment_1 }}{{ else }}home{{ endif }}{{if segment_2}}-{{ segment_2 }}{{endif}}">
...

The website works well, before generating static code:

  • /solutions/retail/: <body class="template-long_page page-solutions-retail">
  • /subscribed/: <body class="template-empty page-subscribed">
  • /work/: <body class="template-long_page page-work">

In the generated website:

  • /solutions/retail/ is correct: <body class="template-long_page page-solutions-retail">
  • /subscribed/ is wrong: <body class="template-empty page-subscribed-retail">
  • /work/ is wrong: <body class="template-long_page page-work-retail">

Notice the extra -retail in the class attribute.

In the logs I can see that subscribed and work are generated right after solutions/retail, so my guess is that segment_2 has leaked to the next pages:

[✔] /solutions/retail
[✔] /subscribed
[✔] /work

Replace Statamic static cache with SSG files.

The problem is with high traffic to our website, When Statamic regenerating new static files we get errors with the leaked data on the website. Maybe there is some way to replace it with SSG files?

Generated files should respect the extension when being generated

I have a dynamic robots.txt generation setup that works fine with a dynamic statamic site. However, when this gets generated via the static site generator, I get /robots.txt/index.html instead of /robots.txt.

The same thing happens with the sitemap.xml generated by SEO Pro. SSG creates this as /sitemap.xml/index.html instead of /sitemap.xml.

The files contain the contents they’re supposed to at least.

Moving Assets on Netlify Deploy

I got Netlify deploy configured and working but my assets are located at /public/assets/ and my deploy directory is /storage/app/static. Is there a way to port or copy assets as part of the deploy process? Still new to this. Thanks for the help!

Netlify: {{ locale }} is always default

Maybe not an issue with the actual ssg package, but the output of {{ locale }} is always the default one when deployed to netlify. Works fine locally.

// config/statamic/sites.php

'sites' => [

    'default' => [
        'name' => 'default',
        'locale' => 'en',
        'url' => '/',
    ],
    'se' => [
        'name' => 'Sweden',
        'locale' => 'sv_SE',
        'url' => '/se/',
    ],
    'zh-cn' => [
        'name' => 'China',
        'locale' => 'zh_CN',
        'url' => '/zh-cn/',
    ],

]

{{ locale }} output:

https://myapp.netlify.app/ // 'default'
https://myapp.netlify.app/se // 'default'
https://myapp.netlify.app/zh-cn // 'default'

Maybe it's just not possible to use variables like this when statically generating the site?

Multisite Manual Route Errors

I'm having trouble with generating the SSG for a multisite website, with errors for some pages like this:

image

My setup is that I have pages that are paginated (just on one of the sites), so in order to make that work statically, I followed the gist to set it up as /blog/page/3 etc, and so have manual routes for those links. Running on PHP8 with multiple workers.

What I think the problem is, is that when the SSG generates, in makeContentGenerationClosures() it loops through the pages and updates the current site - those manual routes are in the pages array, but for some reason the ->site() method on the Statamic\StaticSite\Route returns null, and then subsequently returns an error.

For my scenario, I got it running without errors like this:

image

by defaulting back if null, but I have no idea if I have understood the problem correctly, and I'm having other issues with content leaking between sites, so I'm not confident enough to raise a PR!

Multisite Non-localised content leaking through

I have a multisite website set up with a number of sites, but only some of the content is localised. My homepage has an entries field, that displays in a table. On the live site, the entries that have not been localised do not show up, until we go into the dashboard and create a localised version. When I generate the SSG, however, the generated localised page shows the original locale version of those entries in the table, rather than not showing.

Live version:
image

SSG Version:
image

Interestingly, if I remove one of the entries on a localised page, it disappears in the SSG, though the others still remain the original locale. Also, even if I have a localised version of an entry, that isn't used, and the original locale entries are shown instead.

This is running on PHP8, Statamic 3.1.32, SSG 0.6.0 - not sure what other information is helpful!

Should generate multi-site error pages

On my Statamic site I have error pages that are localised automatically depending on the language:

/404.html (English)
/fr/404.html (French)

When SSG runs it generates the 404.html pages but not error pages for each multi-site. Now, depending on the host for the static website it might be a bit difficult to route errors to /fr/404.html unless you do some custom handling.. but it is possible with Lambda for example if you have that set up.

So it would be nice for SSG to generate them anyway for us, or the docs should mention that as an edge-case so we can add our own urls to generate them in AppServiceProvider.php if we are building a more complex multi-site.

Possible option for redirect tag with static sites

Understandably, the redirect tag doesn't work when generating static sites. During site generation we see:

[✘] /slug (Resulted in a 302 redirect to http://site.test/destination)

I was wondering if the output of the redirect tag could be changed to a meta refresh tag during static site generation, something like:

<meta http-equiv="refresh" content="0;URL='{{ to }}'" />

I undetstand these aren't 100% equal, but at least it would allow users to continue to use the redirect tag with static sites.

Slow when using Glide with S3

This is not really unexpected since its gotta read the images from S3.

But, I thought if I keep the glide cached images around, it would be fast. This isn't true because we create a separate Glide cache inside the ssg output directory.

ssg/src/Generator.php

Lines 101 to 103 in aa9c143

$this->app['League\Glide\Server']->setCache(
new Flysystem(new Local($this->config['destination'] . '/' . $directory))
);

Maybe there can be a "before" step where it copies the cached files over. I tried doing it manually, and it clears out the directory. Might be something that Flysystem does? Not sure.

First page of pagination doesn't generate properly

I posted a comment on the SSG pagination gist because I thought this was just related to that. However, it appears that it's an issue with the SSG + pagination, whether or not that pagination setup is used.

The reason I came to this conclusion is that I've been using the pagination feature in kind of an unusual way, and it doesn't generate correctly with the SSG. I have a list of related articles in the sidebar, and I use the pagination feature to check if there is more than one page. If there is, I display a "see more" link. Well this little list generates with random pages, which means just like the original issue, it's sometimes empty.

So for now, I'll just change this to always show the "see more" link even if there aren't more pages, but there's something weird going on with the SSG and the pagination feature.

Pagination is not supported

My home page template has the following snippet (which I think I took from the v3 docs):

    {{ paginate }}
        <div class="flex justify-between text-sm">
          <a href="{{ prev_page }}">⬅ Previous</a>
  
          {{ current_page }} of {{ total_pages }} pages
          (There {{ total_items == 1 ? 'is' : 'are' }} {{ total_items }} {{ 'post' | plural:total_items }})
          <a href="{{ next_page }}">Next ➡</a>
        </div>
    {{ /paginate }}

When generating a static site, the home page is displayed correctly. However, clicking the pagination links takes you to /?page=2, etc. Since there's no server running, the query param does nothing and the original home page is rendered.

Maybe there's a way the generator could parse the {{ collection:posts limit="10" paginate="true" as="posts" }} tag and somehow loop through/generate the pages?

Unserialize Error

After generating about ~3800 pages I receive this error:

   ErrorException

  unserialize(): Error at offset 8148 of 8178 bytes

  at vendor/spatie/fork/src/Task.php:115
    111▕         $output = $this->output;
    112▕
    113▕         if (str_starts_with($output, self::SERIALIZATION_TOKEN)) {
    114▕             $output = unserialize(
  ➜ 115▕                 substr($output, strlen(self::SERIALIZATION_TOKEN))
    116▕             );
    117▕         }
    118▕
    119▕         return $output;

      +20 vendor frames
  21  please:37

I got this with php please ssg:generate --workers=2 first and decided to try a classic php please ssg:generate but I received the same error too. After this latest update: if you don't specify the workers but still have spatie/fork code installed does it still call the fork code but runs it on 1 thread by default?

During the async call with two workers, it didn't crash immediately but a little while later this happened:

ErrorException

  socket_write(): unable to write to socket [32]: Broken pipe

  at vendor/spatie/fork/src/Connection.php:63
     59▕             }
     60▕
     61▕             $length = strlen($payload);
     62▕
  ➜  63▕             $amountOfBytesSent = socket_write($this->socket, $payload, $length);
     64▕
     65▕             if ($amountOfBytesSent === false || $amountOfBytesSent === $length) {
     66▕                 break;
     67▕             }

      +21 vendor frames
  22  please:37

I can try uninstall spatie/fork code and test the site generation again if that helps, and I'll see if I can try this on another machine with more ram and report back.

Call to member raw() on string

Hey folks,

When I try to run php please ssg:generate I'm getting these errors and not sure what is causing them. Do you have any insight or pointers?

[✘] /blog/what-is-the-uniform-trust-code-what-is-the-uniform-probate-code (Call to a member function raw() on string)
[✘] /blog/sandwich-smarter-trustworthy (Call to a member function raw() on string)
[✘] /blog/is-trust-and-estate-planning-right-for-me (Call to a member function raw() on string)
[✘] /blog/what-is-your-domicile-and-why-it-matters (Call to a member function raw() on string)
[✘] /blog/is-it-safe-to-save-personal-and-family-documents-in-the-cloud (Call to a member function raw() on string)

Change `base_url` in configuration to any value causes `ErrorException`

I am trying several options as base_url in the configuration file config/statamic/ssg.php, but the only accepted one is the default one app.url. This is very weird, and I have no idea how this is possible.

Output:

   ErrorException 

  Undefined offset: 1

  at vendor/statamic/ssg/src/Request.php:33
     29▕     }
     30▕ 
     31▕     public function getHttpHost()
     32▕     {
  ➜  33▕         $withoutScheme = rtrim(explode('://', $this->config['base_url'])[1], '/');
     34▕ 
     35▕         $length = strlen($this->getBaseUrl());
     36▕ 
     37▕         return ($length === 0) ? $withoutScheme : substr($withoutScheme, 0, -$length);

      +8 vendor frames 
  9   [internal]:0
      Illuminate\Support\Collection::Illuminate\Support\Traits\{closure}(Object(Statamic\StaticSite\Page))

      +21 vendor frames 
  31  please:37
      Illuminate\Foundation\Console\Kernel::handle(Object(Symfony\Component\Console\Input\ArgvInput), Object(Symfony\Component\Console\Output\ConsoleOutput))

Tested: app.com, test.url, https://app.url, http://app.url, https://app.url/, google.com, https://google.com.

Version: 0.2.0

Throw when SSG fail unexpectedly

Bug Description

Currently errors are swallowed in the SSG build step. This mean CI can't catch the error, which means broken sites are published.

To give a specific example I have a site where the PHP/Glide version on Netlify servers fails to transform a webp images with: Unable to decode image from file (/tmp/Glide4qCOqe) This meant the topic page /blog/topics/news failed to be generated. Failing to build pages is not unexpected but in this case glide was throwing correctly and the SSG was catching and ignoring this perhaps because it was not distinguished from a non-existent route?.

It should be possible to distinguish these errors and throw\halt the build. There is no situation where anyone wants a site with errors to be published so I think it's critical that CI can catch this and halt publishing. I'm super nervous as I have a site in production where this could happen any day.

How to Reproduce

You can force a route to throw and run SSG.

Automatically generate 404.html if a custom 404 view exists

Right now to get a custom 404 page on netlify we had to...

  1. Create a _redirects file in your project that references a fake 404 page (see docs)...
    /* /not-found 404
    
  2. Create a custom laravel 404 view at resources/views/errors/404.antlers.html
  3. Map a route for it Route::statamic('not-found', 'errors/404')
  4. Add /not-found to urls in your ssg config
  5. Add base_path('_redirects') => '_redirects' to copy in your ssg config

It looks like netlify will use 404.html if it exists, so maybe we could automatically detect if a custom 404 view exists and generate that to 404.html.

SSG should be allowed to generate site with Statamic Protect

I am planning to use a Statamic 3 server for my team, and generate a static website for general users to view. I would like to protect the admin site because it might have content we don't want to push to the static site yet or let other users see yet.

I set up Statamic Protect to use the password scheme, however when I try generate the static site it blocks and redirects the pages.

/journals/camelot/2013/2373 (Resulted in a redirect to http://localhost/!/protect/password?token=2XQ7QLvrrZx8BptdTMC90UZ8R3gjx8Ze)

How can we work around this or can SSG detect the Protect scheme and generate the static site regardless? I don't believe the redirect form would work on a static site anyway.

Redis & Fork = no SSG

Hello guys !

In an attempt to polish my Statamic stack with better performances, I enabled redis for storing the stache and added the Spatie/fork package and start testing the generation with 4 workers.

Since I could not generate correctly my static files. It close everytime like this :
image

With a lot of this kind of errors in the way (I have around 600 files to generate) :
image

However, if I switch redis for "file" driver, everything works, even with multiple workers, I could then generate all my website in a minute :)

I tried to not use any worker but I had same exceptions. I had to completely remove the fork package in order to work.
So for resume :
Redis && Fork = SSG KO
Redis without Fork = SSG OK
File driver && Fork = SSG OK

Here is my details environments :

Statamic 3.1.17 Pro
Laravel 8.42.1
PHP 8.0.5
aryehraber/statamic-logbook 2.0.2
doublethreedigital/duplicator 1.3.2
rias/statamic-position-fieldtype 2.0.1
statamic/ssg 0.6.0

Generating explicit URLs from routes requires an APP_KEY

If you specify URLs in the urls setting that use routes, they won't generate unless you have an APP_KEY. This isn't a problem locally or on a traditional staging server, but the previous behavior and current Netlify docs don't require setting an APP_KEY, so following them exactly will end up with 404s on these URLs.

I'm assuming that it's because this url is using a Route::statamic(), which requires Statamic/Laravel to run, which requires an APP_KEY and that's just the way it is, but wanted to confirm.

image

SSG should allow configuration of trailing slash for permalinks

When running statamic dynamically, URLs get standardized to no trailing slash. However, when the SSG generates a site, every page is a directory, and webservers treat them this way. Since I'm not running an apache server where I can just add a fancy htaccess rule, all my page URLs have trailing slashes.

This isn't a big deal, except that in some deployments, I now end up with every URL that doesn't have a trailing slash getting redirected to the trailing slash. This is also not generally a big deal, but now my sitemap.xml, rss feeds, and nav links don't match up with the actual URLs.

This is also apparently not a big deal in general, until you get to my third part search tool (addsearch). I'm working with them to hopefully fix the issue their bot has with the 308 redirects that my static site hosting platform (CloudFlare Pages) implements for their URL normalization (and no, I don't have enough details to know all the pieces).

This appears like it would be resolved if the URLs discovered in my nav tags, and in my sitemap, and in my RSS feeds all had a trailing slash.

I could manually "fix" some of them, but not the sitemap generated by SEO Pro. It seems this might be a useful default (or just an option) for the SSG to handle when generating permalinks and urls.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.