homepage stack
$skillLinks = [];
try {
$skillLinks = pdo()->query("SELECT framework_id, language_id FROM skill_links")->fetchAll(PDO::FETCH_ASSOC);
} catch (Throwable $e) {}
$rows = pdo()->query("SELECT id, label, level, icon, category, parent_id FROM skills ORDER BY sort_order ASC, id ASC")->fetchAll();
if ($rows && is_array($rows)) {
$languages = [];
$frameworks = [];
$frameworkLanguageMap = [];
foreach ($skillLinks as $lnk) {
$fw = (int)($lnk['framework_id'] ?? 0);
$lang = (int)($lnk['language_id'] ?? 0);
if ($fw > 0 && $lang > 0) {
if (!isset($frameworkLanguageMap[$fw])) $frameworkLanguageMap[$fw] = [];
$frameworkLanguageMap[$fw][$lang] = $lang;
}
}
foreach ($rows as $r) {
$cat = strtolower((string)($r['category'] ?? 'language'));
$item = [
'id' => (int)($r['id'] ?? 0),
'label' => (string)($r['label'] ?? ''),
'level' => (int)($r['level'] ?? 0),
'icon' => (string)($r['icon'] ?? 'ri-code-s-slash-line'),
'parent_id' => (int)($r['parent_id'] ?? 0),
];
if ($cat === 'framework') {
$frameworks[(int)$item['id']] = $item;
} else {
$item['frameworks'] = [];
$languageLabels[(int)$item['id']] = $item['label'];
$languages[(int)$item['id']] = $item;
}
}
// attach frameworks to languages via pivot map (fallback to legacy parent_id)
foreach ($frameworks as $fwId => $fw) {
$langIds = array_values($frameworkLanguageMap[$fwId] ?? []);
if (!$langIds && $fw['parent_id'] > 0) $langIds = [$fw['parent_id']];
$frameworks[$fwId]['language_ids'] = $langIds;
$frameworks[$fwId]['language_labels'] = [];
foreach ($langIds as $lid) {
if (isset($languageLabels[$lid])) {
$frameworks[$fwId]['language_labels'][] = $languageLabels[$lid];
$fwItem = $fw;
$fwItem['parent_id'] = $lid;
$languages[$lid]['frameworks'][] = $fwItem;
}
}
}
if ($languages) {
foreach ($languages as $id => $lang) {
$lang['frameworks'] = array_values($lang['frameworks'] ?? []);
$stack[] = $lang;
}
}
$frameworks = array_values($frameworks);
}
// projects table -> homepage projects
$rows = [];
try {
$rows = pdo()->query("SELECT id, slug, title, tag, year, summary, short_summary, tech_json, links_json FROM projects ORDER BY sort_order ASC, id DESC")->fetchAll();
} catch (Throwable $e) {
$rows = pdo()->query("SELECT id, slug, title, tag, year, summary, tech_json, links_json FROM projects ORDER BY sort_order ASC, id DESC")->fetchAll();
if (is_array($rows)) {
foreach ($rows as &$r) { $r['short_summary'] = null; }
unset($r);
}
}
if ($rows && is_array($rows)) {
$tmp = [];
$tagSet = [];
foreach ($rows as $r) {
$tech = [];
$links = [];
$slugVal = project_slugify((string)($r['slug'] ?? ''));
if ($slugVal === '') {
$slugVal = project_slugify((string)($r['title'] ?? '')) ?: ('p' . (int)$r['id']);
}
$techJson = (string)($r['tech_json'] ?? '');
$linksJson = (string)($r['links_json'] ?? '');
if ($techJson !== '') {
$decoded = json_decode($techJson, true);
if (is_array($decoded)) $tech = $decoded;
}
if ($linksJson !== '') {
$decoded = json_decode($linksJson, true);
if (is_array($decoded)) $links = $decoded;
}
$projectForMedia = [
'id' => (int)($r['id'] ?? 0),
'slug' => $slugVal,
'title' => (string)($r['title'] ?? ''),
];
$shortCard = trim((string)($r['short_summary'] ?? ''));
if ($shortCard === '') {
$shortCard = project_excerpt((string)($r['summary'] ?? ''), 180);
}
$tmp[] = [
'id' => (string)$slugVal,
'title' => (string)($r['title'] ?? ''),
'tag' => (string)($r['tag'] ?? ''),
'year' => (string)($r['year'] ?? ''),
'summary' => (string)($r['summary'] ?? ''),
'summary_short' => $shortCard,
'tech' => is_array($tech) ? $tech : [],
'links' => is_array($links) ? $links : [],
'images' => project_media_files($projectForMedia),
];
$tag = trim((string)($r['tag'] ?? ''));
if ($tag !== '') $tagSet[$tag] = true;
}
if ($tmp) $projects = $tmp;
if ($tagSet) $projectTags = array_keys($tagSet);
}
}
} catch (Throwable $e) {
// keep fallback arrays
}
$profile = [
'name' => 'Georgi Mushatov',
'role' => 'Full Stack Developer & Software Engineer',
'location' => 'Varna,BG',
'github' => 'https://github.com/AJOffishal',
'instagram' => 'https://instagram.com/1_3_aj_official_3_7/',
'tiktok' => 'https://tiktok.com/@ajbtgd',
];
$projectsJson = json_encode($projects, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
$initial = function_exists('mb_substr') ? mb_substr($profile['name'], 0, 1) : substr($profile['name'], 0, 1);
$pfpUrl = url_path('/img/' . rawurlencode('ajpfp.png'));
?>
= htmlspecialchars($profile['name']) ?> • Portfolio
= htmlspecialchars($profile['location']) ?>.
Video Games & Websites.
Discord Bots using discord.js.
Tools & launchers.
Focus
Full Stack
Lua • PHP • AJAX • jQuery • MariaDB • C# • C++
Build fast → harden security → ship clean UI.
Workflow
Git + Gitea
Clean commits, tags
Stable releases + readable history.
About Me
= htmlspecialchars($profile['location']) ?>
I’m Georgi Mushatov, a 15-year-old high schooler from Varna, Bulgaria.
I’m into video games and building websites (front-end + back-end). I like making
community sites, dashboards and tools that connect real data using APIs.
My focus is clean UI and solid functionality - making things work smoothly end-to-end.
Video Games
APIs
Automation
Quick facts
Fast prototyping → clean refactor
Secure auth + CSRF patterns
Git workflow daily
Project Library
Click a card for details.
All
= htmlspecialchars((string)$tag) ?>
= htmlspecialchars((string)$p['year']) ?>
= htmlspecialchars((string)$p['tag']) ?>
= htmlspecialchars((string)$p['title']) ?>
= htmlspecialchars($cardSummary) ?>
= htmlspecialchars((string)$t) ?>
Tech Stack
= htmlspecialchars((string)$lang['label']) ?>
= (int)$lang['level'] ?>%
Frameworks / Librarys / Game Engines
= htmlspecialchars((string)$fw['label']) ?>
No frameworks added yet.
No skills added yet.
Frameworks / Librarys / Game Engines
= htmlspecialchars((string)$fw['label']) ?>
Languages: = htmlspecialchars($langLine) ?>
= (int)($fw['level'] ?? 0) ?>%
No frameworks added yet.
Gaming + Web Focus
Landing pages, team/clean sites, game community hubs - fast, clean and easy to use.
Simple dashboards for data, versions, stats and pages that keep things organized.
PHP + SQL + AJAX/jQuery to connect APIs and build real functionality behind the UI.
© = date('Y') ?> = htmlspecialchars($profile['name']) ?> • Built with PHP • Tailwind • Bootstrap • AJAX • jQuery