Source codes of this website

This site is powered by Nette Framework and uses templating engine Latte. See how you can use Nette as a micro-framework.

index.php

<?php

declare(strict_types=1);

require __DIR__ . '/../vendor/autoload.php';


$configurator = new Nette\Bootstrap\Configurator;

// Enable Nette Debugger for error visualisation & logging
$configurator->enableTracy(__DIR__ . '/app/log');

// Configure libraries
Twitter::$cacheDir = Feed::$cacheDir = __DIR__ . '/app/temp/cache';
$configurator->setTempDirectory(__DIR__ . '/app/temp');

// Create Dependency Injection container from config.neon file
$configurator->addConfig(__DIR__ . '/app/config.neon');
$container = $configurator->createContainer();


// Setup routes
// https://davidgrudl.com/[cs|en]
$router = $container->getService('router');
$router->addRoute('[index.php][<lang (?-i)cs|en>]', function ($presenter, $lang) use ($container) {
    if (!$lang) {
        $lang = $container->getByType(Nette\Http\Request::class)->detectLanguage(['en', 'cs']) ?: 'cs';
        return $presenter->redirectUrl($lang);
    }

    // create template
    $template = $presenter->createTemplate()
        ->setFile(__DIR__ . '/app/' . $lang . '.latte');

    // register template helpers like {$foo|date}
    $template->addFilter('date', function ($date) use ($lang) {
        if ($lang === 'en') {
            return date('F j, Y', (int) $date);
        } else {
            static $months = [1 => 'leden', 'únor', 'březen', 'duben', 'květen', 'červen', 'červenec', 'srpen', 'září', 'říjen', 'listopad', 'prosinec'];
            $date = getdate((int) $date);
            return "$date[mday]. {$months[$date['mon']]} $date[year]";
        }
    });

    $template->addFilter('tweet', fn($s) => Twitter::clickable($s));

    $template->twitter = function ($name) use ($container) {
        try {
            return $container->getService($name)->load(Twitter::ME);
        } catch (TwitterException $e) {
            return [];
        }
    };

    $template->rss = function ($path) {
        try {
            return Feed::loadRss($path)->item;
        } catch (FeedException $e) {
            return [];
        }
    };

    $template->addFilter('texy', fn(Latte\Runtime\FilterInfo $info, $s) => (new Texy)->process($s));

    return $template;
});


// https://davidgrudl.com/sources
$router->addRoute('sources', function ($presenter) use ($container) {
    $template = $presenter->createTemplate()
        ->setFile(__DIR__ . '/app/sources.latte');

    $template->source = fn($file, $lang = null) => new Latte\Runtime\Html(preg_replace('#<br ?/?>#', '', highlight_file($file, true)));
    return $template;
});


// Run the application!
$container->getByType(Nette\Application\Application::class)->run();

app/config.neon

php:
    date.timezone: Europe/Prague

application:
    scanDirs: no

services:
    twitterDavidGrudl: DG\Twitter\Twitter(...secret keys...)

    twitterGeekovo: DG\Twitter\Twitter(...secret keys...)

app/@layout.latte

<!doctype html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="author" content="David Grudl; https://davidgrudl.com">

    <title>{block title|striphtml|trim}David Grudl.com{/block}</title>

    <link rel="stylesheet" href="{$basePath}/css/screen.css">
    <link rel="shortcut icon" href="{$basePath}/favicon.ico">
    <link href="https://fonts.googleapis.com/css?family=Bree+Serif&amp;subset=latin,latin-ext" rel="stylesheet">
</head>

<body>
    {include content}

    <script src="{$basePath}/js/jquery.js"></script>
    <script src="{$basePath}/js/jquery-ui-custom.js"></script>
    <script src="{$basePath}/js/jquery.ui.touch-punch.js"></script>
    <script src="{$basePath}/js/turn.js"></script>
    <script src="{$basePath}/js/main.js"></script>
</body>
</html>

app/cs.latte

{layout "@layout.latte"}
{block content}

<nav id="menu">
    <ul>
        <li><a href="#about">KDO JSEM</a></li>
        <li><a href="#projects">PROJEKTY</a></li>
        <li><a href="#software">SOFTWARE</a></li>
        <li><a href="#trainings">ŠKOLENÍ</a></li>
        <li><a href="#twitter">TWITTER</a></li>
        <li><a href="#blog">BLOG</a></li>
        <li><a href="#interviews">ROZHOVORY</a></li>
        <li><a href="#talks">PŘEDNÁŠKY</a></li>
        <li><a href="#contact">KONTAKT</a></li>
        <li><a href="en">english</a></li>
    </ul>
</nav>

<div id="content">
    <section id="about">
        <h1 id="logo" n:block="title">David Grudl</h1>

        <p class="lead">Otevírám dveře do světa umělé inteligence. Vymýšlím software co pohání weby, které dnes a denně používáte. Přednáším, školím, píšu.</p>

        <div id="photo"></div>
        {block|texy|indent:2}
Jsem spisovatel programů, specialista na AI, bloger a kdovíco ještě.
Začínal jsem s počítači v éře disket, mezičasem se věnoval grafice a dokonce sázel noviny. Dnes navrhuji webové aplikace a zabývám se umělou inteligencí.
Programátoři mě mohou znát jako autora řady populárních open source projektů ("Nette Framework":https://nette.org, Latte, Tracy, Texy a mnoho dalších).

Píšu blog "La Trine":www.latrine.cz, za který jsem získal nominaci na cenu Magnesia Litera, web "Uměligence":https://www.umeligence.cz věnovaný AI a odborný blog "phpFashion":https://phpfashion.com.
Naučím vás "jak správně používat AI":https://www.umeligence.cz/workshop-jazykove-modely, programátory školím jak "vyvíjet webové aplikace":www.skoleniphp.cz, občas běhám závody Spartan Race či maratony.

Sledujte mě na "Facebooku":https://www.facebook.com/davidgrudl, Twitteru jako "@davidgrudl":https://twitter.com/DavidGrudl a "@geekovo":https://twitter.com/geekovo nebo na <a rel="me" href="https://www.threads.net/@davidgrudl">Threads</a>.

"chci vědět mnohem víc » .[lead]":#more{/block}

        <hr>

        <p><a href="files/david-grudl.jpg">Foto ke stažení</a></p>
    </section>


    <section id="projects">
        <h1>Projekty</h1>

        <div class="boxes">
        <div class="box">
            <div><a href="https://nette.org" class="img"><img src="{$basePath}/images/nette.jpg" alt="Nette Framework"></a></div>
        </div>

        <div class="box">
            <h2><a href="https://nette.org">Nette Framework</a></h2>

            <p>Populární nástroj pro vytváření webových aplikací v PHP. Je srozumitelný, při programování vám vychází
            vstříc a nepřidělává vrásky. Eliminuje bezpečnostní rizika, ctí AJAX, DRY, KISS, MVC a znovupoužitelnost.</p>
        </div>
        </div>

        <div class="boxes">
        <div class="box">
            <h2><a href="https://dibiphp.com">dibi</a></h2>
            <div>
                <a href="https://dibiphp.com" class="img"><img src="{$basePath}/images/dibi.jpg" alt="dibi"></a>
                <p>Dibi je chytrý a malý databázový layer pro PHP 5 s velmi šikovným API.</p>
            </div>
        </div>

        <div class="box">
            <h2><a href="https://texy.info">Texy</a></h2>
            <div>
                <a href="https://texy.info" class="img"><img src="{$basePath}/images/texy.jpg" alt="Texy!"></a>
                <p>Texy je program, díky kterému můžete snadno psát texty na webové stránky.</p>
            </div>
        </div>
        </div>

        <div class="boxes">
        <div class="box">
            <h2><a href="https://www.umeligence.cz">Uměligence</a></h2>
            <div>
                <a href="https://www.umeligence.cz" class="img"><img src="{$basePath}/images/umeligence.png" alt="Uměligence"></a>
                <p>Vše podstatné, co potřebuješ vědět o umělé inteligenci. Průvodce ve světě AI.</p>
            </div>
        </div>

        <div class="box">
            <h2><a href="https://ne-on.org">NEON</a></h2>
            <div>
                <a href="https://ne-on.org" class="img"><img src="{$basePath}/images/neon.png" alt="NEON"></a>
                <p>NEON je formát pro serializaci strukturovaných dat do lidsky srozumitelné podoby.</p>
            </div>
        </div>
        </div>
    </section>


    <section id="trainings">
        <h1><a href="https://www.skoleniphp.cz"><span>Školení a kurzy</span> www.skoleniphp.cz</a>
            <a href="https://www.skoleniphp.cz/feed.xml" class="img"><img src="{$basePath}/images/rss.png" alt="RSS FEED"></a></h1>

        <div class="box">
            <div>
                <ul>
                {foreach $rss('https://www.skoleniphp.cz/feed.xml') as $item}
                    <li><span class="date">{$item->description}</span><br><a href={$item->link}>Školení {$item->title}</a></li>
                {/foreach}
                </ul>
            </div>
        </div>
    </section>


    <section id="twitter">
        <h1><a href="https://twitter.com/DavidGrudl"><span>Twitter</span> @DavidGrudl</a></h1>

        <div class="box">
            <div>
                <ul>
                {foreach $twitter('twitterDavidGrudl') as $status}
                {skipIf (string) $status->in_reply_to_status_id}
                {breakIf $iterator->counter > 3}
                    <li>{$status|tweet|noescape}</li>
                {/foreach}
                </ul>

                <p><a href="https://twitter.com/DavidGrudl">…more on Twitter</a></p>
            </div>
        </div>

        <h1><a href="https://twitter.com/geekovo"><span>Twitter</span> @geekovo</a></h1>

        <div class="box">
            <div>
                <ul>
                {foreach $twitter('twitterGeekovo') as $status}
                {skipIf (string) $status->in_reply_to_status_id}
                {breakIf $iterator->counter > 3}
                    <li>{$status|tweet|noescape}</li>
                {/foreach}
                </ul>
                <p><a href="https://twitter.com/geekovo">…more on Twitter</a></p>
            </div>
        </div>
    </section>


    <section id="blog">
        <h1>Blog</h1>

        <div class="boxes">
        <div class="box">
            <h2><a href="https://www.latrine.cz">La Trine</a>
                <a href="https://www.latrine.cz/feed/rss" class="img"><img src="{$basePath}/images/rss.png" alt="RSS FEED"></a></h2>

            <div>
                <ul>
                {foreach $rss('https://www.latrine.cz/feed/rss') as $item}
                {breakIf $iterator->counter > 5}
                    <li><a href={$item->link}>{$item->title}</a></li>
                {/foreach}
                </ul>
            </div>
        </div>


        <div class="box">
            <h2><a href="https://phpfashion.com">phpFashion</a>
                <a href="https://phpfashion.com/feed/rss" class="img"><img src="{$basePath}/images/rss.png" alt="RSS FEED"></a></h2>

            <div>
                <ul>
                {foreach $rss('https://phpfashion.com/feed/rss') as $item}
                {breakIf $iterator->counter > 5}
                    <li><a href={$item->link}>{$item->title}</a></li>
                {/foreach}
                </ul>
            </div>
        </div>
        </div>
    </section>


    <section id="interviews">
        <h1>Rozhovory</h1>

        <div class="box">
            <div>
                <ul>
                {foreach $rss('https://davidgrudl.com/interviews.xml') as $item}
                    <li><span class="date right">{$item->timestamp|date}</span> <a href={$item->link} n:tag-if="$item->link">{$item->title}</a></li>
                {/foreach}
                </ul>
            </div>
        </div>
    </section>


    <section id="talks">
        <h1>Přednášky <a href="https://davidgrudl.com/talks.xml" class="img"><img src="{$basePath}/images/rss.png" alt="RSS FEED"></a></h1>

        <div class="box">
            <div>
                <ul>
                {foreach $rss('https://davidgrudl.com/talks.xml')->item as $item}
                    <li><span class="date right">{$item->timestamp|date}</span> <a href={$item->link} n:tag-if="$item->link">{$item->title}</a>
                    <div class="more">{$item->{'content:encoded'}|noescape}</div></li>
                {/foreach}
                </ul>
            </div>
        </div>
    </section>


    <section id="contact" class="h-card vcard">
        <h1>Kontakt</h1>

        <div class="box">
            <h2>Obchodní a fakturační údaje</h2>
            <div>
                <p><span class="p-name fn">David Grudl</span><br>
                <span class="p-adr adr"><span class="p-street-address street-address">Korunní 2569/108</span><br>
                <span class="p-postal-code postal-code">101 00</span> <span class="p-locality locality">Praha</span></span></p>

                <p>IČ: 69663963 (nejsem plátce DPH)</p>

                <p>E-mail <a href="mailto:david&#64;grudl.com" class="u-email email">david&#64;<!---->grudl.com</a></p>
            </div>
        </div>


        <div class="box">
            <h2>Bankovní spojení</h2>
            <div>
                <p>670100–2200142627 / 6210 (mBank)<br>
                <small>IBAN: CZ62 6210 6701 0022 0014 2627, BIC: BREXCZPP</small></p>
            </div>
        </div>


        <div class="box">
            <div>
                <p class="tiny">Zapsáno na živnostenském úřadě městské části Praha 7, č. j. MČ P7 011455/2017/OŽV/Pey, spisová značka SZ MČ P7 010973/2017.</p>
            </div>
        </div>
    </section>

    <footer>&copy; David Grudl</footer>
</div>

app/en.latte

{layout "@layout.latte"}
{block content}

<nav id="menu">
    <ul>
        <li><a href="#about">ABOUT ME</a></li>
        <li><a href="#software">SOFTWARE</a></li>
        <li><a href="#blog">BLOG</a></li>
        <li><a href="#interviews">INTERVIEWS</a></li>
        <li><a href="#talks">TALKS</a></li>
        <li><a href="#contact">CONTACT</a></li>
        <li><a href="cs">česky</a></li>
    </ul>
</nav>

<div id="content">
    <section id="about">
        <h1 id="logo" n:block="title">David Grudl</h1>

        <p class="lead">I open doors to the world of artificial intelligence. I design software that powers websites you use every day. I lecture, train, write.</p>

        <div id="photo"></div>

        {block|texy|indent:2}
I am a program writer, AI specialist, blogger, and who knows what else.
I started with computers in the floppy disk era, meanwhile worked with graphics and even typeset newspapers. Today I design web applications and focus on artificial intelligence.
Programmers may know me as the author of many popular open source projects ("Nette Framework":https://nette.org, Latte, Tracy, Texy and many others).

I write the blog "La Trine":www.latrine.cz, for which I received a nomination for the Magnesia Litera award, the website "Uměligence":https://www.umeligence.cz dedicated to AI, and the professional blog "phpFashion":https://phpfashion.com,
I'll teach you "how to properly use AI":https://www.umeligence.cz/workshop-jazykove-modely, train programmers on "web application development":www.skoleniphp.cz, and occasionally run Spartan Race competitions or marathons.

Follow me on "Facebook":https://www.facebook.com/davidgrudl, Twitter as "@davidgrudl":https://twitter.com/DavidGrudl and "@geekovo":https://twitter.com/geekovo or on <a rel="me" href="https://www.threads.net/@davidgrudl">Threads</a>.

"I want to know much more » .[lead]":#more{/block}

        <hr>

        <p><a href="files/david-grudl.jpg">Photo for download</a></p>
    </section>


    <section id="projects">
        <h1>Projects</h1>

        <div class="boxes">
        <div class="box">
            <div><a href="https://nette.org" class="img"><img src="{$basePath}/images/nette.jpg" alt="Nette Framework"></a></div>
        </div>

        <div class="box">
            <h2><a href="https://nette.org">Nette Framework</a></h2>

            <p>A popular tool for creating web applications in PHP. Powerful and understandable tool that satisfies
            the programmers. It eliminates security risks, honors for AJAX, DRY, KISS, MVC and code reuse.</p>
        </div>
        </div>

        <div class="boxes">
        <div class="box">
            <h2><a href="https://dibiphp.com">dibi</a></h2>
            <div>
                <a href="https://dibiphp.com" class="img"><img src="{$basePath}/images/dibi.jpg" alt="dibi"></a>
                <p>Dibi is a smart and tiny database abstraction library for PHP 5 with very handy API.</p>
            </div>
        </div>

        <div class="box">
            <h2><a href="https://texy.info">Texy</a></h2>
            <div>
                <a href="https://texy.info" class="img"><img src="{$basePath}/images/texy.jpg" alt="Texy!"></a>
                <p>Texy is text-to-HTML formatter. It allows you to write
                structured documents using easy-to-read plain text.</p>
            </div>
        </div>
        </div>

        <div class="boxes">
        <div class="box">
            <h2><a href="https://www.umeligence.cz">Umeligence</a></h2>
            <div>
                <a href="https://www.umeligence.cz" class="img"><img src="{$basePath}/images/umeligence.png" alt="Umeligence"></a>
                <p>Everything you need to know about artificial intelligence. A guide to the world of AI.</p>
            </div>
        </div>

        <div class="box">
            <h2><a href="https://ne-on.org">NEON</a></h2>
            <div>
                <a href="https://ne-on.org" class="img"><img src="{$basePath}/images/neon.png" alt="NEON"></a>
                <p>NEON is a human friendly data serialization format for programming languages, similar to YAML.</p>
            </div>
        </div>
        </div>
    </section>


    <section id="blog">
        <h1>Blog</h1>

        <div class="boxes">
        <div class="box">
            <h2><a href="https://www.latrine.cz">La Trine</a>
                <a href="https://www.latrine.cz/feed/rss" class="img"><img src="{$basePath}/images/rss.png" alt="RSS FEED"></a></h2>

            <div>
                <ul>
                {foreach $rss('https://www.latrine.cz/feed/rss') as $item}
                {breakIf $iterator->counter > 5}
                    <li><a href={$item->link}>{$item->title}</a></li>
                {/foreach}
                </ul>
            </div>
        </div>


        <div class="box">
            <h2><a href="https://phpfashion.com">phpFashion</a>
                <a href="https://phpfashion.com/feed/rss" class="img"><img src="{$basePath}/images/rss.png" alt="RSS FEED"></a></h2>

            <div>
                <ul>
                {foreach $rss('https://phpfashion.com/feed/rss') as $item}
                {breakIf $iterator->counter > 5}
                    <li><a href={$item->link}>{$item->title}</a></li>
                {/foreach}
                </ul>
            </div>
        </div>
        </div>
    </section>


    <section id="interviews">
        <h1>Interviews</h1>

        <div class="box">
            <div>
                <ul>
                {foreach $rss('https://davidgrudl.com/interviews.xml') as $item}
                    <li><span class="date right">{$item->timestamp|date}</span> <a href={$item->link} n:tag-if="$item->link">{$item->title}</a></li>
                {/foreach}
                </ul>
            </div>
        </div>
    </section>


    <section id="talks">
        <h1>Talks <a href="https://davidgrudl.com/talks.xml" class="img"><img src="{$basePath}/images/rss.png" alt="RSS FEED"></a></h1>

        <div class="box">
            <div>
                <ul>
                {foreach $rss('https://davidgrudl.com/talks.xml') as $item}
                    <li><span class="date right">{$item->timestamp|date}</span> <a href={$item->link} n:tag-if="$item->link">{$item->title}</a>
                    <div class="more">{$item->{'content:encoded'}|noescape}</div></li>
                {/foreach}
                </ul>
            </div>
        </div>
    </section>


    <section id="contact" class="h-card vcard">
        <h1>Contact</h1>

        <div class="box">
            <h2>Address</h2>

            <div>
                <p><span class="p-name fn">David Grudl</span><br>
                <span class="p-adr adr"><span class="p-street-address street-address">Korunní 2569/108</span><br>
                <span class="p-postal-code postal-code">101 00</span> <span class="p-locality locality">Praha</span></p>
                <span class="p-country-name country-name">The Czech Republic</span></span></p>

                <p>E-mail <a href="mailto:david&#64;grudl.com" class="u-email email">david&#64;<!---->grudl.com</a></p>
            </div>
        </div>
    </section>

    <footer>&copy; David Grudl</footer>
</div>

app/sources.latte

{layout "@layout.latte"}
{block content}

<nav id="menu">
    <ul>
        <li><a href="#index-php">index.php</a></li>
        <li><a href="#config-neon">app/config.neon</a></li>
        <li><a href="#layout-latte">app/@layout.latte</a></li>
        <li><a href="#cs-latte">app/cs.latte</a></li>
        <li><a href="#en-latte">app/en.latte</a></li>
        <li><a href="#sources-latte">app/sources.latte</a></li>
        <li><a href="en">back</a></li>
    </ul>
</nav>

<div id="content">
    <section id="sources">
        <h1 id="logo" n:block="title">Source codes of this website</h1>

        <p>This site is powered by <a href="https://nette.org">Nette Framework</a> and uses
        templating engine <a href="https://latte.nette.org">Latte</a>. See how you can use Nette as a micro-framework.</p>
    </section>

    <h2 id="index-php">index.php</h2>
    <pre>{$source('index.php', 'Php')}</pre>

    <h2 id="config-neon">app/config.neon</h2>
    <pre>{$source('app/config.neon', 'Javascript')}</pre>

    <h2 id="layout-latte">app/@layout.latte</h2>
    <pre>{$source('app/@layout.latte', 'LatteHtml')}</pre>

    <h2 id="cs-latte">app/cs.latte</h2>
    <pre>{$source('app/cs.latte', 'LatteHtml')}</pre>

    <h2 id="en-latte">app/en.latte</h2>
    <pre>{$source('app/en.latte', 'LatteHtml')}</pre>

    <h2 id="sources-latte">app/sources.latte</h2>
    <pre>{$source('app/sources.latte', 'LatteHtml')}</pre>

    <footer>&copy; David Grudl</footer>
</div>