diff --git a/.gitignore b/.gitignore index 408cb749d..eb1a2c123 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +.vscode/ + node_modules public/build yarn.lock diff --git a/.vscode/extensions.json b/.vscode/extensions.json deleted file mode 100644 index 99e242bbb..000000000 --- a/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["bradlc.vscode-tailwindcss"] -} diff --git a/README.md b/README.md deleted file mode 100644 index ad88e6fac..000000000 --- a/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Tailwind CSS Playground - -A simple starter project for playing around with Tailwind in a proper PostCSS environment. - -To get started: - -1. Clone the repository: - - ```bash - git clone https://github.com/tailwindcss/playground.git tailwindcss-playground - - cd tailwindcss-playground - ``` - -2. Install the dependencies: - - ```bash - # Using npm - npm install - - # Using Yarn - yarn - ``` - -3. Start the development server: - - ```bash - # Using npm - npm run serve - - # Using Yarn - yarn run serve - ``` - - Now you should be able to see the project running at localhost:8080. - -4. Open `public/index.html` in your editor and start experimenting! - -## Building for production - -Even though this isn't necessarily a starter kit for a proper project, we've included an example of setting up both [Purgecss](https://www.purgecss.com/) and [cssnano](https://cssnano.co/) to optimize your CSS for production. - -To build an optimized version of your CSS, simply run: - -```bash -# Using npm -npm run production - -# Using Yarn -yarn run production -``` - -After that's done, check out `./public/build/tailwind.css` to see the optimized output. diff --git a/archetypes/default.md b/archetypes/default.md new file mode 100644 index 000000000..f7e5e03d9 --- /dev/null +++ b/archetypes/default.md @@ -0,0 +1,7 @@ +--- +title: "{{ replace .Name "-" " " | title }}" +description: "" +date: {{ .Date }} +draft: true +tags: [] +--- diff --git a/i18n/en.yaml b/i18n/en.yaml new file mode 100644 index 000000000..8326be14a --- /dev/null +++ b/i18n/en.yaml @@ -0,0 +1,5 @@ +- id: back_home + translation: "Back Home" + +- id: not_found_page_title + translation: "Whoops! The page you're looking for doesn't exist :(" diff --git a/layouts/404.html b/layouts/404.html new file mode 100644 index 000000000..afa69fec7 --- /dev/null +++ b/layouts/404.html @@ -0,0 +1,12 @@ +{{ define "heading"}} +
+ ← {{ i18n "back_home" }} +

{{ i18n "not_found_page_title" }}

+
+{{ end }} + +{{ define "content" }} +
+ Page Not Found +
+{{ end }} diff --git a/layouts/_default/baseof.html b/layouts/_default/baseof.html new file mode 100644 index 000000000..2e32b7537 --- /dev/null +++ b/layouts/_default/baseof.html @@ -0,0 +1,86 @@ + + + + + + {{ hugo.Generator }} + + + + + + + + + + + + + + + + + + + + + + {{ if .IsHome }}{{ .Site.Title }}{{ else }}{{ .Title }} - {{ .Site.Title }}{{ end }} + + + + + + {{ with .OutputFormats.Get "RSS" }} + + {{ end }} + + + {{ if .IsTranslated }} + {{ range .Translations }} + + {{ end }} + {{ end }} + + + + + + + +
+
+ +
+ {{ block "heading" . }} +
+ {{ partial "back-home.html" . }} +

{{ .Title }}

+
+ {{ end }} +
+ + + {{ if .IsTranslated }} + + {{ end }} +
+ + + {{ block "content" . }}{{ end }} + + +
+ + {{ template "_internal/google_analytics.html" . }} + + diff --git a/layouts/_default/list.html b/layouts/_default/list.html new file mode 100644 index 000000000..d781ce752 --- /dev/null +++ b/layouts/_default/list.html @@ -0,0 +1,7 @@ +{{ define "content" }} +
+ {{ range site.RegularPages.GroupByDate "2006" -}} + {{ partial "posts.html" . }} + {{ end }} +
+{{ end }} diff --git a/layouts/index.html b/layouts/index.html new file mode 100644 index 000000000..4869c466b --- /dev/null +++ b/layouts/index.html @@ -0,0 +1,18 @@ +{{ define "heading" }} +{{ if .Site.Params.Avatar }} + +{{ end }} + +
+

{{ .Site.Title }}

+

{{ .Site.Params.tagline }}

+
+{{ end }} + +{{ define "content" }} +
+ {{ range site.RegularPages.GroupByDate "2006" -}} + {{ partial "posts.html" . }} + {{ end }} +
+{{ end }} diff --git a/layouts/partials/back-home.html b/layouts/partials/back-home.html new file mode 100644 index 000000000..4064d5256 --- /dev/null +++ b/layouts/partials/back-home.html @@ -0,0 +1 @@ +← {{ i18n "back_home" }} diff --git a/layouts/partials/posts.html b/layouts/partials/posts.html new file mode 100644 index 000000000..0ebd4ca7e --- /dev/null +++ b/layouts/partials/posts.html @@ -0,0 +1,12 @@ +
+

{{ .Key }}

+ +
    + {{ range .Pages -}} +
  1. + + {{ .Title }} +
  2. + {{- end }} +
+
diff --git a/layouts/posts/single.html b/layouts/posts/single.html new file mode 100644 index 000000000..e4485f324 --- /dev/null +++ b/layouts/posts/single.html @@ -0,0 +1,28 @@ +{{ define "heading" }} +
+ {{ partial "back-home.html" . }} + + +

{{ .Title }}

+ + + + {{ with .Params.tags }} +
    + {{ range . }} +
  1. + {{ . }} +
  2. + {{ end }} +
+ {{ end }} +
+{{ end }} + +{{ define "content" }} +
+ {{ .Content }} + + {{ template "_internal/disqus.html" . }} +
+{{ end }} diff --git a/layouts/taxonomy/terms.html b/layouts/taxonomy/terms.html new file mode 100644 index 000000000..76da49ed0 --- /dev/null +++ b/layouts/taxonomy/terms.html @@ -0,0 +1,13 @@ +{{ define "content" }} +
+
    + {{ range .Pages -}} +
  1. + + {{ .Title }} + +
  2. + {{- end }} +
+
+{{ end }} diff --git a/package.json b/package.json index 7a405cbd3..86bb50f94 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,7 @@ { "scripts": { - "serve": "cross-env NODE_ENV=development concurrently \"postcss public/theme.scss -o public/build/theme.css --watch\" \"live-server ./public\"", - "development": "cross-env NODE_ENV=development postcss public/theme.scss -o public/build/theme.css", - "production": "cross-env NODE_ENV=production postcss public/theme.scss -o public/build/theme.css" + "watch": "cross-env NODE_ENV=development postcss scss/theme.scss -o static/css/theme.css --watch", + "build": "cross-env NODE_ENV=production postcss scss/theme.scss -o static/css/theme.css" }, "dependencies": { "autoprefixer": "^9.5.1", @@ -13,7 +12,6 @@ "concurrently": "^4.1.0", "cross-env": "^5.2.0", "cssnano": "^4.1.10", - "live-server": "^1.2.1", "postcss-cli": "^6.1.2" } } diff --git a/postcss.config.js b/postcss.config.js index e4fec1909..6efcb774f 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,5 +1,5 @@ const purgecss = require('@fullhuman/postcss-purgecss')({ - content: ['./public/**/*.html'], + content: ['./layouts/**/*.html'], defaultExtractor: content => content.match(/[A-Za-z0-9-_:/]+/g) || [] }) diff --git a/public/favicon-16x16.png b/public/favicon-16x16.png deleted file mode 100644 index 58aae7eac..000000000 Binary files a/public/favicon-16x16.png and /dev/null differ diff --git a/public/favicon-32x32.png b/public/favicon-32x32.png deleted file mode 100644 index 30eb5396b..000000000 Binary files a/public/favicon-32x32.png and /dev/null differ diff --git a/public/favicon.ico b/public/favicon.ico deleted file mode 100644 index 70be1bc60..000000000 Binary files a/public/favicon.ico and /dev/null differ diff --git a/public/index.html b/public/index.html deleted file mode 100644 index 2553f5b8f..000000000 --- a/public/index.html +++ /dev/null @@ -1,342 +0,0 @@ - - - - - - - Minimalist Journal - Theme for Hugo - - - - - - - - - -
-
-
- -
-

Ian Rodrigues

-

yet another blog about dev, sometimes ops

-
- - -
- - - -
- -
-
-

2019

- -
    -
  1. - - Writing value objects in PHP -
  2. -
  3. - - Hello, World! -
  4. -
-
-
- -
-

If you already have heard about DDD (Domain-Driven Design), you probably also may have heard about Value Objects. It is one of the building blocks introduced by Eric Evans in “the blue book”.

- -

A value object is a type which wraps data and is distinguishable only by its properties. Unlike an Entity, it doesn’t have a unique identifier. Thus, two value objects with the same property values should be considered equal.

- -

A good example of candidates for value objects are:

- - - -

When designing a value object, you should pay attention to its three main characteristics: immutability, structural equality, and self-validation.

- -

Here’s an example:

- -
<?php declare(strict_types=1);
-        
-        final class Price
-        {
-            const USD = 'USD';
-            const CAD = 'CAD';
-        
-            /** @var float */
-            private $amount;
-        
-            /** @var string */
-            private $currency;
-        
-            public function __construct(float $amount, string $currency = 'USD')
-            {
-                if ($amount < 0) {
-                    throw new \InvalidArgumentException("Amount should be a positive value: {$amount}.");
-                }
-        
-                if (!in_array($currency, $this->getAvailableCurrencies())) {
-                    throw new \InvalidArgumentException("Currency should be a valid one: {$currency}.");
-                }
-        
-                $this->amount = $amount;
-                $this->currency = $currency;
-            }
-        
-            private function getAvailableCurrencies(): array
-            {
-                return [self::USD, self::CAD];
-            }
-        
-            public function getAmount(): float
-            {
-                return $this->amount;
-            }
-        
-            public function getCurrency(): string
-            {
-                return $this->currency;
-            }
-        }
-        
- -

Immutability

- -

Once you instantiate a value object, it should be the same for the rest of the application lifecycle. If you need to change its value, it should be done by entirely replacing that object.

- -

Using mutable value objects is acceptable if you are using them entirely within a local scope, with only one reference to the object. Otherwise, you may have problems.

- -

Taking the previous example, here’s how you can update the amount of a Price type:

- -
<?php declare(strict_types=1);
-        
-        final class Price
-        {
-            // ...
-        
-            private function hasSameCurrency(Price $price): bool
-            {
-                return $this->currency === $price->currency;
-            }
-        
-            public function sum(Price $price): self
-            {
-                if (!$this->hasSameCurrency($price)) {
-                    throw \InvalidArgumentException(
-                        "You can only sum values with the same currency: {$this->currency} !== {$price->currency}."
-                    );
-                }
-        
-                return new self($this->amount + $price->amount, $this->currency);
-            }
-        }
-        
- -

Structural Equality

- -

Value objects don’t have an identifier. In other words, if two value objects have the same internal values, they must be considered equal. As PHP doesn’t have a way to override the equality operator, you should implement it by yourself.

- -

You can create a specialized method to do that:

- -
<?php declare(strict_types=1);
-        
-        final class Price
-        {
-            // ...
-        
-            public function isEqualsTo(Price $price): bool
-            {
-                return $this->amount === $price->amount && $this->currency === $price->currency;
-            }
-        }
-        
- -

Another option is to create a hash based on its properties:

- -
<?php declare(strict_types=1);
-        
-        final class Price
-        {
-            // ...
-        
-            private function hash(): string
-            {
-                return md5("{$this->amount}{$this->currency}");
-            }
-        
-            public function isEqualsTo(Price $price): bool
-            {
-                return $this->hash() === $price->hash();
-            }
-        }
-        
- -

Self-Validation

- -

The validation of a value object should occur on its creation. If any of its properties are invalid, it should throw an exception. Putting this together with immutability, once you create a value object, you can be sure it will always be valid.

- -

Taking the Price type example once again, it doesn’t make sense to have a negative amount for the domain of the application:

- -
<?php declare(strict_types=1);
-        
-        final class Price
-        {
-            // ...
-        
-            public function __construct(float $amount, string $currency = 'USD')
-            {
-                if ($amount < 0) {
-                    throw new \InvalidArgumentException("Amount should be a positive value: {$amount}.");
-                }
-        
-                if (!in_array($currency, $this->getAvailableCurrencies())) {
-                    throw new \InvalidArgumentException("Currency should be a valid one: {$currency}.");
-                }
-        
-                $this->amount = $amount;
-                $this->currency = $currency;
-            }
-        }
-        
- -

Using with Doctrine

- -

Storing and retrieving value objects from the database using Doctrine is quite easy using Embeddables. According to the documentation, Embeddables are not entities. But, you embed them in entities, which makes them perfect for dealing with value objects.

- -

Let’s suppose you have a Product class, and you would like to store the price in that class. You will end up with the following modeling:

- -
<?php declare(strict_types=1);
-        
-        /** @Embeddable */
-        final class Price
-        {
-            /** @Column(type="float") */
-            private $amount;
-        
-            /** @Column(type="string") */
-            private $currency;
-        
-            public function __construct(float $amount, string $currency = 'USD')
-            {
-                // ...
-        
-                $this->amount = $amount;
-                $this->currency = $currency;
-            }
-        
-            // ...
-        }
-        
-        /** @Entity */
-        class Product
-        {
-            /** @Embedded(class="Price") */
-            private $price;
-        
-            public function __construct(Price $price)
-            {
-                $this->price = $price;
-            }
-        }
-        
- -

Doctrine will automatically create the columns from the Price class into the table of the Product class. By default, it prefixes the database columns after the Embeddable class name, in this case: price_amount and price_currency.

- -

Conclusion

- -

Value objects are useful for writing clean code. Instead of writing:

- -
public function addPhoneNumber(string $phone): void {}
-        
- -

You can write:

- -
public function addPhoneNumber(PhoneNumber $phone): void {}
-        
- -

Which makes it easy to read and reason about it, also you don’t need to figure out which phone format you should use.

- -

Since their attributes define them, and you can share them with other different entities, they can be cacheable forever.

- -

They can help you to reduce duplication. Instead of having multiples amount and currency fields, you can use a pure Price class.

- -

Of course, like everything in life, you should not abuse of value objects. Imagine you converting tons of objects to primitive values to store them in the database, or converting those back to value objects when fetching them from the database.Indeed, you can have performance issues. Also, having tons of granular value objects can bloat your codebase.

- -

With value objects, you can reduce the primitive obsession. Use them to represent a field or group of fields of your domain that require validation or can cause ambiguity if you use primitive values.

- -

Thanks for reading, and happy coding!

- -

Further Reading

- - - - -
- - -
- - -
- - diff --git a/readme.md b/readme.md new file mode 100644 index 000000000..140750294 --- /dev/null +++ b/readme.md @@ -0,0 +1,62 @@ +# TailwindCSS Journal + +_TailwindCSS Journal_ is a minimalist theme for [Hugo](https://gohugo.io) using [TailwindCSS](https://tailwindcss.com). + +Based on [Journal](https://dashdashzako.github.io/hugo-journal-demo/), it also focuses on improving reading experience with no fancy effect. + +It uses [Chroma](https://gohugo.io/content-management/syntax-highlighting/) for the syntaxic coloration of code snippets. + +Demo is available [here](https://ianrodrigues.github.io/hugo-tailwind-demo/). + +## Installation + +Please refer to the [Hugo documentation](https://gohugo.io/themes/installing/). + +## Configuration + +A few parameters should be adjusted in the site config: + +```toml +baseURL = "https://username.github.io/" +disqusShortname = "username" +googleAnalytics = "UA-XXXXXXXXX-X" +title = "Tailwind Journal" +theme = "hugo-tailwind-journal" +pygmentsCodeFences = true +pygmentsUseClasses = true + +[taxonomies] + tag = "tags" + +[permalinks] + posts = "/posts/:year/:month/:title/" + +[params] + author = "John Doe" + avatar = "images/avatar.jpg" + description = "A minimalist journal template for Hugo using TailwindCSS." + tagline = "A minimalist journal template for Hugo using TailwindCSS." + +[languages] + [languages.en] + contentDir = "content/english" + languageCode = "en-us" + languageName = "🇺🇸 English" + weight = 1 + + [languages.pt-br] + contentDir = "content/portuguese" + description = "Um template minimalista para Hugo usando TailwindCSS." + languageCode = "pt-br" + languageName = "🇧🇷 Português" + tagline = "Um template minimalista para Hugo usando TailwindCSS." + weight = 2 + + [languages.de] + contentDir = "content/german" + description = "Eine minimalistische Journalvorlage für Hugo mit TailwindCSS." + languageCode = "de" + languageName = "🇩🇪 Deutsch" + tagline = "Eine minimalistische Journalvorlage für Hugo mit TailwindCSS." + weight = 3 +``` diff --git a/public/theme.scss b/scss/theme.scss similarity index 69% rename from public/theme.scss rename to scss/theme.scss index 68acd5b5f..9da9261b6 100644 --- a/public/theme.scss +++ b/scss/theme.scss @@ -14,7 +14,7 @@ article > p, ul, ol { @apply text-lg tracking-wide; } -article > p, ul, ol, pre:not(:last-child) { +article > div, p, ul, ol, pre:not(:last-child) { @apply mb-6; } @@ -37,3 +37,15 @@ article > h2 { a { @apply border-b border-black text-black; } + +/* purgecss ignore */ +pre.chroma { + @apply p-4 overflow-x-auto font-mono text-lg; +} + +@screen md { + /* purgecss ignore */ + div.highlight { + @apply -mx-12; + } +} diff --git a/static/css/chroma.dracula.css b/static/css/chroma.dracula.css new file mode 100644 index 000000000..5e903f4fd --- /dev/null +++ b/static/css/chroma.dracula.css @@ -0,0 +1 @@ +.chroma{color:#f8f8f2;background-color:#282a36}.chroma .lntd{vertical-align:top;padding:0;margin:0;border:0}.chroma .lntable{border-spacing:0;padding:0;margin:0;border:0;width:auto;overflow:auto;display:block}.chroma .hl{display:block;width:100%;background-color:#ffc}.chroma .lnt{margin-right:.4em;padding:0 .4em 0 .4em;color:#7f7f7f}.chroma .ln{margin-right:.4em;padding:0 .4em 0 .4em;color:#7f7f7f}.chroma .k{color:#ff79c6}.chroma .kc{color:#ff79c6}.chroma .kd{color:#8be9fd;font-style:italic}.chroma .kn{color:#ff79c6}.chroma .kp{color:#ff79c6}.chroma .kr{color:#ff79c6}.chroma .kt{color:#8be9fd}.chroma .na{color:#50fa7b}.chroma .nb{color:#8be9fd;font-style:italic}.chroma .nc{color:#50fa7b}.chroma .nf{color:#50fa7b}.chroma .nl{color:#8be9fd;font-style:italic}.chroma .nt{color:#ff79c6}.chroma .nv{color:#8be9fd;font-style:italic}.chroma .vc{color:#8be9fd;font-style:italic}.chroma .vg{color:#8be9fd;font-style:italic}.chroma .vi{color:#8be9fd;font-style:italic}.chroma .s{color:#f1fa8c}.chroma .sa{color:#f1fa8c}.chroma .sb{color:#f1fa8c}.chroma .sc{color:#f1fa8c}.chroma .dl{color:#f1fa8c}.chroma .sd{color:#f1fa8c}.chroma .s2{color:#f1fa8c}.chroma .se{color:#f1fa8c}.chroma .sh{color:#f1fa8c}.chroma .si{color:#f1fa8c}.chroma .sx{color:#f1fa8c}.chroma .sr{color:#f1fa8c}.chroma .s1{color:#f1fa8c}.chroma .ss{color:#f1fa8c}.chroma .m{color:#bd93f9}.chroma .mb{color:#bd93f9}.chroma .mf{color:#bd93f9}.chroma .mh{color:#bd93f9}.chroma .mi{color:#bd93f9}.chroma .il{color:#bd93f9}.chroma .mo{color:#bd93f9}.chroma .o{color:#ff79c6}.chroma .ow{color:#ff79c6}.chroma .c{color:#6272a4}.chroma .ch{color:#6272a4}.chroma .cm{color:#6272a4}.chroma .c1{color:#6272a4}.chroma .cs{color:#6272a4}.chroma .cp{color:#ff79c6}.chroma .cpf{color:#ff79c6}.chroma .gd{color:#8b080b}.chroma .ge{text-decoration:underline}.chroma .gh{font-weight:700}.chroma .gi{font-weight:700}.chroma .go{color:#44475a}.chroma .gu{font-weight:700}.chroma .gl{text-decoration:underline} diff --git a/static/css/theme.css b/static/css/theme.css new file mode 100644 index 000000000..4d9cc992f --- /dev/null +++ b/static/css/theme.css @@ -0,0 +1 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}a{background-color:transparent}strong{font-weight:bolder}img{border-style:none}button,input{font-family:inherit;font-size:100%;line-height:1.15;margin:0;overflow:visible}button{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}legend{color:inherit;display:table;max-width:100%;white-space:normal}[type=checkbox],[type=radio],legend{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}[hidden],template{display:none}html{box-sizing:border-box;font-family:sans-serif}*,:after,:before{box-sizing:inherit}h1,h2,p{margin:0}button{background:transparent;padding:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}ol{list-style:none;margin:0;padding:0}html{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{border:0 solid #e2e8f0}img{border-style:solid}input::-webkit-input-placeholder{color:#a0aec0}input::-moz-placeholder{color:#a0aec0}input:-ms-input-placeholder{color:#a0aec0}input::-ms-input-placeholder{color:#a0aec0}input::placeholder{color:#a0aec0}[role=button],button{cursor:pointer}h1,h2{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}button,input{padding:0;line-height:inherit;color:inherit}canvas,img{display:block;vertical-align:middle}img{max-width:100%;height:auto}.bg-gray-200{background-color:#edf2f7}.bg-gray-400{background-color:#cbd5e0}.hover\:bg-gray-600:hover{background-color:#718096}.border-blue-500{border-color:#4299e1}.rounded-sm{border-radius:.125rem}.rounded-full{border-radius:9999px}.border-none{border-style:none}.border-t-4{border-top-width:4px}.block{display:block}.inline-block{display:inline-block}.hidden{display:none}.font-serif{font-family:Arvo}.font-bold{font-weight:700}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mx-2{margin-left:.5rem;margin-right:.5rem}.-mx-2{margin-left:-.5rem;margin-right:-.5rem}.mb-2{margin-bottom:.5rem}.mt-4{margin-top:1rem}.mr-6{margin-right:1.5rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.mb-12{margin-bottom:3rem}.mb-24{margin-bottom:6rem}.p-6{padding:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-3{padding-left:.75rem;padding-right:.75rem}.text-gray-800{color:#2d3748}.hover\:text-white:hover{color:#fff}.text-xs{font-size:.75rem}.text-lg{font-size:1.125rem}.text-3xl{font-size:1.875rem}.text-4xl{font-size:2.25rem}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-20{width:5rem}.w-full{width:100%}body{color:#2d3748}h1,h2,strong{color:#1a202c}article>p,ol{font-size:1.125rem;letter-spacing:.025em}article>div,ol,p{margin-bottom:1.5rem}article>ol{list-style-type:disc;margin-left:2rem}article>li:not(:last-of-type){margin-bottom:.5rem}article>h2{font-size:1.5rem;margin-top:2rem;margin-bottom:2rem;font-weight:700;color:#000}a{border-bottom-width:1px;border-color:#000;color:#000}pre.chroma{padding:1rem;overflow-x:auto;font-family:Source Code Pro;font-size:1.125rem}@media (min-width:768px){div.highlight{margin-left:-3rem;margin-right:-3rem}}@media (min-width:768px){.md\:block{display:block}.md\:flex{display:-webkit-box;display:flex}.md\:flex-row{-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-direction:row}.md\:items-center{-webkit-box-align:center;align-items:center}.md\:flex-l-24{-webkit-box-flex:0;flex:0 0 6rem}.md\:mx-auto{margin-left:auto;margin-right:auto}.md\:ml-12{margin-left:3rem}.md\:px-0{padding-left:0;padding-right:0}.md\:w-2\/3{width:66.666667%}}@media (min-width:1280px){.xl\:w-2\/5{width:40%}} \ No newline at end of file diff --git a/static/images/404-background.png b/static/images/404-background.png new file mode 100644 index 000000000..4b945386a Binary files /dev/null and b/static/images/404-background.png differ diff --git a/theme.toml b/theme.toml new file mode 100644 index 000000000..2986f65e0 --- /dev/null +++ b/theme.toml @@ -0,0 +1,12 @@ +name = "Tailwind Journal" +license = "MIT" +licenselink = "https://github.com/ianrodrigues/hugo-tailwind-journal/blob/master/readme.md" +description = "A minimalist journal template for Hugo using TailwindCSS." +homepage = "https://github.com/ianrodrigues/hugo-tailwind-journal" +tags = ["minimalist", "reading", "blog", "tailwindcss"] +features = ["blog"] +min_version = "0.54.0" + +[author] + name = "Ian Rodrigues" + homepage = "https://ianrodrigues.dev"