diff --git a/README.md b/README.md index de45ab6..9f55bc6 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Drop markdown, HTML and PHP files in directories to instantly publish online. A ## How it works -Your file system is your site structure. Create folders, drop in content files – and they're live. Create `content/about/intro.md` and it turns into `yoursite.com/about/`. Need more presentational control then what Markdown offers? Drop in an HTML file. Dynamic content? Add a PHP script. No routing configuration, no build step, just save a file, refresh the browser. +Your file system is your site structure. Create folders, drop in content files, and they're live. Create `content/about/intro.md` and it turns into `yoursite.com/about/`. Need more presentational controll then what Markdown offers? Drop in an HTML file. Dynamic content? Add a PHP script. No routing configuration, no build step, just save a file, refresh the browser. Since everything is just files and folders, you can mount your site via SFTP or WebDAV and edit content directly from your local machine — save a file, and the change is live. Create websites like it's 1996! diff --git a/app/default/content/00-hero.no.php b/app/default/content/00-hero.no.php new file mode 100644 index 0000000..3f3387a --- /dev/null +++ b/app/default/content/00-hero.no.php @@ -0,0 +1,51 @@ + '📁', 'title' => 'Filbasert', 'description' => 'Mapper blir URL-er automatisk', 'url' => $prefix . '/examples/file-based-routing/'], + ['icon' => '⚡', 'title' => 'Uten byggesteg', 'description' => 'Rediger og oppdater—det er alt', 'url' => $prefix . '/examples/no-build-step/'], + ['icon' => '🎨', 'title' => 'Bland formater', 'description' => 'Kombiner .md, .html og .php', 'url' => $prefix . '/examples/mix-formats/'], + ['icon' => '🌍', 'title' => 'Flerspråklig', 'description' => 'Innebygd i18n-støtte', 'url' => $prefix . '/multilingual/'], + ['icon' => '📝', 'title' => 'Markdown', 'description' => 'Skriv innhold i markdown', 'url' => $prefix . '/examples/2024-12-15-markdown-demo/'], + ['icon' => '🎭', 'title' => 'Maler', 'description' => 'Egendefinerte layout og stiler', 'url' => $prefix . '/examples/templates-demo/'], +]; + +$stats = [ + 'files' => count(glob(__DIR__ . '/**/*', GLOB_BRACE)) ?: 0, + 'generated' => number_format((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000, 2) . 'ms', + 'php_version' => PHP_VERSION, +]; +?> + +
+

FolderWeb

+

+ Slipp filer i mapper. De rendres umiddelbart. + Ingen konfigurasjon, ingen byggesteg, ingen kompleksitet. +

+ +
+ + + +

+

+
+ +
+ +
+
+ + Filer i innhold +
+
+ + Side generert +
+
+ PHP + Runtime +
+
+
diff --git a/app/default/content/00-hero.php b/app/default/content/00-hero.php new file mode 100644 index 0000000..e2c2708 --- /dev/null +++ b/app/default/content/00-hero.php @@ -0,0 +1,51 @@ + '📁', 'title' => 'File-Based', 'description' => 'Folders become URLs automatically', 'url' => $prefix . '/examples/file-based-routing/'], + ['icon' => '⚡', 'title' => 'No Build Step', 'description' => 'Edit and refresh—that\'s it', 'url' => $prefix . '/examples/no-build-step/'], + ['icon' => '🎨', 'title' => 'Mix Formats', 'description' => 'Combine .md, .html, and .php', 'url' => $prefix . '/examples/mix-formats/'], + ['icon' => '🌍', 'title' => 'Multilingual', 'description' => 'Built-in i18n support', 'url' => $prefix . '/multilingual/'], + ['icon' => '📝', 'title' => 'Markdown', 'description' => 'Write content in markdown', 'url' => $prefix . '/examples/2024-12-15-markdown-demo/'], + ['icon' => '🎭', 'title' => 'Templates', 'description' => 'Custom layouts and styles', 'url' => $prefix . '/examples/templates-demo/'], +]; + +$stats = [ + 'files' => count(glob(__DIR__ . '/**/*', GLOB_BRACE)) ?: 0, + 'generated' => number_format((microtime(true) - $_SERVER['REQUEST_TIME_FLOAT']) * 1000, 2) . 'ms', + 'php_version' => PHP_VERSION, +]; +?> + +
+

FolderWeb

+

+ Drop files in folders. They render immediately. + No configuration, no build step, no complexity. +

+ +
+ + + +

+

+
+ +
+ +
+
+ + Files in content +
+
+ + Page generated +
+
+ PHP + Runtime +
+
+
diff --git a/app/default/content/01-index.md b/app/default/content/01-index.md new file mode 100644 index 0000000..145e99a --- /dev/null +++ b/app/default/content/01-index.md @@ -0,0 +1,45 @@ + + + +## Quick Start + +1. **Empty the content folder** – Delete everything in `/content/` to start fresh +2. **Copy the default folder** – Copy `/app/default/` to `/custom/` (one level up from app/) to create your own theme +3. **Add your content** – Drop `.md`, `.html`, or `.php` files in `/content/` and they're live +4. **Customize templates** – Edit files in `/custom/templates/` to change the look +5. **Style it** – Add CSS in `/custom/styles/styles.css` for global styles + +## What Makes FolderWeb Different + +**File-based routing** – Your folder structure is your URL structure. No configuration needed. + +**No JavaScript** – Fast, simple, accessible websites that work everywhere. + +**Modern PHP & CSS** – Clean code using the latest language features and CSS capabilities. + +**No build step** – Edit a file, refresh the page. That's it. + +**Decade-proof** – Minimal dependencies mean this will work for years without breaking. + +## How This Page Works + +This frontpage demonstrates how you can **mix different file types** to create dynamic, custom layouts: + +- **`hero.php`** – Dynamic PHP component with live stats and styling +- **`index.md`** – Static markdown content (this section!) + +Files in the same directory are rendered alphabetically. Want a different order? Prefix filenames with numbers like `00-hero.php` and `01-content.md`. + +## Features Demonstrated Here {#features} + +Explore this demo site to see what FolderWeb can do: + +- [Examples](/examples/) – Markdown, metadata, dates, and cover images +- [Multilingual](/multilingual/) – Build sites in multiple languages +- [Nested Content](/examples/nested/) – Organize content as deep as you need + +## Philosophy + +**Just enough, nothing more.** This framework uses minimal PHP to enable modern conveniences while remaining maintainable for years or decades. + +Read more in `CLAUDE.md` to understand the principles behind FolderWeb. diff --git a/app/default/content/01-index.no.md b/app/default/content/01-index.no.md new file mode 100644 index 0000000..dc0a430 --- /dev/null +++ b/app/default/content/01-index.no.md @@ -0,0 +1,45 @@ + + + +## Hurtigstart + +1. **Tøm innholdsmappen** – Slett alt i `/content/` for å starte fra bunnen av +2. **Kopier standardmappen** – Kopier `/app/default/` til `/custom/` (ett nivå opp fra app/) for å lage ditt eget tema +3. **Legg til innhold** – Slipp `.md`, `.html`, eller `.php`-filer i `/content/` og de er live +4. **Tilpass maler** – Rediger filer i `/custom/templates/` for å endre utseendet +5. **Stil det** – Legg til CSS i `/custom/styles/styles.css` for globale stiler + +## Hva gjør FolderWeb annerledes + +**Filbasert routing** – Mappestrukturen din er URL-strukturen din. Ingen konfigurasjon nødvendig. + +**Ingen JavaScript** – Raske, enkle, tilgjengelige nettsteder som fungerer overalt. + +**Moderne PHP & CSS** – Ren kode som bruker de nyeste språkfunksjonene og CSS-mulighetene. + +**Uten byggesteg** – Rediger en fil, oppdater siden. Det er det. + +**Tiår-sikker** – Minimale avhengigheter betyr at dette vil fungere i årevis uten å gå i stykker. + +## Hvordan denne siden fungerer + +Denne forsiden demonstrerer hvordan du kan **blande forskjellige filtyper** for å lage dynamiske, egendefinerte layout: + +- **`hero.no.php`** – Dynamisk PHP-komponent med live statistikk og styling +- **`index.no.md`** – Statisk markdown-innhold (denne seksjonen!) + +Filer i samme katalog rendres alfabetisk. Vil du ha en annen rekkefølge? Prefikser filnavn med tall som `00-hero.php` og `01-innhold.md`. + +## Funksjoner demonstrert her {#funksjoner} + +Utforsk denne demosiden for å se hva FolderWeb kan gjøre: + +- [Eksempler](/examples/) – Markdown, metadata, datoer og forsidebilder +- [Flerspråklig](/multilingual/) – Bygg nettsteder på flere språk +- [Nestet innhold](/examples/nested/) – Organiser innhold så dypt du trenger + +## Filosofi + +**Akkurat nok, ikke mer.** Dette rammeverket bruker minimal PHP for å muliggjøre moderne bekvemmeligheter samtidig som det forblir vedlikeholdbart i årevis eller tiår. + +Les mer i `CLAUDE.md` for å forstå prinsippene bak FolderWeb. diff --git a/app/default/content/about/about.md b/app/default/content/about/about.md deleted file mode 100644 index 46e2d87..0000000 --- a/app/default/content/about/about.md +++ /dev/null @@ -1,5 +0,0 @@ -# About - -This is a simple page. It lives in `content/about/about.md` and renders at `/about/`. - -Any folder with only files (no subdirectories) renders as a page. diff --git a/app/default/content/about/about.no.md b/app/default/content/about/about.no.md deleted file mode 100644 index 83a4dee..0000000 --- a/app/default/content/about/about.no.md +++ /dev/null @@ -1,5 +0,0 @@ -# Om - -Dette er en enkel side. Den ligger i `content/about/about.no.md` og vises på `/no/about/`. - -Mapper som bare inneholder filer (ingen undermapper) vises som en side. diff --git a/app/default/content/blog/2025-01-15-first-post/metadata.ini b/app/default/content/blog/2025-01-15-first-post/metadata.ini deleted file mode 100644 index f27cb61..0000000 --- a/app/default/content/blog/2025-01-15-first-post/metadata.ini +++ /dev/null @@ -1,6 +0,0 @@ -title = "First Post" -summary = "A simple blog post demonstrating date extraction and metadata" - -[no] -title = "Første innlegg" -summary = "Et enkelt blogginnlegg som viser datouttrekk og metadata" diff --git a/app/default/content/blog/2025-01-15-first-post/post.md b/app/default/content/blog/2025-01-15-first-post/post.md deleted file mode 100644 index 3b0066e..0000000 --- a/app/default/content/blog/2025-01-15-first-post/post.md +++ /dev/null @@ -1,5 +0,0 @@ -# First Post - -This is a blog post. The date `2025-01-15` is extracted from the folder name for sorting and display. - -You can set a custom URL slug in `metadata.ini` to shorten the URL. diff --git a/app/default/content/blog/2025-01-15-first-post/post.no.md b/app/default/content/blog/2025-01-15-first-post/post.no.md deleted file mode 100644 index e5d701a..0000000 --- a/app/default/content/blog/2025-01-15-first-post/post.no.md +++ /dev/null @@ -1,5 +0,0 @@ -# Første innlegg - -Dette er et blogginnlegg. Datoen `2025-01-15` hentes fra mappenavnet for sortering og visning. - -Du kan sette en egendefinert URL-slug i `metadata.ini` for å forkorte URL-en. diff --git a/app/default/content/blog/2025-02-01-second-post/10-intro.md b/app/default/content/blog/2025-02-01-second-post/10-intro.md deleted file mode 100644 index ded3c81..0000000 --- a/app/default/content/blog/2025-02-01-second-post/10-intro.md +++ /dev/null @@ -1,3 +0,0 @@ -# Second Post - -This post combines multiple content files into a single page. This section is Markdown. diff --git a/app/default/content/blog/2025-02-01-second-post/10-intro.no.md b/app/default/content/blog/2025-02-01-second-post/10-intro.no.md deleted file mode 100644 index 9451455..0000000 --- a/app/default/content/blog/2025-02-01-second-post/10-intro.no.md +++ /dev/null @@ -1,3 +0,0 @@ -# Andre innlegg - -Dette innlegget kombinerer flere innholdsfiler til en enkelt side. Denne delen er Markdown. diff --git a/app/default/content/blog/2025-02-01-second-post/20-details.html b/app/default/content/blog/2025-02-01-second-post/20-details.html deleted file mode 100644 index f2f5261..0000000 --- a/app/default/content/blog/2025-02-01-second-post/20-details.html +++ /dev/null @@ -1,5 +0,0 @@ -
-

HTML Section

-

This section is plain HTML, rendered after the Markdown above. Number prefixes (10-, 20-) control the order.

-

You can mix .md, .html, and .php files freely within a single page.

-
diff --git a/app/default/content/blog/2025-02-01-second-post/20-details.no.html b/app/default/content/blog/2025-02-01-second-post/20-details.no.html deleted file mode 100644 index cf1c66b..0000000 --- a/app/default/content/blog/2025-02-01-second-post/20-details.no.html +++ /dev/null @@ -1,5 +0,0 @@ -
-

HTML-seksjon

-

Denne delen er ren HTML, vist etter Markdown-en over. Nummerprefiks (10-, 20-) styrer rekkefølgen.

-

Du kan blande .md-, .html- og .php-filer fritt på en enkelt side.

-
diff --git a/app/default/content/blog/2025-02-01-second-post/30-dynamic.no.php b/app/default/content/blog/2025-02-01-second-post/30-dynamic.no.php deleted file mode 100644 index a43f7e2..0000000 --- a/app/default/content/blog/2025-02-01-second-post/30-dynamic.no.php +++ /dev/null @@ -1,18 +0,0 @@ -
-

PHP-seksjon

-

Denne delen er dynamisk PHP, vist etter HTML-en over.

- - - - - - - - - - - -
EgenskapVerdi
Servertid
PHP-versjon
Side generert påms
Operativsystem
- -

Oppdater siden for å se klokken endre seg. Dette er serverside-output — ingen JavaScript involvert.

-
diff --git a/app/default/content/blog/2025-02-01-second-post/30-dynamic.php b/app/default/content/blog/2025-02-01-second-post/30-dynamic.php deleted file mode 100644 index 4589ed6..0000000 --- a/app/default/content/blog/2025-02-01-second-post/30-dynamic.php +++ /dev/null @@ -1,18 +0,0 @@ -
-

PHP Section

-

This section is dynamic PHP, rendered after the HTML above.

- - - - - - - - - - - -
PropertyValue
Server time
PHP version
Page generated inms
Operating system
- -

Refresh the page to see the time update. This is live server-side output — no JavaScript involved.

-
diff --git a/app/default/content/blog/2025-02-01-second-post/metadata.ini b/app/default/content/blog/2025-02-01-second-post/metadata.ini deleted file mode 100644 index 7bface6..0000000 --- a/app/default/content/blog/2025-02-01-second-post/metadata.ini +++ /dev/null @@ -1,6 +0,0 @@ -title = "Second Post" -summary = "A post demonstrating mixed content formats" - -[no] -title = "Andre innlegg" -summary = "Et innlegg som viser blandede innholdsformater" diff --git a/app/default/content/blog/metadata.ini b/app/default/content/blog/metadata.ini deleted file mode 100644 index a555899..0000000 --- a/app/default/content/blog/metadata.ini +++ /dev/null @@ -1,8 +0,0 @@ -title = "Blog" -summary = "Example blog with list view" -menu = 1 -menu_order = 10 - -[no] -title = "Blogg" -summary = "Eksempelblogg med listevisning" diff --git a/app/default/content/examples/2024-10-05-cover-image-demo/cover.svg b/app/default/content/examples/2024-10-05-cover-image-demo/cover.svg new file mode 100644 index 0000000..31e832f --- /dev/null +++ b/app/default/content/examples/2024-10-05-cover-image-demo/cover.svg @@ -0,0 +1,5 @@ + + + + Cover Image Example + diff --git a/app/default/content/examples/2024-10-05-cover-image-demo/index.md b/app/default/content/examples/2024-10-05-cover-image-demo/index.md new file mode 100644 index 0000000..78e749c --- /dev/null +++ b/app/default/content/examples/2024-10-05-cover-image-demo/index.md @@ -0,0 +1,39 @@ +# Cover Images and Assets + +FolderWeb automatically detects and uses cover images for social sharing and list views. + +## How Cover Images Work + +Place an image named `cover.jpg`, `cover.png`, or `cover.webp` in your content folder and it's automatically: + +- Used as the Open Graph image for social media +- Displayed in list views (when using templates that support it) +- Available at the same URL as your content + +## Supported Formats + +- `cover.jpg` or `cover.jpeg` +- `cover.png` +- `cover.webp` +- `cover.gif` + +The system checks for these in order and uses the first one found. + +## Other Assets + +Any file in your content folder is accessible at the same URL path: + +- Images: `photo.jpg`, `diagram.png` +- Documents: `download.pdf`, `report.docx` +- Data: `data.json`, `spreadsheet.csv` + +Just reference them in your markdown: + +```markdown +![Diagram](diagram.png) +[Download PDF](report.pdf) +``` + +## This Folder + +This folder includes a simple SVG as the cover image. Check the folder structure to see how it's organized. diff --git a/app/default/content/examples/2024-10-05-cover-image-demo/metadata.ini b/app/default/content/examples/2024-10-05-cover-image-demo/metadata.ini new file mode 100644 index 0000000..a305d97 --- /dev/null +++ b/app/default/content/examples/2024-10-05-cover-image-demo/metadata.ini @@ -0,0 +1,2 @@ +title = "Cover Images and Assets" +summary = "Learn how cover images and static assets work in FolderWeb" diff --git a/app/default/content/examples/2024-11-20-metadata-example/index.md b/app/default/content/examples/2024-11-20-metadata-example/index.md new file mode 100644 index 0000000..c3bcae9 --- /dev/null +++ b/app/default/content/examples/2024-11-20-metadata-example/index.md @@ -0,0 +1,53 @@ +# Working with Metadata + +Metadata provides structured information about your pages and controls how they display. + +## What is metadata.ini? + +Every folder can have a `metadata.ini` file that defines: + +- Title (overrides automatic title extraction) +- Date (overrides folder-based date detection) +- Summary (appears in list views) +- Custom template selection +- Other custom fields + +## Example metadata.ini + +```ini +title = "My Custom Title" +date = "2024-11-20" +summary = "A brief description that appears in lists" + +[settings] +page_template = "list-grid" +show_date = false +``` + +## Common Use Cases + +**Override automatic titles** – If you want a title different from the folder name. + +**Set explicit dates** – When the folder name doesn't include a date. + +**Add summaries** – Give context in list views without showing full content. + +**Choose templates** – Different sections can use different list templates. + +**Hide metadata** – Set `show_date = false` to hide dates in lists. + +## Custom Fields + +You can add any fields you want: + +```ini +author = "Jane Doe" +category = "Tutorial" +tags = "metadata, configuration, tutorial" +``` + +Then access them in custom templates via `$metadata['author']`. + +## This Page's Metadata + +Check out `metadata.ini` in this folder to see how the title, date, and summary are defined. diff --git a/app/default/content/examples/2024-11-20-metadata-example/metadata.ini b/app/default/content/examples/2024-11-20-metadata-example/metadata.ini new file mode 100644 index 0000000..060c614 --- /dev/null +++ b/app/default/content/examples/2024-11-20-metadata-example/metadata.ini @@ -0,0 +1,3 @@ +title = "Working with Metadata" +date = "2024-11-20" +summary = "Learn how to use metadata.ini files to control page information and behavior" diff --git a/app/default/content/examples/2024-12-15-markdown-demo/index.md b/app/default/content/examples/2024-12-15-markdown-demo/index.md new file mode 100644 index 0000000..949972c --- /dev/null +++ b/app/default/content/examples/2024-12-15-markdown-demo/index.md @@ -0,0 +1,74 @@ +# Markdown Demonstration + +This page shows the full range of Markdown formatting available through Parsedown. + +## Text Formatting + +You can use **bold text**, *italic text*, and even ***bold italic***. + +Use `inline code` for technical terms or file paths like `/app/default/templates/`. + +## Lists + +Unordered lists: + +- First item +- Second item + - Nested item + - Another nested item +- Third item + +Ordered lists: + +1. Step one +2. Step two +3. Step three + +## Links and Images + +Here's a [link to the homepage](/). + +Images work too (when you add them to the folder): + +![Example image](placeholder.jpg) + +## Code Blocks + +```php + This is a blockquote. Perfect for highlighting important information or quotes from other sources. +> +> It can span multiple paragraphs. + +## Tables + +| Feature | Status | +|---------|--------| +| Markdown | ✓ | +| HTML | ✓ | +| PHP | ✓ | +| JavaScript | ✗ | + +## Horizontal Rules + +--- + +That line above is a horizontal rule, useful for separating sections. + +## What You Can Do + +- Write content in simple Markdown +- Mix HTML when needed +- Include images stored alongside your content +- Use all standard Markdown features + +The file for this page is just `index.md` in a dated folder. The date is automatically extracted and displayed. diff --git a/app/default/content/examples/2024-12-15-markdown-demo/index.no.md b/app/default/content/examples/2024-12-15-markdown-demo/index.no.md new file mode 100644 index 0000000..e7edd3a --- /dev/null +++ b/app/default/content/examples/2024-12-15-markdown-demo/index.no.md @@ -0,0 +1,74 @@ +# Markdown-demonstrasjon + +Denne siden viser hele utvalget av Markdown-formatering tilgjengelig gjennom Parsedown. + +## Tekstformatering + +Du kan bruke **fet tekst**, *kursiv tekst*, og til og med ***fet kursiv***. + +Bruk `inline kode` for tekniske termer eller filstier som `/app/default/templates/`. + +## Lister + +Uspesifiserte lister: + +- Første element +- Andre element + - Nestet element + - Enda et nestet element +- Tredje element + +Ordnede lister: + +1. Steg én +2. Steg to +3. Steg tre + +## Lenker og bilder + +Her er en [lenke til forsiden](/). + +Bilder fungerer også (når du legger dem til i mappen): + +![Eksempelbilde](placeholder.jpg) + +## Kodeblokker + +```php + Dette er et blokksitat. Perfekt for å fremheve viktig informasjon eller sitater fra andre kilder. +> +> Det kan spenne over flere avsnitt. + +## Tabeller + +| Funksjon | Status | +|---------|--------| +| Markdown | ✓ | +| HTML | ✓ | +| PHP | ✓ | +| JavaScript | ✗ | + +## Horisontale linjer + +--- + +Linjen over er en horisontal linje, nyttig for å skille seksjoner. + +## Hva du kan gjøre + +- Skriv innhold i enkel Markdown +- Bland inn HTML når det trengs +- Inkluder bilder lagret sammen med innholdet ditt +- Bruk alle standard Markdown-funksjoner + +Filen for denne siden er bare `index.no.md` i en datert mappe. Datoen blir automatisk hentet ut og vist. diff --git a/app/default/content/examples/2024-12-15-markdown-demo/metadata.ini b/app/default/content/examples/2024-12-15-markdown-demo/metadata.ini new file mode 100644 index 0000000..94e5c22 --- /dev/null +++ b/app/default/content/examples/2024-12-15-markdown-demo/metadata.ini @@ -0,0 +1,2 @@ +title = "Markdown Demonstration" +summary = "Shows all the Markdown formatting features available through Parsedown" diff --git a/app/default/content/examples/file-based-routing/index.md b/app/default/content/examples/file-based-routing/index.md new file mode 100644 index 0000000..a1c51bf --- /dev/null +++ b/app/default/content/examples/file-based-routing/index.md @@ -0,0 +1,52 @@ +# File-Based Routing + +FolderWeb's routing is beautifully simple: **your folder structure is your URL structure**. No configuration files, no route definitions, no magic strings. + +## How It Works + +When you visit a URL, FolderWeb looks for matching folders and files: + +``` +/content/ +├── index.md → / +├── about/ +│ └── index.md → /about/ +└── blog/ + ├── 2024-11-01-post/ + │ └── index.md → /blog/post/ + └── index.md → /blog/ +``` + +## Automatic Features + +**Folder names become URLs** – Create a folder called `projects` and it's instantly available at `/projects/` + +**Date prefixes are stripped** – `2024-11-01-my-post` becomes `/my-post/` in the URL + +**Custom slugs via metadata** – Override the default URL with `slug = "custom-url"` in `metadata.ini` + +**Trailing slashes** – Directories always redirect to include trailing slashes for consistency + +## Example + +This very page demonstrates file-based routing! The path is: + +``` +app/default/content/examples/file-based-routing/index.md +``` + +Which renders at: + +``` +/examples/file-based-routing/ +``` + +No routes to define. No configuration to update. Just files and folders. + +## Benefits + +- **Intuitive** – If you can navigate folders, you understand the routing +- **Refactor-friendly** – Moving content means moving folders +- **No broken links** – URLs match the filesystem +- **Fast** – No route matching overhead, direct file lookup +- **Predictable** – What you see is what you get diff --git a/app/default/content/examples/file-based-routing/index.no.md b/app/default/content/examples/file-based-routing/index.no.md new file mode 100644 index 0000000..73387e1 --- /dev/null +++ b/app/default/content/examples/file-based-routing/index.no.md @@ -0,0 +1,52 @@ +# Filbasert routing + +FolderWebs routing er vakkert enkelt: **mappestrukturen din er URL-strukturen din**. Ingen konfigurasjonsfiler, ingen rutedefinisjon, ingen magiske strenger. + +## Hvordan det fungerer + +Når du besøker en URL, ser FolderWeb etter matchende mapper og filer: + +``` +/content/ +├── index.md → / +├── om/ +│ └── index.md → /om/ +└── blogg/ + ├── 2024-11-01-innlegg/ + │ └── index.md → /blogg/innlegg/ + └── index.md → /blogg/ +``` + +## Automatiske funksjoner + +**Mappenavn blir URL-er** – Lag en mappe kalt `prosjekter` og den er umiddelbart tilgjengelig på `/prosjekter/` + +**Datoprefikser fjernes** – `2024-11-01-mitt-innlegg` blir `/mitt-innlegg/` i URL-en + +**Egendefinerte slugs via metadata** – Overstyr standard URL med `slug = "egendefinert-url"` i `metadata.ini` + +**Avsluttende skråstrek** – Kataloger omdirigerer alltid til å inkludere avsluttende skråstrek for konsistens + +## Eksempel + +Denne siden demonstrerer filbasert routing! Stien er: + +``` +app/default/content/examples/file-based-routing/index.no.md +``` + +Som rendres på: + +``` +/examples/file-based-routing/ +``` + +Ingen ruter å definere. Ingen konfigurasjon å oppdatere. Bare filer og mapper. + +## Fordeler + +- **Intuitivt** – Hvis du kan navigere mapper, forstår du routingen +- **Refaktorvennlig** – Å flytte innhold betyr å flytte mapper +- **Ingen ødelagte lenker** – URL-er matcher filsystemet +- **Rask** – Ingen rutematching overhead, direkte filoppslag +- **Forutsigbar** – Det du ser er det du får diff --git a/app/default/content/examples/file-based-routing/metadata.ini b/app/default/content/examples/file-based-routing/metadata.ini new file mode 100644 index 0000000..54fe86d --- /dev/null +++ b/app/default/content/examples/file-based-routing/metadata.ini @@ -0,0 +1,3 @@ +title = "File-Based Routing" +summary = "Your folder structure is your URL structure—no configuration needed" +date = "2024-11-26" diff --git a/app/default/content/examples/index.md b/app/default/content/examples/index.md new file mode 100644 index 0000000..4690055 --- /dev/null +++ b/app/default/content/examples/index.md @@ -0,0 +1,5 @@ +# Examples + +This section demonstrates different content types and features you can use in FolderWeb. + +Each example below shows a different capability. Click through to see the source and how it works. diff --git a/app/default/content/examples/mix-formats/00-intro.md b/app/default/content/examples/mix-formats/00-intro.md new file mode 100644 index 0000000..26c34f3 --- /dev/null +++ b/app/default/content/examples/mix-formats/00-intro.md @@ -0,0 +1,11 @@ +# Mix Formats + +FolderWeb lets you **combine different file types** in the same directory. Markdown, HTML, and PHP files can coexist and render together on a single page. + +## Supported Formats + +- **`.md`** – Markdown for content (this file!) +- **`.html`** – Static HTML snippets +- **`.php`** – Dynamic PHP components + +All files in the same directory are rendered in **alphabetical order**. Use number prefixes (like `00-`, `01-`, `02-`) to control the sequence. diff --git a/app/default/content/examples/mix-formats/00-intro.no.md b/app/default/content/examples/mix-formats/00-intro.no.md new file mode 100644 index 0000000..358eb64 --- /dev/null +++ b/app/default/content/examples/mix-formats/00-intro.no.md @@ -0,0 +1,11 @@ +# Bland formater + +FolderWeb lar deg **kombinere forskjellige filtyper** i samme katalog. Markdown, HTML og PHP-filer kan eksistere side om side og rendres sammen på en enkelt side. + +## Støttede formater + +- **`.md`** – Markdown for innhold (denne filen!) +- **`.html`** – Statiske HTML-snippets +- **`.php`** – Dynamiske PHP-komponenter + +Alle filer i samme katalog rendres i **alfabetisk rekkefølge**. Bruk talprefikser (som `00-`, `01-`, `02-`) for å kontrollere sekvensen. diff --git a/app/default/content/examples/mix-formats/01-html-example.html b/app/default/content/examples/mix-formats/01-html-example.html new file mode 100644 index 0000000..7324c01 --- /dev/null +++ b/app/default/content/examples/mix-formats/01-html-example.html @@ -0,0 +1,11 @@ +
+

HTML Component

+

This section is rendered from 01-html-example.html – a static HTML file with inline styles.

+

HTML files are perfect for:

+ +
diff --git a/app/default/content/examples/mix-formats/01-html-example.no.html b/app/default/content/examples/mix-formats/01-html-example.no.html new file mode 100644 index 0000000..32142f6 --- /dev/null +++ b/app/default/content/examples/mix-formats/01-html-example.no.html @@ -0,0 +1,11 @@ +
+

HTML-komponent

+

Denne seksjonen rendres fra 01-html-example.no.html – en statisk HTML-fil med inline stiler.

+

HTML-filer er perfekte for:

+ +
diff --git a/app/default/content/examples/mix-formats/02-dynamic.no.php b/app/default/content/examples/mix-formats/02-dynamic.no.php new file mode 100644 index 0000000..28277f7 --- /dev/null +++ b/app/default/content/examples/mix-formats/02-dynamic.no.php @@ -0,0 +1,41 @@ + PHP_VERSION, + 'Servertid' => $currentTime, + 'Filer i denne katalogen' => count(glob(__DIR__ . '/*')), +]; +?> + +
+

PHP-komponent

+

Denne seksjonen rendres fra 02-dynamic.no.php – en dynamisk PHP-fil som kjører på serversiden.

+ + + + + + + + + + $value): ?> + + + + + + +
EgenskapVerdi
+ +

PHP-filer kan:

+ + +

Last inn denne siden på nytt for å se servertiden oppdatere seg!

+
diff --git a/app/default/content/examples/mix-formats/02-dynamic.php b/app/default/content/examples/mix-formats/02-dynamic.php new file mode 100644 index 0000000..7c0e989 --- /dev/null +++ b/app/default/content/examples/mix-formats/02-dynamic.php @@ -0,0 +1,41 @@ + PHP_VERSION, + 'Server Time' => $currentTime, + 'Files in this directory' => count(glob(__DIR__ . '/*')), +]; +?> + +
+

PHP Component

+

This section is rendered from 02-dynamic.php – a dynamic PHP file that executes server-side.

+ + + + + + + + + + $value): ?> + + + + + + +
PropertyValue
+ +

PHP files can:

+ + +

Refresh this page to see the server time update!

+
diff --git a/app/default/content/examples/mix-formats/03-conclusion.md b/app/default/content/examples/mix-formats/03-conclusion.md new file mode 100644 index 0000000..00f04f6 --- /dev/null +++ b/app/default/content/examples/mix-formats/03-conclusion.md @@ -0,0 +1,38 @@ +## Why Mix Formats? + +Different content types have different needs: + +**Markdown** – Fast authoring, readable source, perfect for articles and documentation + +**HTML** – Full control over structure, ideal for custom layouts and embedded media + +**PHP** – Dynamic content, server-side logic, database queries, real-time data + +By mixing them freely, you get the best of all worlds. Write most content in Markdown for speed, add HTML for custom sections, and use PHP when you need dynamic behavior. + +## This Page's Structure + +This very page demonstrates format mixing: + +``` +/examples/mix-formats/ +├── 00-intro.md (Markdown introduction) +├── 01-html-example.html (Static HTML component) +├── 02-dynamic.php (Dynamic PHP component) +├── 03-conclusion.md (Markdown conclusion) +└── metadata.ini (Page metadata) +``` + +All four content files render seamlessly as one cohesive page. The numbered prefixes ensure they appear in the intended order. + +## Use Cases + +**Blog with special sections** – Markdown posts with custom HTML callouts or PHP-generated stats + +**Documentation with demos** – Markdown explanations with live PHP examples + +**Landing pages** – Mix markdown content with custom HTML heroes and PHP dynamic elements + +**Portfolio sites** – Markdown project descriptions with HTML galleries and PHP filtering + +The flexibility is yours. diff --git a/app/default/content/examples/mix-formats/03-conclusion.no.md b/app/default/content/examples/mix-formats/03-conclusion.no.md new file mode 100644 index 0000000..833aaba --- /dev/null +++ b/app/default/content/examples/mix-formats/03-conclusion.no.md @@ -0,0 +1,38 @@ +## Hvorfor blande formater? + +Forskjellige innholdstyper har forskjellige behov: + +**Markdown** – Rask redigering, lesbar kilde, perfekt for artikler og dokumentasjon + +**HTML** – Full kontroll over struktur, ideelt for egendefinerte layout og innebygde medier + +**PHP** – Dynamisk innhold, server-side logikk, databasespørringer, sanntidsdata + +Ved å blande dem fritt, får du det beste fra alle verdener. Skriv mesteparten av innholdet i Markdown for hastighet, legg til HTML for egendefinerte seksjoner, og bruk PHP når du trenger dynamisk oppførsel. + +## Denne sidens struktur + +Denne siden demonstrerer formatblanding: + +``` +/examples/mix-formats/ +├── 00-intro.no.md (Markdown-introduksjon) +├── 01-html-example.no.html (Statisk HTML-komponent) +├── 02-dynamic.no.php (Dynamisk PHP-komponent) +├── 03-conclusion.no.md (Markdown-konklusjon) +└── metadata.ini (Sidemetadata) +``` + +Alle fire innholdsfilene rendres sømløst som én sammenhengende side. De nummererte prefiksene sikrer at de vises i ønsket rekkefølge. + +## Bruksområder + +**Blogg med spesialseksjoner** – Markdown-innlegg med egendefinerte HTML-callouts eller PHP-generert statistikk + +**Dokumentasjon med demoer** – Markdown-forklaringer med live PHP-eksempler + +**Landingssider** – Bland markdown-innhold med egendefinerte HTML-heroer og PHP-dynamiske elementer + +**Porteføljesider** – Markdown-prosjektbeskrivelser med HTML-gallerier og PHP-filtrering + +Fleksibiliteten er din. diff --git a/app/default/content/examples/mix-formats/metadata.ini b/app/default/content/examples/mix-formats/metadata.ini new file mode 100644 index 0000000..29e9702 --- /dev/null +++ b/app/default/content/examples/mix-formats/metadata.ini @@ -0,0 +1,3 @@ +title = "Mix Formats" +summary = "Combine Markdown, HTML, and PHP files to create rich, dynamic pages" +date = "2024-11-26" diff --git a/app/default/content/examples/nested/index.md b/app/default/content/examples/nested/index.md new file mode 100644 index 0000000..33718dd --- /dev/null +++ b/app/default/content/examples/nested/index.md @@ -0,0 +1,5 @@ +# Nested Content + +FolderWeb supports content nested as deep as you need. Your folder structure is your URL structure. + +This section demonstrates multi-level nesting. Explore the subdirectories to see how it works. diff --git a/app/default/content/examples/nested/level-two/index.md b/app/default/content/examples/nested/level-two/index.md new file mode 100644 index 0000000..8766f2b --- /dev/null +++ b/app/default/content/examples/nested/level-two/index.md @@ -0,0 +1,5 @@ +# Level Two + +This is two levels deep: `/examples/nested/level-two/` + +You can organize content in hierarchies that make sense for your site structure. diff --git a/app/default/content/examples/nested/level-two/level-three/index.md b/app/default/content/examples/nested/level-two/level-three/index.md new file mode 100644 index 0000000..a9a3114 --- /dev/null +++ b/app/default/content/examples/nested/level-two/level-three/index.md @@ -0,0 +1,5 @@ +# Level Three + +This is three levels deep: `/examples/nested/level-two/level-three/` + +The URL structure automatically follows your folder organization. No routing configuration needed. diff --git a/app/default/content/examples/nested/level-two/level-three/level-four/index.md b/app/default/content/examples/nested/level-two/level-three/level-four/index.md new file mode 100644 index 0000000..a2904b0 --- /dev/null +++ b/app/default/content/examples/nested/level-two/level-three/level-four/index.md @@ -0,0 +1,29 @@ +# Level Four + +Four levels deep: `/examples/nested/level-two/level-three/level-four/` + +## How Deep Can You Go? + +As deep as your filesystem allows. Each folder can contain: + +- Content files (`.md`, `.html`, `.php`) +- Subdirectories (which become sub-URLs) +- Assets (images, PDFs, etc.) +- A `metadata.ini` file +- A `styles.css` file for page-specific styles + +## Navigation + +There's no automatic breadcrumb generation in the default theme, but you can add it in a custom template by parsing the URL path. + +## Use Cases + +**Documentation sites** – Organize by category/subcategory/topic + +**Photo galleries** – Year/month/album/photo + +**Course content** – Course/module/lesson/exercise + +**Product catalogs** – Category/subcategory/product + +The simplicity of file-based routing means your content organization is transparent and portable. diff --git a/app/default/content/examples/no-build-step/index.md b/app/default/content/examples/no-build-step/index.md new file mode 100644 index 0000000..69caba1 --- /dev/null +++ b/app/default/content/examples/no-build-step/index.md @@ -0,0 +1,47 @@ +# No Build Step + +Modern web development often involves complex build pipelines: transpilers, bundlers, minifiers, watchers, and more. FolderWeb takes a different approach: **edit a file, refresh the page, see the result**. + +## What This Means + +**No npm install** – No package.json, no node_modules folder, no dependency hell + +**No compilation** – Write PHP, HTML, CSS, and Markdown directly + +**No watching** – No background processes monitoring file changes + +**No bundling** – Files are served as-is, leveraging HTTP/2 multiplexing + +**No transpiling** – Modern PHP 8.4+ and CSS work in all browsers + +## The Development Flow + +Traditional workflow: +``` +Edit file → Save → Wait for build → Reload → See changes +``` + +FolderWeb workflow: +``` +Edit file → Save → Reload → See changes +``` + +That's it. No waiting. No build errors. No cache invalidation headaches. + +## But What About... + +**Performance?** – PHP is fast. No JavaScript means pages load instantly. CSS is cacheable with MD5 versioning. + +**Minification?** – HTTP/2 compression handles this. Serve from behind a CDN if needed. + +**Modern CSS?** – CSS nesting, custom properties, oklch() colors, grid—all native, all supported. + +**Development speed?** – Instant feedback loop beats any hot reload system. + +## Why This Matters + +Build steps add complexity. Every dependency is a potential breaking change. Every tool is another thing to learn, configure, and maintain. + +FolderWeb will work the same way in 5 years, 10 years, even 20 years. Your content is just files. Your templates are just PHP. Your styles are just CSS. + +**Simple lasts.** diff --git a/app/default/content/examples/no-build-step/index.no.md b/app/default/content/examples/no-build-step/index.no.md new file mode 100644 index 0000000..675a87a --- /dev/null +++ b/app/default/content/examples/no-build-step/index.no.md @@ -0,0 +1,47 @@ +# Uten byggesteg + +Moderne webutvikling involverer ofte komplekse byggepipelines: transpilere, bundlere, minifisere, overvåkere og mer. FolderWeb tar en annen tilnærming: **rediger en fil, oppdater siden, se resultatet**. + +## Hva dette betyr + +**Ingen npm install** – Ingen package.json, ingen node_modules-mappe, ingen avhengighetshelvete + +**Ingen kompilering** – Skriv PHP, HTML, CSS og Markdown direkte + +**Ingen overvåkning** – Ingen bakgrunnsprosesser som overvåker filendringer + +**Ingen bundling** – Filer serveres som de er, ved å utnytte HTTP/2-multipleksing + +**Ingen transpilering** – Moderne PHP 8.4+ og CSS fungerer i alle nettlesere + +## Utviklingsflyten + +Tradisjonell arbeidsflyt: +``` +Rediger fil → Lagre → Vent på bygg → Last inn på nytt → Se endringer +``` + +FolderWeb-arbeidsflyt: +``` +Rediger fil → Lagre → Last inn på nytt → Se endringer +``` + +Det er det. Ingen venting. Ingen byggefeil. Ingen cache-invalideringshodebryet. + +## Men hva med... + +**Ytelse?** – PHP er rask. Ingen JavaScript betyr at sider lastes øyeblikkelig. CSS er cachebar med MD5-versjonering. + +**Minifisering?** – HTTP/2-kompresjon håndterer dette. Server fra bak en CDN om nødvendig. + +**Moderne CSS?** – CSS-nesting, custom properties, oklch()-farger, grid—alt native, alt støttet. + +**Utviklingshastighet?** – Øyeblikkelig tilbakemeldingssløyfe slår ethvert hot reload-system. + +## Hvorfor dette betyr noe + +Byggesteg legger til kompleksitet. Hver avhengighet er en potensiell breaking change. Hvert verktøy er noe nytt å lære, konfigurere og vedlikeholde. + +FolderWeb vil fungere på samme måte om 5 år, 10 år, til og med 20 år. Innholdet ditt er bare filer. Malene dine er bare PHP. Stilene dine er bare CSS. + +**Enkelt varer.** diff --git a/app/default/content/examples/no-build-step/metadata.ini b/app/default/content/examples/no-build-step/metadata.ini new file mode 100644 index 0000000..aeef2e9 --- /dev/null +++ b/app/default/content/examples/no-build-step/metadata.ini @@ -0,0 +1,3 @@ +title = "No Build Step" +summary = "Edit, save, refresh—that's it. No compilation, no bundling, no waiting" +date = "2024-11-26" diff --git a/app/default/content/examples/templates-demo/compact-example/2024-10-10-oldest-post/index.md b/app/default/content/examples/templates-demo/compact-example/2024-10-10-oldest-post/index.md new file mode 100644 index 0000000..0269bef --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/2024-10-10-oldest-post/index.md @@ -0,0 +1,3 @@ +# Oldest Post + +The oldest post in this compact list. diff --git a/app/default/content/examples/templates-demo/compact-example/2024-11-15-older-post/index.md b/app/default/content/examples/templates-demo/compact-example/2024-11-15-older-post/index.md new file mode 100644 index 0000000..634aeb5 --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/2024-11-15-older-post/index.md @@ -0,0 +1,3 @@ +# Older Post + +An older post showing date ordering. diff --git a/app/default/content/examples/templates-demo/compact-example/2024-12-01-recent-post/index.md b/app/default/content/examples/templates-demo/compact-example/2024-12-01-recent-post/index.md new file mode 100644 index 0000000..70d8cc0 --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/2024-12-01-recent-post/index.md @@ -0,0 +1,3 @@ +# Recent Post + +A recent example post. diff --git a/app/default/content/examples/templates-demo/compact-example/index.md b/app/default/content/examples/templates-demo/compact-example/index.md new file mode 100644 index 0000000..552ee94 --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/index.md @@ -0,0 +1,3 @@ +# Compact Template + +This section uses `list-compact.php` for a minimal, clean list view. diff --git a/app/default/content/examples/templates-demo/compact-example/metadata.ini b/app/default/content/examples/templates-demo/compact-example/metadata.ini new file mode 100644 index 0000000..a98e845 --- /dev/null +++ b/app/default/content/examples/templates-demo/compact-example/metadata.ini @@ -0,0 +1,4 @@ +title = "Compact Template Example" + +[settings] +page_template = "list-compact" diff --git a/app/default/content/examples/templates-demo/grid-example/index.md b/app/default/content/examples/templates-demo/grid-example/index.md new file mode 100644 index 0000000..33a8ba9 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/index.md @@ -0,0 +1,3 @@ +# Grid Template + +This section uses `list-grid.php` to display items in a responsive grid with cards. diff --git a/app/default/content/examples/templates-demo/grid-example/item-one/index.md b/app/default/content/examples/templates-demo/grid-example/item-one/index.md new file mode 100644 index 0000000..91c74d9 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-one/index.md @@ -0,0 +1,3 @@ +# Grid Item One + +This is an example item in the grid layout. diff --git a/app/default/content/examples/templates-demo/grid-example/item-one/metadata.ini b/app/default/content/examples/templates-demo/grid-example/item-one/metadata.ini new file mode 100644 index 0000000..39293ad --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-one/metadata.ini @@ -0,0 +1 @@ +summary = "First item demonstrating grid layout" diff --git a/app/default/content/examples/templates-demo/grid-example/item-three/index.md b/app/default/content/examples/templates-demo/grid-example/item-three/index.md new file mode 100644 index 0000000..5e945e1 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-three/index.md @@ -0,0 +1,3 @@ +# Grid Item Three + +A third item to show the grid layout with multiple items. diff --git a/app/default/content/examples/templates-demo/grid-example/item-three/metadata.ini b/app/default/content/examples/templates-demo/grid-example/item-three/metadata.ini new file mode 100644 index 0000000..db23a37 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-three/metadata.ini @@ -0,0 +1 @@ +summary = "Third grid item" diff --git a/app/default/content/examples/templates-demo/grid-example/item-two/index.md b/app/default/content/examples/templates-demo/grid-example/item-two/index.md new file mode 100644 index 0000000..bf06247 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-two/index.md @@ -0,0 +1,3 @@ +# Grid Item Two + +Another example showing how items appear in the grid. diff --git a/app/default/content/examples/templates-demo/grid-example/item-two/metadata.ini b/app/default/content/examples/templates-demo/grid-example/item-two/metadata.ini new file mode 100644 index 0000000..d32da37 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/item-two/metadata.ini @@ -0,0 +1 @@ +summary = "Second item in the grid" diff --git a/app/default/content/examples/templates-demo/grid-example/metadata.ini b/app/default/content/examples/templates-demo/grid-example/metadata.ini new file mode 100644 index 0000000..958c6a0 --- /dev/null +++ b/app/default/content/examples/templates-demo/grid-example/metadata.ini @@ -0,0 +1,4 @@ +title = "Grid Template Example" + +[settings] +page_template = "list-grid" diff --git a/app/default/content/examples/templates-demo/index.md b/app/default/content/examples/templates-demo/index.md new file mode 100644 index 0000000..e6a777d --- /dev/null +++ b/app/default/content/examples/templates-demo/index.md @@ -0,0 +1,24 @@ +# List Templates + +FolderWeb includes several list templates you can use for different presentation styles. + +This section demonstrates the different templates by using subdirectories. Each subdirectory below uses a different template via `metadata.ini`. + +## Available Templates + +**list.php** – Default linear list with optional cover images + +**list-grid.php** – Grid layout with cards, great for galleries or portfolios + +**list-compact.php** – Minimal list showing just titles and dates + +## Choosing a Template + +In any folder's `metadata.ini`, add: + +```ini +[settings] +page_template = "list-grid" +``` + +The three subdirectories below each use a different template. Compare them to see which fits your content best. diff --git a/app/default/content/front.md b/app/default/content/front.md deleted file mode 100644 index 27fddd9..0000000 --- a/app/default/content/front.md +++ /dev/null @@ -1,11 +0,0 @@ -# Welcome to FolderWeb - -This is the default content. Replace it by adding your own files to the `content/` directory. - -Your folder structure becomes your site structure — create a folder, drop in a `.md`, `.html`, or `.php` file, and it's a page. - -## Getting Started - -1. Create a `content/` directory in your project root -2. Copy `app/default/` to `custom/` to start customizing -3. Add content files and refresh the browser diff --git a/app/default/content/front.no.md b/app/default/content/front.no.md deleted file mode 100644 index 58f86ef..0000000 --- a/app/default/content/front.no.md +++ /dev/null @@ -1,11 +0,0 @@ -# Velkommen til FolderWeb - -Dette er standardinnholdet. Erstatt det ved å legge til egne filer i `content/`-mappen. - -Mappestrukturen din blir nettstedets struktur — opprett en mappe, legg inn en `.md`-, `.html`- eller `.php`-fil, og den blir en side. - -## Kom i gang - -1. Opprett en `content/`-mappe i prosjektets rotmappe -2. Kopier `app/default/` til `custom/` for å begynne å tilpasse -3. Legg til innholdsfiler og oppdater nettleseren diff --git a/app/default/content/multilingual/index.en.md b/app/default/content/multilingual/index.en.md new file mode 100644 index 0000000..0fa5c7b --- /dev/null +++ b/app/default/content/multilingual/index.en.md @@ -0,0 +1,53 @@ +# Multilingual Support + +**Currently viewing: English (EN)** + +This page demonstrates FolderWeb's built-in language support. Use the language switcher in the header to toggle between **EN** and **NO** - the page content will change to match your selected language. + +## How It Works + +Creating multilingual content is straightforward: + +1. **Add language codes to filenames** – Create `index.en.md` and `index.no.md` +2. **Language switcher appears automatically** – When multiple versions exist +3. **URLs get language prefixes** – Non-default languages use `/en/page/`, `/no/page/`, etc. +4. **Share metadata** – One `metadata.ini` file per directory works for all languages + +## File Structure Example + +``` +/content/about/ +├── index.en.md # English version +├── index.no.md # Norwegian version +└── metadata.ini # Shared metadata +``` + +## Configuration + +Enable languages in `/app/default/config.ini`: + +```ini +[languages] +default = "en" +available = "en,no" +``` + +## Translation Strings + +UI text comes from language files in `/app/default/languages/`: + +```ini +; en.ini +home = "Home" +read_more = "Read more" + +; no.ini +home = "Hjem" +read_more = "Les mer" +``` + +Translation strings are optional—templates fall back to sensible defaults if missing. + +## Try It + +Use the language switcher in the header to toggle between English and Norwegian versions of this page. The content stays the same, just translated. diff --git a/app/default/content/multilingual/index.no.md b/app/default/content/multilingual/index.no.md new file mode 100644 index 0000000..a610b23 --- /dev/null +++ b/app/default/content/multilingual/index.no.md @@ -0,0 +1,53 @@ +# Flerspråklig støtte + +**Viser nå: Norsk (NO)** + +Denne siden demonstrerer FolderWebs innebygde språkstøtte. Bruk språkvelgeren i headeren for å bytte mellom **EN** og **NO** - sideinnholdet vil endre seg til å matche det valgte språket. + +## Slik fungerer det + +Å opprette flerspråklig innhold er enkelt: + +1. **Legg til språkkoder i filnavn** – Opprett `index.en.md` og `index.no.md` +2. **Språkvelgeren vises automatisk** – Når flere versjoner finnes +3. **URL-er får språkprefikser** – Ikke-standardspråk bruker `/en/side/`, `/no/side/`, osv. +4. **Del metadata** – Én `metadata.ini`-fil per katalog fungerer for alle språk + +## Eksempel på filstruktur + +``` +/content/om/ +├── index.en.md # Engelsk versjon +├── index.no.md # Norsk versjon +└── metadata.ini # Delt metadata +``` + +## Konfigurasjon + +Aktiver språk i `/app/default/config.ini`: + +```ini +[languages] +default = "en" +available = "en,no" +``` + +## Oversettelsesstrenger + +UI-tekst kommer fra språkfiler i `/app/default/languages/`: + +```ini +; en.ini +home = "Home" +read_more = "Read more" + +; no.ini +home = "Hjem" +read_more = "Les mer" +``` + +Oversettelsesstrenger er valgfrie—maler faller tilbake til fornuftige standardverdier hvis de mangler. + +## Prøv det + +Bruk språkvelgeren i headeren for å bytte mellom engelske og norske versjoner av denne siden. Innholdet forblir det samme, bare oversatt. diff --git a/app/default/content/multilingual/metadata.ini b/app/default/content/multilingual/metadata.ini new file mode 100644 index 0000000..66a04f1 --- /dev/null +++ b/app/default/content/multilingual/metadata.ini @@ -0,0 +1,2 @@ +title = "Multilingual Support" +summary = "Learn how to create content in multiple languages" diff --git a/app/default/content/styles.css b/app/default/content/styles.css new file mode 100644 index 0000000..0abceb8 --- /dev/null +++ b/app/default/content/styles.css @@ -0,0 +1,112 @@ +/* Hero section for frontpage */ +.hero { + background: linear-gradient(135deg, oklch(95% 0.05 250) 0%, oklch(98% 0.02 250) 100%); + border-radius: 0.75rem; + padding: var(--space-m); + margin-block: var(--space-s); + text-align: center; + + & .hero-title { + font-size: clamp(2rem, 5vw, 2.5rem); + margin-block: 0 var(--space-xs); + background: linear-gradient(135deg, oklch(40% 0.15 250), oklch(30% 0.2 280)); + background-clip: text; + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-weight: 900; + } + + & .hero-subtitle { + font-size: clamp(1rem, 2vw, 1.125rem); + color: var(--color-muted); + margin-block-end: var(--space-m); + max-width: 32rem; + margin-inline: auto; + } + + & .cta-button { + display: inline-block; + background: var(--color-accent); + color: white; + padding: var(--space-xs) var(--space-m); + border-radius: 0.5rem; + text-decoration: none; + font-weight: 600; + margin-block-start: var(--space-xs); + + &:hover { + background: oklch(45% 0.15 250); + color: white; + } + } +} + +.features { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(min(100%, 9rem), 1fr)); + gap: var(--space-s); + margin-block: var(--space-m); + + & .feature-card { + background: var(--color-background); + padding: var(--space-s); + border-radius: 0.5rem; + border: 1px solid var(--color-border); + text-align: center; + transition: transform 0.2s, box-shadow 0.2s; + text-decoration: none; + color: inherit; + display: block; + + &:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px oklch(0% 0 0 / 0.1); + border-color: var(--color-accent); + } + + & .feature-icon { + font-size: 2rem; + display: block; + margin-block-end: var(--space-xs); + } + + & .feature-title { + font-weight: bold; + margin-block: var(--space-xs); + color: var(--color-text); + font-size: 0.9rem; + } + + & .feature-description { + font-size: 0.85rem; + color: var(--color-muted); + margin: 0; + } + } +} + +.stats { + display: flex; + justify-content: center; + gap: var(--space-m); + flex-wrap: wrap; + margin-block-start: var(--space-m); + padding-block-start: var(--space-s); + border-block-start: 1px solid var(--color-border); + + & .stat { + text-align: center; + + & .stat-value { + display: block; + font-size: 1.25rem; + font-weight: bold; + color: var(--color-accent); + } + + & .stat-label { + font-size: 0.8rem; + color: var(--color-muted); + } + } +} diff --git a/app/default/styles/styles.css b/app/default/styles/styles.css index e94e52a..2c8d029 100644 --- a/app/default/styles/styles.css +++ b/app/default/styles/styles.css @@ -1,11 +1,8 @@ -/* RESET */ -* { box-sizing: border-box; margin-bottom: 0 } - -/* VARIABLES */ :root { --color-text: oklch(20% 0 0); --color-background: oklch(98% 0 0); --color-accent: oklch(50% 0.15 250); + --color-accent-light: oklch(95% 0.05 250); --color-border: oklch(85% 0 0); --color-muted: oklch(50% 0 0); @@ -14,13 +11,17 @@ --space-m: 2rem; --space-l: 4rem; - --size-content: 42rem; + --size-content: 65ch; + --size-constrained: 42rem; + --size-wide: 90rem; +} + +* { + box-sizing: border-box; } -/* GLOBAL */ html { font-family: system-ui, sans-serif; - font-size: clamp(16px, 2.3vw, 20px); line-height: 1.6; color: var(--color-text); background: var(--color-background); @@ -29,99 +30,139 @@ html { body { margin: 0; display: grid; + grid-template-columns: + [full-start] minmax(var(--space-s), 1fr) + [content-start] minmax(0, var(--size-constrained)) + [content-end] minmax(var(--space-s), 1fr) + [full-end]; grid-template-rows: auto 1fr auto; min-height: 100vh; } -/* CONTENT CENTERING */ -.contain, :where(main > article, main > section, main > div) { - display: grid; - grid-template-columns: minmax(var(--space-s), 1fr) minmax(0, var(--size-content)) minmax(var(--space-s), 1fr); - & > * { grid-column: 2 } -} - -/* TYPOGRAPHY */ h1, h2, h3, h4, h5, h6 { - font-weight: 400; - line-height: 1.3; - margin-top: 1.3em; - text-wrap: pretty; + line-height: 1.2; + margin-block: 1.5em 0.5em; } -h1 { font-size: 2.3rem } -h4 { font-weight: 700 } -p, ul, ol, dl { margin-block: 1em } +h1 { font-size: clamp(2rem, 5vw, 3rem); } +h2 { font-size: clamp(1.5rem, 4vw, 2rem); } +h3 { font-size: clamp(1.25rem, 3vw, 1.5rem); } + +p, ul, ol, dl { + max-width: var(--size-content); + margin-block: 1em; +} a { color: var(--color-accent); - text-decoration: none; - &:hover { text-decoration: underline } + text-underline-offset: 0.2em; + + &:hover { + text-decoration: none; + } } -img { max-width: 100%; height: auto; display: block } +header, main, footer { + grid-column: content; +} -/* HEADER */ header { - border-bottom: 1px solid var(--color-border); - - & > div { - display: flex; - flex-wrap: wrap; - gap: var(--space-s); - align-items: center; - padding-block: var(--space-s); - } + border-block-end: 1px solid var(--color-border); + padding-block: var(--space-s); + display: flex; + flex-wrap: wrap; + gap: var(--space-s); + align-items: center; & nav { display: flex; gap: var(--space-s); flex-wrap: wrap; - align-items: center; - &:first-child { flex: 1 } + &:first-child { + flex: 1; + } & a { text-decoration: none; - &:hover { text-decoration: underline } - &[aria-current] { font-weight: bold } + + &:hover { + text-decoration: underline; + } + + &[aria-current] { + font-weight: bold; + } } } + + & .language-switcher { + margin-inline-start: auto; + } } -/* MAIN */ -main { padding-block: var(--space-m) } +main { + padding-block: var(--space-m); +} -/* FOOTER */ footer { - border-top: 1px solid var(--color-border); + border-block-start: 1px solid var(--color-border); padding-block: var(--space-s); font-size: 0.875rem; color: var(--color-muted); - & p { margin: 0 } + + & nav { + display: flex; + gap: var(--space-s); + margin-block-end: var(--space-xs); + } + + & p { + margin: 0; + } +} + +img { + max-width: 100%; + height: auto; + display: block; } -/* CODE */ code { - background: oklch(95% 0.02 250); + background: var(--color-accent-light); padding: 0.125em 0.25em; border-radius: 0.25em; font-size: 0.9em; } pre { - background: oklch(95% 0.02 250); + background: var(--color-accent-light); padding: var(--space-s); border-radius: 0.5em; overflow-x: auto; - & code { background: none; padding: 0 } + + & code { + background: none; + padding: 0; + } } -/* TABLES */ -table { border-collapse: collapse; width: 100%; margin-block: var(--space-s) } -th, td { padding: var(--space-xs); text-align: start; border-bottom: 1px solid var(--color-border) } -th { font-weight: bold } +table { + border-collapse: collapse; + width: 100%; + margin-block: var(--space-s); +} + +th, td { + padding: var(--space-xs); + text-align: start; + border-block-end: 1px solid var(--color-border); +} + +th { + font-weight: bold; +} -/* BLOCKQUOTES */ blockquote { margin-inline: 0; padding-inline-start: var(--space-s); @@ -129,41 +170,9 @@ blockquote { color: var(--color-muted); } -/* ARTICLE */ -article time { color: var(--color-muted); font-size: 0.875rem } - -/* LIST VIEWS */ -.list-item { - margin-bottom: var(--space-m); - & img { margin-bottom: var(--space-xs) } - & h2 { margin-top: 0 } -} - -.grid { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr)); - gap: var(--space-m); -} - -.card { - border: 1px solid var(--color-border); - border-radius: 0.5rem; - padding: var(--space-s); - & img { margin-bottom: var(--space-xs); border-radius: 0.25rem } - & h3 { margin-top: 0 } -} - -.compact-list { - list-style: none; - padding: 0; - & li { border-bottom: 1px solid var(--color-border); padding-block: var(--space-xs) } - & a { - display: flex; - justify-content: space-between; - align-items: baseline; - gap: var(--space-s); - &:hover strong { text-decoration: underline } +article { + & time { + color: var(--color-muted); + font-size: 0.875rem; } - & time { white-space: nowrap; font-size: 0.875rem } - & p { margin-top: var(--space-xs); color: var(--color-muted); font-size: 0.9rem } } diff --git a/app/default/templates/base.php b/app/default/templates/base.php index a2b643c..d739dbe 100644 --- a/app/default/templates/base.php +++ b/app/default/templates/base.php @@ -1,14 +1,3 @@ - @@ -21,7 +10,7 @@ if (file_exists($customCssPath)) { - + @@ -30,34 +19,41 @@ if (file_exists($customCssPath)) { -
-
-
+ + 1): ?> + +
- +
-