20 | {% for page in term.pages %}
21 | {{ macros::page_in_list(page=page) }}
22 | {%- endfor %}
23 |
24 | {% endblock %}
25 |
--------------------------------------------------------------------------------
/data/cv/summary.yml:
--------------------------------------------------------------------------------
1 | - I am a data scientist with a background in physics and a passion for solving complex problems. I have experience in developing and implementing machine learning algorithms to extract insights from large datasets. I am proficient in Python and have experience working with AWS-based data warehouse infrastructure. I am looking for opportunities to apply my skills in a dynamic and challenging environment.
2 | - I am a full-stack developer with experience in building web applications using Python, Django, JavaScript, and React. I have worked on projects ranging from e-commerce platforms to data visualization tools. I am passionate about creating user-friendly interfaces and optimizing performance. I am looking for opportunities to work on innovative projects and collaborate with talented teams.
3 |
--------------------------------------------------------------------------------
/templates/tags/list.html:
--------------------------------------------------------------------------------
1 | {% extends "base.html" %}
2 |
3 | {%- block seo %}
4 | {{- super() }}
5 | {%- set title = "Tags" %}
6 | {%- set description = "List of tags" %}
7 |
8 | {%- if config.title %}
9 | {%- set title_addition = title_separator ~ config.title %}
10 | {%- else %}
11 | {%- set title_addition = "" %}
12 | {%- endif %}
13 |
14 | {{- macros::seo(title=title, title_addition=title_addition, description=description, is_page=true) }}
15 | {%- endblock seo %}
16 |
17 | {%- block content %}
18 |
30 | {%- endblock %}
31 |
--------------------------------------------------------------------------------
/content/pages/about.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "About"
3 | path = "about"
4 |
5 | [extra]
6 | no_page_info = true
7 | pgp_key_enabled = true
8 |
9 | [extra.seo]
10 | type = "Person"
11 | +++
12 |
13 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam nec purus auctor, cursus turpis ac, ultricies nunc. Ut auctor, odio id tincidunt tincidunt, nunc metus tincidunt justo, ac ultricies nunc mi nec sapien. Nullam auctor, libero nec ultricies lacinia, mi purus vehicula mi, nec iaculis nunc elit nec felis. Nullam nec purus auctor, cursus turpis ac, ultricies nunc. Ut auctor, odio id tincidunt tincidunt, nunc metus tincidunt justo, ac ultricies nunc mi nec sapien. Nullam auctor, libero nec ultricies lacinia, mi purus vehicula mi, nec iaculis nunc elit nec felis.
14 |
15 | [Currículum Vitae](@/pages/cv.md)
16 |
34 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Vladimir Loskutov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/templates/index.html:
--------------------------------------------------------------------------------
1 | {%- extends "base.html" %}
2 |
3 | {%- block seo -%}
4 | {{- super() }}
5 |
6 | {%- if config.title %}
7 | {%- set title = config.title %}
8 | {%- else %}
9 | {%- set title = "" %}
10 | {%- endif %}
11 |
12 | {%- if config.description and title %}
13 | {%- set title_addition = title_separator ~ config.description %}
14 | {%- elif config.description %}
15 | {%- set title_addition = config.description %}
16 | {%- else %}
17 | {%- set title_addition = "" %}
18 | {%- endif %}
19 |
20 | {{- macros::seo(title=title, title_addition=title_addition, description=config.description, is_home=true) }}
21 | {%- endblock seo %}
22 |
23 | {%- block content %}
24 |
25 | {%- for page in paginator.pages %}
26 | {{ macros::page_in_list(page=page) }}
27 | {%- endfor %}
28 |
73 |
--------------------------------------------------------------------------------
/content/posts/first-post.md:
--------------------------------------------------------------------------------
1 | +++
2 | title = "Title"
3 | date = 2017-01-10T00:00:00+00:00
4 |
5 | [taxonomies]
6 | tags = ["Features", "Markdown"]
7 | +++
8 |
9 | Text can be **bold**, _italic_, ~~strikethrough~~ or `keyword`.
10 |
11 | [Link to another page](@/pages/another-page.md).
12 |
13 | There should be whitespace between paragraphs.
14 |
15 |
16 | There should be whitespace between paragraphs. We recommend including a README, or a file with information about your project.
17 |
18 | # Header 1
19 |
20 | This is a normal paragraph following a header. GitHub is a code hosting platform for version control and collaboration. It lets you and others work together on projects from anywhere.
21 |
22 | ## Header 2
23 |
24 | > This is a blockquote following a header.
25 | >
26 | > When something is important enough, you do it even if the odds are not in your favor.
27 |
28 | ### Header 3
29 |
30 | ```js
31 | // Javascript code with syntax highlighting.
32 | var fun = function lang(l) {
33 | dateformat.i18n = require('./lang/' + l)
34 | return true;
35 | }
36 | ```
37 |
38 | ```ruby
39 | # Ruby code with syntax highlighting
40 | GitHubPages::Dependencies.gems.each do |gem, version|
41 | s.add_dependency(gem, "= #{version}")
42 | end
43 | ```
44 |
45 | #### Header 4
46 |
47 | * This is an unordered list following a header.
48 | * This is an unordered list following a header.
49 | * This is an unordered list following a header.
50 |
51 | ##### Header 5
52 |
53 | 1. This is an ordered list following a header.
54 | 2. This is an ordered list following a header.
55 | 3. This is an ordered list following a header.
56 |
57 | ###### Header 6
58 |
59 | | head1 | head two | three |
60 | |:------------:|:------------------|------:|
61 | | ok | good swedish fish | nice |
62 | | out of stock | good and plenty | nice |
63 | | ok | good `oreos` | hmm |
64 | | ok | good `zoute` drop | yumm |
65 |
66 | ### There's a horizontal rule below this.
67 |
68 | * * *
69 |
70 | ### Here is an unordered list:
71 |
72 | * Item foo
73 | * Item bar
74 | * Item baz
75 | * Item zip
76 |
77 | ### And an ordered list:
78 |
79 | 1. Item one
80 | 1. Item two
81 | 1. Item three
82 | 1. Item four
83 |
84 | ### And a nested list:
85 |
86 | - level 1 item
87 | - level 2 item
88 | - level 2 item
89 | - level 3 item
90 | - level 3 item
91 | - level 1 item
92 | - level 2 item
93 | - level 2 item
94 | - level 2 item
95 | - level 1 item
96 | - level 2 item
97 | - level 2 item
98 | - level 1 item
99 |
100 | ### Small image
101 |
102 | 
103 |
104 | ### Large image
105 |
106 | 
107 |
108 |
109 | ### Definition lists can be used with HTML syntax.
110 |
111 |
112 |
Name
113 |
Godzilla
114 |
Born
115 |
1952
116 |
Birthplace
117 |
Japan
118 |
Color
119 |
Green
120 |
121 |
122 | ```
123 | Long, single-line code blocks should not wrap. They should horizontally scroll if they are too long. This line should be long enough to demonstrate this.
124 | ```
125 |
126 | ```
127 | The final element.
128 | ```
129 |
130 | ```scss, linenos
131 | pre mark {
132 | display: block;
133 | color: currentcolor;
134 | }
135 |
136 | pre table td:nth-of-type(1) {
137 | color: #6b6b6b;
138 | font-style: italic;
139 | }
140 | ```
141 |
--------------------------------------------------------------------------------
/static/js/form-submission-handler.js:
--------------------------------------------------------------------------------
1 | (function () {
2 | // get all data in form and return object
3 | function getFormData(form) {
4 | const elements = form.elements;
5 | let itsatrap;
6 |
7 | const fields = Object.keys(elements).filter((k) => {
8 | if (elements[k].name === "itsatrap") {
9 | itsatrap = elements[k].value;
10 | return false;
11 | }
12 | return true;
13 | }).map((k) => {
14 | if (elements[k].name !== undefined) {
15 | return elements[k].name;
16 | // special case for Edge's html collection
17 | } else if (elements[k].length > 0) {
18 | return elements[k].item(0).name;
19 | }
20 | }).filter((item, pos, self) => {
21 | return self.indexOf(item) == pos && item;
22 | });
23 |
24 | const formData = {};
25 | fields.forEach((name) => {
26 | const element = elements[name];
27 |
28 | // singular form elements just have one value
29 | formData[name] = element.value;
30 |
31 | // when our element has multiple items, get their values
32 | if (element.length) {
33 | const data = [];
34 | for (let i = 0; i < element.length; i++) {
35 | const item = element.item(i);
36 | if (item.checked || item.selected) {
37 | data.push(item.value);
38 | }
39 | }
40 | formData[name] = data.join(', ');
41 | }
42 | });
43 |
44 | // add form-specific values into the data
45 | formData.formDataNameOrder = JSON.stringify(fields);
46 | formData.formGoogleSheetName = form.dataset.sheet || "responses"; // default sheet name
47 | formData.formGoogleSendEmail
48 | = form.dataset.email || ""; // no email by default
49 |
50 | return { data: formData, itsatrap };
51 | }
52 |
53 | function handleFormSubmit(event) {
54 | event.preventDefault(); // we are submitting via fetch below
55 | const form = event.target;
56 | const formData = getFormData(form);
57 | const data = formData.data;
58 |
59 | // If a itsatrap field is filled, assume it was done so by a spam bot.
60 | if (formData.itsatrap || data.submit) {
61 | return false;
62 | }
63 |
64 | disableAllButtons(form);
65 | const url = `https://script.google.com/macros/s/${form.dataset.scriptId}/exec`;
66 |
67 | fetch(url, {
68 | method: 'POST',
69 | headers: {
70 | 'Content-Type': 'application/x-www-form-urlencoded',
71 | },
72 | body: new URLSearchParams(data).toString(),
73 | })
74 | .then((response) => {
75 | if (response.ok) {
76 | form.reset();
77 | const formElements = form.querySelector(".form-elements");
78 | if (formElements) {
79 | formElements.style.display = "none"; // hide form
80 | }
81 | const thankYouMessage = form.querySelector(".thankyou-message");
82 | if (thankYouMessage) {
83 | thankYouMessage.style.display = "block";
84 | }
85 | }
86 | })
87 | .catch((error) => {
88 | console.error('Error submitting the form:', error);
89 | });
90 | }
91 |
92 | function loaded() {
93 | // bind to the submit event of our form
94 | const forms = document.querySelectorAll("form.contact-form");
95 | forms.forEach((form) => {
96 | form.addEventListener("submit", handleFormSubmit, false);
97 | });
98 | };
99 | document.addEventListener("DOMContentLoaded", loaded, false);
100 |
101 | function disableAllButtons(form) {
102 | const buttons = form.querySelectorAll("button");
103 | buttons.forEach((button) => {
104 | button.disabled = true;
105 | });
106 | }
107 | })();
108 |
--------------------------------------------------------------------------------
/config.toml:
--------------------------------------------------------------------------------
1 | # The URL the site will be built for
2 | base_url = "https://zola-hacker.enginerd.io/"
3 |
4 | # The title of the site
5 | title = "Hacker theme"
6 |
7 | # The description of the site
8 | description = "Hacker is a theme for Zola"
9 |
10 | author = "John Doe"
11 |
12 | # Whether to automatically compile all Sass files in the sass directory
13 | compile_sass = true
14 |
15 | # Whether to minify the HTML when building the site
16 | minify_html = false
17 |
18 | # Whether to generate an Atom feed
19 | generate_feeds = true
20 |
21 | # Taxonomies
22 | taxonomies = [{ name = "tags" }]
23 |
24 | [markdown]
25 | # Whether to do syntax highlighting
26 | # Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
27 | highlight_code = true
28 | highlight_theme = "charcoal"
29 |
30 | # Whether to render emojis
31 | render_emoji = true
32 |
33 | # Whether footnotes are rendered in the GitHub-style (at the bottom, with back references) or plain (in the place, where they are defined)
34 | bottom_footnotes = true
35 |
36 | [extra]
37 | title_separator = "|" # set as |, -, _, etc
38 |
39 | # The path to the logo of the site
40 | logo = "images/logo.png"
41 |
42 | # Google Analytics tracking ID
43 | google_analytics = "example-tracking-id"
44 |
45 | # Contact form script id that points to google macros (e.g. https://script.google.com/macros/s//exec)
46 | # More info about contact form based on google macros can be found here: https://github.com/en9inerd/learn-to-send-email-via-google-script-html-no-server
47 | contact_form_script_id = ""
48 |
49 | # Visitor notifier based on IFTTT + Webhooks. Sample here - /static/js/monitor.js
50 | monitor = false
51 |
52 | # Menu items
53 | menu = [{ url = "/about", name = "About" }, { url = "/tags", name = "Tags" }]
54 |
55 | language_code = "en-US"
56 |
57 | # Enable OpenGraph metadata
58 | opengraph = true
59 |
60 | timezone = "America/New_York"
61 |
62 | # Date and time format for displaying post dates.
63 | # If left empty, the default format will be used: "%B %e, %Y at %H:%M %Z".
64 | # Example of a custom format: "%Y-%m-%d %H:%M:%S %z" (2024-02-04 15:30:00 +0000)
65 | # timeformat = ""
66 |
67 | # The path to cv file if you use cv shortcode
68 | # cv_file = "/files/Curriculum_Vitae.pdf"
69 |
70 | # provide link to edit page on github
71 | edit_page = true
72 |
73 | # Use theme specific tags page based on templates/tags.html
74 | simplified_tags = false
75 |
76 | # Social links
77 | social_links = [
78 | { platform = "email", user_id = "johndoe@example.com" },
79 | { platform = "github", user_id = "johndoe" },
80 | { platform = "linkedin", user_id = "johndoe" },
81 | { platform = "feed", user_id = true },
82 | { platform = "keyoxide", user_id = "aspe:host:XXXXXXX" },
83 | # { platform = "facebook", user_id = "" },
84 | # { platform = "instagram", user_id = "" },
85 | # { platform = "pinterest", user_id = "" },
86 | # { platform = "twitter", user_id = "" },
87 | # { platform = "stackoverflow", user_id = "" },
88 | # { platform = "youtube", user_id = "" },
89 | # { platform = "telegram", user_id = "" },
90 | ]
91 |
92 | # GitHub settings that are used to generate the edit page link
93 | [extra.github]
94 | username = "en9inerd"
95 | repo = "zola-hacker"
96 |
97 | # Giscus settings
98 | # Please refer to https://giscus.app/ for more information
99 | # and don't use the same repo_id and category_id as in the example below
100 | [extra.giscus]
101 | repo = "en9inerd/zola-hacker"
102 | repo_id = "R_kgDOMZOW5g"
103 | category = "Comments"
104 | category_id = "DIC_kwDOMZOW5s4ChFNw"
105 | mapping = "og:title"
106 | strict = 0
107 | reactions_enabled = 1
108 | emit_metadata = 0
109 | input_position = "top"
110 | theme = "dark"
111 | lang = "en"
112 | loading = "lazy"
113 | crossorigin = "anonymous"
114 |
115 | # PGP key
116 | [extra.pgp_key]
117 | url = "https://keys.openpgp.org/vks/v1/by-fingerprint/0000000000000000000000000000000000000000"
118 | fingerprint = "0000 0000 0000 0000 0000 0000 0000 0000 0000 0000"
119 |
120 | # JSON-LD metadata
121 | [extra.bio]
122 | gender = "male"
123 | employer_name = "Unknown"
124 | employer_url = "https://unknown.com"
125 | job_title = "Software Engineer"
126 | links = [
127 | "https://github.com/johndoe",
128 | "https://linkedin.com/in/johndoe",
129 | "https://twitter.com/johndoe",
130 | ]
131 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Hacker theme for Zola
2 |
3 | Zola Hacker is a minimalistic theme for Zola, inspired by the [Hacker theme](https://pages-themes.github.io/hacker/) for Jekyll. It is designed for developers who want to write blogs.
4 |
5 | ## Demo
6 |
7 | [Live Preview](https://zola-hacker.enginerd.io/).
8 |
9 | ## Requirements
10 |
11 | Before using the theme, you need to install the [Zola](https://www.getzola.org/documentation/getting-started/installation/) ≥ 0.19.1.
12 |
13 | ## Quick Start
14 |
15 | ```bash
16 | git clone git@github.com:en9inerd/zola-hacker.git
17 | cd zola-hacker
18 | zola serve
19 | # open http://127.0.0.1:1111/ in the browser
20 | ```
21 |
22 | ## Installation
23 |
24 | Just earlier we showed you how to run the theme directly. Now we start to
25 | install the theme in an existing site step by step.
26 |
27 | ### Step 1: Create a new zola site
28 |
29 | ```bash
30 | zola init mysite
31 | ```
32 |
33 | ### Step 2: Install Zola Hacker Theme
34 |
35 | Download this theme to your themes directory:
36 |
37 | ```bash
38 | cd mysite/themes
39 | git clone git@github.com:en9inerd/zola-hacker.git
40 | ```
41 |
42 | Or install as a submodule:
43 |
44 | ```bash
45 | cd mysite
46 | git init # if your project is a git repository already, ignore this command
47 | git submodule add git@github.com:en9inerd/zola-hacker.git themes/hacker
48 | ```
49 |
50 | ### Step 3: Configuration
51 |
52 | Enable the theme in your `config.toml` in the site directory:
53 |
54 | ```toml
55 | theme = "hacker"
56 | ```
57 |
58 | Or copy the `config.toml` from the theme directory to your project's
59 | root directory:
60 |
61 | ```bash
62 | cp themes/hacker/config.toml config.toml
63 | ```
64 |
65 | ### Step 4: Add new content
66 |
67 | You can copy the content from the theme directory to your project:
68 |
69 | ```bash
70 | cp -r themes/hacker/content .
71 | ```
72 |
73 | You can modify or add new posts in the `content/posts`, `content/pages` or other
74 | content directories as needed.
75 |
76 | ### Step 5: Run the project
77 |
78 | Just run `zola serve` in the root path of the project:
79 |
80 | ```bash
81 | zola serve
82 | ```
83 |
84 | Command will start the Zola development web server accessible by default at
85 | `http://127.0.0.1:1111`. Saved changes will live reload in the browser.
86 |
87 | ## Customisation
88 |
89 | You can customize your configurations, templates and content for yourself. Look
90 | at the `config.toml`, `theme.toml`, `content` files and templates files in this
91 | repo for an idea.
92 |
93 | ### Global Configuration
94 |
95 | There are some configuration options that you can customize in `config.toml`.
96 |
97 | #### Configuration options before `extra` options
98 |
99 | Set the tags taxonomy in the `config.toml`:
100 |
101 | ```toml
102 | taxonomies = [
103 | { name = "tags" },
104 | ]
105 | ```
106 |
107 | #### Configuration options under the `extra`
108 |
109 | The following options should be under the `[extra]` in `config.toml`
110 |
111 | - `language_code` - set HTML file language (default to `en-US`)
112 | - `title_separator` - the separator to your site title, like `|` and `-` (defaults to `|`)
113 | - `logo` - path to the logo image
114 | - `google_analytics` - Google Analytics tracking ID
115 | - `timeformat` - the timeformat for the blog article published date
116 | - `timezone` - the timezone for the blog article published date
117 | - `edit_page` - whether to show the edit page in the github repo for your posts
118 | - `menu` - set the menu items for your site
119 | - `contact_form_script_id` - the script id for the contact form based on [Google Script](https://github.com/en9inerd/learn-to-send-email-via-google-script-html-no-server)
120 | - `[extra.github]` - set the GitHub metadata for your site
121 | - `[extra.giscus]` - set the Giscus settings for your site to enable the comments. Please use own settings from the [Giscus](https://giscus.app/) website
122 | - `[extra.opengraph]` - set the Open Graph metadata for your site
123 | - `[extra.pgp_key]` - set pgp key in the footer for certain pages
124 | - `social_links` - set the social media links in the footer
125 | ...
126 |
127 | ### Templates
128 |
129 | All pages are extend to the `base.html`, and you can customize them as need.
130 |
131 | ### Shortcodes
132 |
133 | The theme provides some shortcodes to help you write your content:
134 |
135 | `contact_form`
136 | The `contact_form` shortcode is based on [Google Apps Mail](https://github.com/en9inerd/learn-to-send-email-via-google-script-html-no-server) to send emails without a server.
137 | It depends on `contact_form_script_id` in the `config.toml`.
138 |
139 | ```markdown
140 | {{ contact_form() }}
141 | ```
142 |
143 | `cv`
144 | The `cv` shortcode is used to display the CV in the page. Data for CV is stored in yaml format in the `data/cv` directory.
145 |
146 | ```markdown
147 | {{ cv() }}
148 | ```
149 |
150 | `github_avatar`
151 | The `github_avatar` shortcode is used to display the GitHub avatar image. It depends on `extra.github.username` in the `config.toml`. Also, you can pass size as an argument.
152 |
153 | ```markdown
154 | {{ github_avatar(size=100) }}
155 | ```
156 |
157 | `projects`
158 | The `projects` shortcode is used to display repositories from GitHub. It depends on `extra.github.username` in the `config.toml` and `extra.repo_names` in page front matter to filter the repositories.
159 |
160 | ```markdown
161 | {{ projects() }}
162 | ```
163 |
164 | ## Reporting Issues
165 |
166 | We use GitHub Issues as the official bug tracker for the **Zola Hacker Theme**. Please
167 | search [existing issues](https://github.com/en9inerd/zola-hacker/issues). It’s
168 | possible someone has already reported the same problem.
169 |
170 | If your problem or idea is not addressed yet, [open a new issue](https://github.com/en9inerd/zola-hacker/issues/new).
171 |
172 | ## License
173 |
174 | **Zola Hacker Theme** is distributed under the terms of the
175 | [MIT license](https://github.com/en9inerd/zola-hacker/blob/master/LICENSE).
176 |
--------------------------------------------------------------------------------
/templates/macros.html:
--------------------------------------------------------------------------------
1 | {%- macro page_in_list(page) -%}
2 |
3 |