6 Commits

Author SHA1 Message Date
81c239f043 added matomo 2026-01-09 12:41:55 -08:00
0d91b61bd0 control panel head changes 2025-12-22 18:32:35 -08:00
fd9a71c4d6 added page to the front end 2025-12-16 05:35:56 -08:00
71413283c8 added humans and robots 2025-12-15 09:54:57 -08:00
a32956b4a2 added coming soon page 2025-12-15 09:28:09 -08:00
7bf3dc6610 added coming soon page 2025-12-15 09:27:56 -08:00
19 changed files with 464 additions and 115 deletions

View File

@@ -0,0 +1,9 @@
<?php
$data = array_merge($data, [
'title' => 'Coming Soon',
'heading' => 'Coming Soon',
'countdown' => true,
'launch_date' => '2026-01-01T00:00:00'
]);
view('@novacore/coming-soon', $data);

View File

@@ -0,0 +1,94 @@
body#coming-soon
display: flex
justify-content: center
align-items: center
height: 100%
padding: 1rem
box-sizing: border-box
margin: 0
text-align: center
color: #eee
font-family: 'Segoe UI', Roboto, sans-serif
background-size: cover
background-repeat: no-repeat
background-position: center center
background-attachment: fixed
.container
max-width: 600px
background-color: rgba(30, 30, 30, 0.89)
padding: 2rem
border-radius: 8px
box-shadow: 0 0 20px rgba(0,0,0,0.5)
h1
font-size: 3rem
margin-bottom: 1rem
animation: pulse 1.5s infinite
p
font-size: 1.2rem
opacity: 0.85
margin-bottom: 1.5rem
.countdown
font-size: 2rem
font-weight: bold
margin: 1rem 0 2rem 0
form.newsletter
display: flex
flex-direction: column
gap: 0.5rem
margin-top: 1rem
input[type="email"]
padding: 0.5rem
font-size: 1rem
border: 1px solid #666
border-radius: 4px
background: rgba(255,255,255,0.05)
color: #eee
button
padding: 0.5rem
font-size: 1rem
border: 1px solid #1e90ff
border-radius: 4px
background: #1e90ff
color: #fff
cursor: pointer
transition: background 0.2s
&:hover
background: #1565c0
.social-icons
margin-top: 2rem
display: flex
justify-content: center
gap: 1rem
a
display: inline-flex
align-items: center
justify-content: center
width: 40px
height: 40px
font-size: 1.5rem
color: #eee
text-decoration: none
transition: color 0.2s
&:hover
color: #1e90ff
i
font-style: normal
@keyframes pulse
0%, 100%
opacity: 0.8
50%
opacity: 1

View File

@@ -3,3 +3,4 @@
@use 'base' as * @use 'base' as *
@use 'framework' as * @use 'framework' as *
@use 'controlPanel' as * @use 'controlPanel' as *
@use 'coming-soon' as *

View File

@@ -10,6 +10,7 @@ $config = [
'base_url' => 'http://localhost:8000', 'base_url' => 'http://localhost:8000',
'secure_key' => '', //64 alphanumeric characters 'secure_key' => '', //64 alphanumeric characters
'logfile' => '/logs/novaconium.log', 'logfile' => '/logs/novaconium.log',
'loglevel' => 'ERROR', // 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'NONE' 'loglevel' => 'ERROR', // 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'NONE',
'matomo' => '1',
'fonts' => 'https://fonts.googleapis.com/css2?family=VT323:wght@400&family=Fira+Code:wght@400;500&display=swap&family=Material+Icons:wght@400;500&display=swap' 'fonts' => 'https://fonts.googleapis.com/css2?family=VT323:wght@400&family=Fira+Code:wght@400;500&display=swap&family=Material+Icons:wght@400;500&display=swap'
]; ];

View File

@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);
header('Content-Type: text/plain; charset=UTF-8');
header('Cache-Control: public, max-age=604800');
echo <<<TXT
/*
* This humans.txt was generated by the framework.
* You may edit or remove it without affecting your site.
*/
/* FRAMEWORK */
Built With: Novaconium PHP
repo: https://git.4lt.ca/4lt/novaconium
Human: Nick Yeoman
url: https://www.nickyeoman.com/
Occupation: Linux Systems Administrator / Software Framework Author
Location: Canada
/* SITE */
Built with: Novaconium PHP
Runs on: CORXN Container
Optimized for: Humans
/* META */
There are four lights.
TXT;

View File

@@ -0,0 +1,33 @@
<?php
$slug = $router->parameters['slug'];
$query=<<<EOSQL
SELECT
id,
title,
heading,
description,
keywords,
author,
body,
created,
updated
FROM pages
WHERE slug = '$slug'
EOSQL;
//$db->debugGetRow($query);
$data = $db->getRow($query);
if(!$data) {
http_response_code('404');
header("Content-Type: text/html");
view('404');
exit;
}
$data = array_merge($data, [
'menuActive' => 'blog',
'pageid' => 'page',
'permissionsGroup' => $session->get('group')
]);
view('page', $data);

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
// Send proper headers
header('Content-Type: text/plain; charset=UTF-8');
header('Cache-Control: public, max-age=604800');
// Use $config['base_url'] as-is
$baseUrl = $config['base_url'];
echo <<<TXT
# robots.txt for sites powered by Novaconium framework
User-agent: *
Disallow: /novaconium/
Sitemap: {$baseUrl}/sitemap.xml
TXT;

View File

@@ -2,5 +2,14 @@
$routes = [ $routes = [
'/' => [ '/' => [
'get' => 'index' 'get' => 'index'
],
'/robots.txt' => [
'get' => 'robots'
],
'/humans.txt' => [
'get' => 'humans'
],
'/page/{slug}' => [
'get' => 'page'
] ]
]; ];

View File

@@ -0,0 +1,11 @@
{% extends '@novaconium/master.html.twig' %}
{% block content %}
<h1>{{ title }}</h1>
<div class="page-meta">
{% if updated is not empty %}
<span class="page-updated">Last Updated: {{ updated | date("M\\. jS Y \\a\\t g:ia") }}</span>
{% endif %}
</div>
{{ body | raw}}
{% endblock %}

File diff suppressed because one or more lines are too long

View File

@@ -1,16 +1,4 @@
<?php <?php
/**
* Novaconium Framework Entry Point
*
* This is the main entry point for the Novaconium framework.
* It sets up the environment, loads necessary components,
* and runs the application.
*
* @package Novaconium
* @author Nick Yeoman <dev@4lt.ca>
*/
// Enable error reporting for development environments // Enable error reporting for development environments
// error_reporting(E_ALL); // error_reporting(E_ALL);
// ini_set('display_errors', 1); // ini_set('display_errors', 1);

View File

@@ -1,5 +1,6 @@
<script> // /js/tabs.js
// Tab switching JS (unchanged)
// Tab switching
function switchTab(tabId, button) { function switchTab(tabId, button) {
const contents = document.querySelectorAll('.tab-content'); const contents = document.querySelectorAll('.tab-content');
contents.forEach(content => content.classList.remove('active')); contents.forEach(content => content.classList.remove('active'));
@@ -17,6 +18,7 @@ function switchTab(tabId, button) {
// Tags Init (with custom dropdown autocomplete) // Tags Init (with custom dropdown autocomplete)
let tagsListeners = []; let tagsListeners = [];
function initTags() { function initTags() {
const tagsInput = document.getElementById('tags-input'); const tagsInput = document.getElementById('tags-input');
const tagsField = document.getElementById('tags'); const tagsField = document.getElementById('tags');
@@ -28,7 +30,7 @@ function initTags() {
return; return;
} }
// Clean old listeners // Remove old listeners
tagsListeners.forEach(ls => ls()); tagsListeners.forEach(ls => ls());
tagsListeners = []; tagsListeners = [];
@@ -39,13 +41,10 @@ function initTags() {
existingTags = JSON.parse(tagsInput.dataset.existingTags || '[]'); existingTags = JSON.parse(tagsInput.dataset.existingTags || '[]');
} catch (e) { } catch (e) {
console.warn('JSON error:', e); console.warn('JSON error:', e);
tags = [];
existingTags = [];
} }
let selectedIndex = -1; // For keyboard nav let selectedIndex = -1;
// Render chips (unchanged)
function renderTags() { function renderTags() {
tagsInput.innerHTML = ''; tagsInput.innerHTML = '';
tags.forEach((tag, index) => { tags.forEach((tag, index) => {
@@ -60,11 +59,10 @@ function initTags() {
tagsInput.appendChild(chip); tagsInput.appendChild(chip);
}); });
tagsInput.appendChild(tagsField); tagsInput.appendChild(tagsField);
tagsInput.appendChild(dropdown); // Re-add dropdown tagsInput.appendChild(dropdown);
hiddenTags.value = JSON.stringify(tags); hiddenTags.value = JSON.stringify(tags);
} }
// Filter and render dropdown
function updateDropdown() { function updateDropdown() {
const value = tagsField.value.toLowerCase().trim(); const value = tagsField.value.toLowerCase().trim();
dropdown.innerHTML = ''; dropdown.innerHTML = '';
@@ -73,9 +71,9 @@ function initTags() {
if (!value) return; if (!value) return;
const matches = existingTags.filter(tag => const matches = existingTags
tag.toLowerCase().startsWith(value) && !tags.includes(tag.toLowerCase()) .filter(tag => tag.toLowerCase().startsWith(value) && !tags.includes(tag.toLowerCase()))
).slice(0, 10); // Top 10 matches, exclude existing .slice(0, 10);
matches.forEach((tag, index) => { matches.forEach((tag, index) => {
const li = document.createElement('li'); const li = document.createElement('li');
@@ -90,21 +88,18 @@ function initTags() {
else dropdown.parentElement.classList.remove('has-dropdown'); else dropdown.parentElement.classList.remove('has-dropdown');
} }
// Highlight selected in dropdown
function updateHighlight() { function updateHighlight() {
dropdown.querySelectorAll('li').forEach((li, index) => { dropdown.querySelectorAll('li').forEach((li, index) => {
li.classList.toggle('selected', index === selectedIndex); li.classList.toggle('selected', index === selectedIndex);
}); });
} }
// Select tag from dropdown
function selectTag(tag) { function selectTag(tag) {
addTag(tag, true); // Add as chip, refocus addTag(tag, true);
tagsField.value = ''; // Clear input tagsField.value = '';
dropdown.setAttribute('aria-expanded', 'false'); dropdown.setAttribute('aria-expanded', 'false');
} }
// Add tag (unchanged)
function addTag(inputValue, refocus = false) { function addTag(inputValue, refocus = false) {
const tag = inputValue.trim().toLowerCase().replace(/[^\w-]/g, ''); const tag = inputValue.trim().toLowerCase().replace(/[^\w-]/g, '');
if (tag && tag.length > 0 && tag.length <= 50 && !tags.includes(tag)) { if (tag && tag.length > 0 && tag.length <= 50 && !tags.includes(tag)) {
@@ -113,67 +108,63 @@ function initTags() {
if (refocus) tagsField.focus(); if (refocus) tagsField.focus();
} }
tagsField.value = ''; tagsField.value = '';
updateDropdown(); // Hide dropdown after add updateDropdown();
} }
// Events: Enter/comma/TAB adds tag (no form submit) const keydownListener = (e) => {
const keydownListener = (e) => { if (dropdown.getAttribute('aria-expanded') === 'true') {
console.log('Keydown:', e.key, 'Value:', tagsField.value, 'Selected:', selectedIndex); if (e.key === 'ArrowDown') {
if (dropdown.getAttribute('aria-expanded') === 'true') { e.preventDefault();
if (e.key === 'ArrowDown') { selectedIndex = Math.min(selectedIndex + 1, dropdown.querySelectorAll('li').length - 1);
e.preventDefault(); updateHighlight();
selectedIndex = Math.min(selectedIndex + 1, dropdown.querySelectorAll('li').length - 1); dropdown.querySelector(`li:nth-child(${selectedIndex + 1})`)?.scrollIntoView({ block: 'nearest' });
updateHighlight(); } else if (e.key === 'ArrowUp') {
dropdown.querySelector(`li:nth-child(${selectedIndex + 1})`).scrollIntoView({ block: 'nearest' }); e.preventDefault();
} else if (e.key === 'ArrowUp') { selectedIndex = Math.max(selectedIndex - 1, 0);
e.preventDefault(); updateHighlight();
selectedIndex = Math.max(selectedIndex - 1, 0); dropdown.querySelector(`li:nth-child(${selectedIndex + 1})`)?.scrollIntoView({ block: 'nearest' });
updateHighlight(); } else if ((e.key === 'Enter' || e.key === 'Tab') && selectedIndex >= 0) {
dropdown.querySelector(`li:nth-child(${selectedIndex + 1})`).scrollIntoView({ block: 'nearest' }); e.preventDefault();
} else if ((e.key === 'Enter' || e.key === 'Tab') && selectedIndex >= 0) { const selected = dropdown.querySelector(`li:nth-child(${selectedIndex + 1})`)?.textContent;
e.preventDefault(); if (selected) selectTag(selected);
const selected = dropdown.querySelector(`li:nth-child(${selectedIndex + 1})`).textContent; } else if (e.key === 'Escape') {
selectTag(selected); // Adds chip, refocuses e.preventDefault();
} else if (e.key === 'Escape') { tagsField.blur();
e.preventDefault(); }
tagsField.blur();
} }
}
// Fallback for no dropdown or non-selected Tab/Enter if (!dropdown.getAttribute('aria-expanded') === 'true' || selectedIndex < 0) {
if (!dropdown.getAttribute('aria-expanded') === 'true' || selectedIndex < 0) { if (e.key === 'Enter' || e.key === ',') {
if (e.key === 'Enter' || e.key === ',') { e.preventDefault();
e.preventDefault(); addTag(tagsField.value, true);
addTag(tagsField.value, true); } else if (e.key === 'Tab') {
} else if (e.key === 'Tab') { e.preventDefault();
e.preventDefault(); if (tagsField.value.trim()) addTag(tagsField.value, true);
if (tagsField.value.trim()) addTag(tagsField.value, true); // Add typed value, refocus }
} }
} };
};
tagsField.addEventListener('keydown', keydownListener); tagsField.addEventListener('keydown', keydownListener);
tagsListeners.push(() => tagsField.removeEventListener('keydown', keydownListener)); tagsListeners.push(() => tagsField.removeEventListener('keydown', keydownListener));
const inputListener = () => updateDropdown(); const inputListener = () => updateDropdown();
tagsField.addEventListener('input', inputListener); tagsField.addEventListener('input', inputListener);
tagsListeners.push(() => tagsField.removeEventListener('input', inputListener)); tagsListeners.push(() => tagsField.removeEventListener('input', inputListener));
const blurListener = () => { const blurListener = () => {
setTimeout(() => dropdown.setAttribute('aria-expanded', 'false'), 150); // Hide after blur setTimeout(() => dropdown.setAttribute('aria-expanded', 'false'), 150);
if (tagsField.value.trim()) addTag(tagsField.value); if (tagsField.value.trim()) addTag(tagsField.value);
}; };
tagsField.addEventListener('blur', blurListener); tagsField.addEventListener('blur', blurListener);
tagsListeners.push(() => tagsField.removeEventListener('blur', blurListener)); tagsListeners.push(() => tagsField.removeEventListener('blur', blurListener));
// Initial render
renderTags(); renderTags();
console.log('Tags ready with autocomplete, loaded:', tags.length, 'tags');
} }
// Init on load + observe (unchanged) // Init on load and observe tab changes
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', () => {
const tagsTab = document.getElementById('content6'); const tagsTab = document.getElementById('content6');
if (tagsTab && tagsTab.classList.contains('active')) { if (tagsTab?.classList.contains('active')) {
initTags(); initTags();
} }
@@ -189,4 +180,6 @@ document.addEventListener('DOMContentLoaded', function() {
}); });
observer.observe(document.body, { subtree: true, attributes: true }); observer.observe(document.body, { subtree: true, attributes: true });
}); });
</script>
// Export switchTab for external use if needed
window.switchTab = switchTab;

View File

@@ -17,6 +17,7 @@ $log = new Logger(\BASEPATH . $config['logfile'], $config['loglevel']);
// --- Twig Data Array --- // --- Twig Data Array ---
$data = []; $data = [];
$data['fonts'] = $config['fonts'] ?? []; $data['fonts'] = $config['fonts'] ?? [];
$data['matomo'] = $config['matomo'] ?? 0;
// --- Session --- // --- Session ---
use Novaconium\Session; use Novaconium\Session;

View File

@@ -0,0 +1,71 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ title | default('Coming Soon') }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="/css/novaconium.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
body {
background: url("{{ bg_image | default('https://w.wallhaven.cc/full/5y/wallhaven-5yymk9.jpg') }}") no-repeat center center fixed;
background-size: cover;
}
</style>
</head>
<body id="coming-soon">
<div class="container">
<h1>{{ heading | default('Coming Soon') }}</h1>
{% block content %}{% endblock %}
{% if countdown %}
<div class="countdown" id="countdown"></div>
{% endif %}
{# TODO: listmonk #}
<form class="newsletter" action="#" method="post">
<label for="email">Subscribe to our newsletter:</label>
<input type="email" id="email" name="email" placeholder="Your email address" required>
<button type="submit">Subscribe</button>
</form>
{# Social media icons using Font Awesome #}
<div class="social-icons">
{% block social %}{% endblock %}
</div>
</div>
{% if countdown %}
<script>
{% if countdown %}
{% set default_launch = "now"|date_modify("+30 days")|date("Y-m-d\TH:i:s") %}
const launchDate = new Date('{{ launch_date | default(default_launch) }}').getTime();
const countdownEl = document.getElementById('countdown');
function updateCountdown() {
const now = new Date().getTime();
const distance = launchDate - now;
if (distance <= 0) {
countdownEl.innerText = 'Launched!';
return;
}
const days = Math.floor(distance / (1000*60*60*24));
const hours = Math.floor((distance % (1000*60*60*24)) / (1000*60*60));
const mins = Math.floor((distance % (1000*60*60)) / (1000*60));
const secs = Math.floor((distance % (1000*60)) / 1000);
countdownEl.innerText = `${days}d ${hours}h ${mins}m ${secs}s`;
}
updateCountdown();
setInterval(updateCountdown, 1000);
{% endif %}
</script>
{% endif %}
</body>
</html>

View File

@@ -2,7 +2,7 @@
<html class="no-js" lang="en"> <html class="no-js" lang="en">
<head> <head>
{% include ['@override/head.html.twig', '@novaconium/head.html.twig'] %} {% include ['@novaconium/cp/head.html.twig'] %}
</head> </head>
<body id="{{ pageid | default('pageid') }}" class="{{ pageclass | default('pageclass') }}" > <body id="{{ pageid | default('pageid') }}" class="{{ pageclass | default('pageclass') }}" >
@@ -28,8 +28,6 @@
<div class="copyright">&copy; {{ 'now' | date('Y') }} Novaconium</div> <div class="copyright">&copy; {{ 'now' | date('Y') }} Novaconium</div>
</footer> </footer>
{% include '@novaconium/javascript/page-edit.html.twig' %}
{% if editor == 'ace' %} {% if editor == 'ace' %}
{% include '@novaconium/javascript/ace.html.twig' %} {% include '@novaconium/javascript/ace.html.twig' %}
{% endif %} {% endif %}

60
twig/cp/head.html.twig Normal file
View File

@@ -0,0 +1,60 @@
{# =============================================================================
<HEAD>
=============================================================================
#}
<meta charset="utf-8">
<title>{{ title | default('Welcome To Novaconium') }}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
{# SEO & METADATA #}
<meta name="generator" content="Novaconium" />
<meta name="description" content="{{ description | default('No description given') }}">
<meta name="keywords" content="{{ keywords | default('website') }}">
<meta name="author" content="{{ author | default('anonymous') }}">
{# DARK MODE & THEME HINTS #}
<meta name="color-scheme" content="dark">
<meta name="theme-color" content="#000000">
{# OPEN GRAPH (OG) FOR SOCIAL SHARING #}
<meta property="og:title" content="{{ title | default('Welcome') }}">
<meta property="og:type" content="website">
<meta property="og:url" content="{{ app_url | default(request.scheme ~ '://' ~ request.host) }}">
<meta property="og:image" content="{{ og_image | default('/icon.png') }}">
{# PWA & FAVICONS #}
<link rel="manifest" href="site.webmanifest">
<link rel="apple-touch-icon" href="/icon.png">
<link rel="icon" type="image/x-icon" href="/favicon.ico">
{# GOOGLE FONTS (CDN VIA PRECONNECT) #}
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="{{ fonts | default('https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&family=Roboto+Mono&family=Source+Code+Pro&family=Lato&family=Poppins&family=Material+Icons&family=Material+Icons+Outlined&family=VT323:wght@400&family=Fira+Code:wght@400;500&display=swap') }}"
rel="stylesheet"
>
{% if editor == 'ace' %}
<!-- ACE Editor -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/ace.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/ace.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/mode-html.min.js"></script> {# HTML syntax #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/theme-tomorrow_night.min.js"></script> {# Dark theme #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/ext-language_tools.min.js"></script> {# Autocomplete #}
<!-- END ACE Editor -->
{% endif %}
{# highlight.js #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/ir-black.min.css">
<script src="/js/tabs.js"></script>
{# STYLESHEET #}
<link rel="stylesheet" href="/css/novaconium.css">

View File

@@ -9,3 +9,20 @@
{% if editor == 'ace' %} {% if editor == 'ace' %}
{% include '@novaconium/javascript/ace.html.twig' %} {% include '@novaconium/javascript/ace.html.twig' %}
{% endif %} {% endif %}
{% if matomo > 0 %}
<!-- Matomo -->
<script>
var _paq = window._paq = window._paq || [];
_paq.push(['trackPageView']);
_paq.push(['enableLinkTracking']);
(function() {
var u = "//matomo.4lt.ca/";
_paq.push(['setTrackerUrl', u + 'matomo.php']);
_paq.push(['setSiteId', {{ matomo }}]);
var d = document, g = d.createElement('script'), s = d.getElementsByTagName('script')[0];
g.async = true; g.src = u + 'matomo.js'; s.parentNode.insertBefore(g, s);
})();
</script>
<!-- End Matomo Code -->
{% endif %}

View File

@@ -39,22 +39,7 @@
> >
{# STYLESHEET #} {# STYLESHEET #}
{% if pageclass == "novaconium" %} <link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="/css/novaconium.css">
{% else %}
<link rel="stylesheet" href="/css/main.css">
{% endif %}
{% if editor == 'ace' %}
<!-- ACE Editor -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/ace.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/ace.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/mode-html.min.js"></script> {# HTML syntax #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/theme-tomorrow_night.min.js"></script> {# Dark theme #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.35.2/ext-language_tools.min.js"></script> {# Autocomplete #}
<!-- END ACE Editor -->
{% endif %}
{# highlight.js #} {# highlight.js #}
<script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>

View File

@@ -0,0 +1,32 @@
{% extends '@novaconium/coming-soon/index.html.twig' %}
{% set bg_image = "https://i.4lt.ca/4lt/waterBubbles.webp" %}
{% set default_launch = "now"|date_modify("+30 days")|date("Y-m-d\TH:i:s") %}
{% block content %}
<p>Our website is under construction. Were working hard to bring you a better experience.</p>
<p>Stay tuned for updates!</p>
{% endblock %}
{% block social %}
<a href="mailto:you@example.com" title="Email">
<i class="fa-solid fa-envelope"></i>
</a>
<a href="tel:+1234567890" title="Phone">
<i class="fa-solid fa-phone"></i>
</a>
<a href="#" title="Twitter">
<i class="fab fa-twitter"></i>
</a>
<a href="#" title="Facebook">
<i class="fab fa-facebook-f"></i>
</a>
<a href="#" title="Instagram">
<i class="fab fa-instagram"></i>
</a>
{% endblock %}