Skip to content
New: Customize your theme with an AI assistant. Read the guide

How Taskly Works

Skill level: Everyone · Time: 10 minutes

Read this page once and the rest of the theme stops being a mystery. Taskly is built from a few simple ideas that repeat everywhere.

The Big Picture

Taskly is a static site: when you run npm run build, it turns your text files into finished HTML pages in dist/. There is no database and no admin panel. Your files are the website.

config.toml ──► site settings: name, URL, forms
menu.en.json ─► header and footer links
theme.css ────► colors, radii, type scale
ROUTE src/pages/[...lang]/pricing.astro
│ which sections, in which order
│
├─ PAGE src/content/pricing/english/-index.md
│ title, SEO, named blocks
│
└─ each SECTION
├─ default: sections/english/pricing-section.md
├─ + page block: pricingSection: { ... }
└─ look: layout
Base.astro wraps every page:
head · announcement bar · header · page · CTA · footer · cookies · search

1. Routes Decide What A Page Shows

Each file in src/pages/[...lang]/ is one page (a route). It lists the sections that page shows, top to bottom. This is the second homepage, src/pages/[...lang]/home-2.astro, shortened:

<Base {...data}>
<LayoutVariants section="hero" content={data?.heroSection} />
<LayoutVariants section="logos" content={data?.logosSection} />
<StatsPanelSection content={data?.statsPanelSection} />
<FeatureRowsSection content={data?.featureRowsSection} />
<PricingSection content={data?.pricingSection} />
<!-- ...more sections... -->
</Base>

To reorder sections, move a line. To remove a section from one page, delete its line. <LayoutVariants section="hero" …> renders the hero exactly like <HeroSection …> would; it only exists so the theme’s own demo can preview other layouts. The [...lang] folder name means one file builds every language: English at /pricing/, French at /fr/pricing/.

2. Sections Have Default Content

Every section has a matching content file in src/content/sections/<language>/. For example, PricingSection.astro reads pricing-section.md. That file holds the section’s default text, lists, buttons, and options, with comments that explain each one.

Edit a section file and the change appears everywhere that section is used. Set enable: false at the top of the file to hide the section on every page.

3. Pages Can Override Any Section

A page file can change a section for that page only with a named block. The second homepage uses this to give the shared hero another layout and title:

src/content/homepage/english/home-2.md
---
title: ""
heroSection: # overrides src/content/sections/english/hero-section.md
layout: "split"
title: "Run your *team* from one board"
---

Block names are the section name in camelCase: heroSection, pricingSection, faqSection, ctaSection, and so on. Each page file lists the blocks it renders in the comments at its top. Sections has the full list.

A block with a wrong name, for example pricing: instead of pricingSection:, is ignored without an error. Copy block names from the page file’s comments, the Sections table, or sectionsSchema in src/sections.schema.ts.

4. How Overrides Merge

When a page block meets the section’s default content, Taskly merges them with four rules:

You write in the page blockResult
A text or number (title: "Hello")Replaces the default value
An object (button:, tag:)Merges key by key: only the keys you write change
A list (plans:, items:, rows:)Replaces the whole list. Write every item you want to keep
An empty string (title: "")Clears the value. Leave the key out to keep the default

So this block changes only the button label and keeps its URL, icon, and style:

heroSection:
button:
label: "Start your trial"

5. Layouts Change The Look, Not The Content

9 sections can be drawn in more than one way (the page header too). The layout is one field, at the top level of the section’s content:

layout: "split" # the hero: default | split | signup

The content fields stay the same, so you can switch back and forth freely. Some layouts read a few extra fields (the split hero reads rating, the signup hero reads pill and signup); the section file groups them under # layout: <name> comments. Set the layout in the section file (every page) or in a page block (one page). The layout gallery at /elements/ shows every layout of these sections and of the page header on one page.

See Section Layouts for every value.

6. Base Wraps Every Page

src/layouts/Base.astro adds the parts that every page shares:

  • the <head>: title, description, Open Graph tags, structured data, fonts, and your [head] scripts
  • the announcement bar above the header, from src/content/widgets/<language>/announcement-bar.md
  • the floating header, from config.toml and the menu files
  • the call to action card that sits on the top edge of the footer, from src/content/sections/<language>/call-to-action.md. A page changes or hides it with a ctaSection: block (enable: false hides it)
  • the footer, from the menu files, config.toml, and src/i18n/<language>.json, in the layout the page’s footerLayout picks (default when it has none)
  • the cookie banner, the search window, the back-to-top button, and shared scripts

The log-in, sign-up, and password screens use src/layouts/AuthLayout.astro instead, without the header, footer, or call to action.

7. Small Interface Text Lives In i18n Files

Labels that are not page content, such as “Log in”, “Subscribe”, “Copy”, or search messages, live in src/i18n/en.json and src/i18n/fr.json. Many config.toml labels are empty on purpose (label = ""): empty means “use the translated text from the i18n file”. Fill them in only if your site has one language.

8. Config Is Converted Before Astro Reads It

Astro cannot read TOML, so npm run dev, npm run build, and npm run astro-check first convert src/config/config.toml into .astro/config.generated.json. While npm run dev is running, this happens every time you save. Always edit the TOML file, never the generated JSON.

Restart npm run dev after changing trailingSlash or anything under [settings.multilingual].

9. What Happens During A Build

  1. config.toml is converted to JSON.
  2. Astro checks the content collections that have a schema in src/content.config.ts, including the named blocks in their page frontmatter (sectionsSchema in src/sections.schema.ts). A wrong value there stops the build with the file name and field.
  3. Every route is rendered once per language into dist/. Each section checks its merged content (section file plus page block) against its schema while it renders, so a wrong value in a section file, such as a misspelled layout, also stops the build (and shows an error in npm run dev).
  4. Open Graph images are drawn for pages without an image, plus llms.txt, llms-full.txt, the Markdown copies of pages, the sitemap, robots.txt, and the RSS feeds.
  5. If the site URL is still the https://example.com placeholder, a yellow [site] warning prints when the Astro build finishes.
  6. Pagefind builds the search index from the finished pages.
  7. Drafts and pages with excludeFromSitemap: true are removed from the sitemap.

Development vs. Production

Some things behave differently while you work with npm run dev:

Featurenpm run devBuilt site (npm run build)
Pages with draft: trueShown, so you can preview themNot built
Site searchThe search window says search works on the built siteWorks
Form endpoint warningsShown inside forms with placeholder URLs, and in the terminalPrinted in the terminal only; visitors never see them
Site URL warningNot shownPrinted after the Astro build step while the URL is example.com
Open Graph imagesNot drawnDrawn for every page without an image

Find Where Any Text Comes From

See a sentence on the site and want to change it? Search the whole project for it: in VS Code press Ctrl + Shift + F (⌘ + Shift + F on Mac) and paste a few words. It will be in one of these places, checked in this order:

  1. The page’s own file, in a named block (src/content/<page>/<language>/-index.md)
  2. The section’s default file (src/content/sections/<language>/)
  3. A widget file: the dashboard mockup, cookie banner, or announcement bar (src/content/widgets/<language>/)
  4. The interface text (src/i18n/<language>.json)
  5. The menus (src/config/menu.<language>.json)
  6. Site settings (src/config/config.toml)

If the same text appears in both a page block and a section file, the page block wins on that page.

Type something to search...