Frontend: Publika sidor
🌐hittadittsverige.se
Nationell startsida. Kommunkort, karta, exploration entry points.
Static HTML
🏛pitea.hittadittsverige.se
Kommunportal. Branding via _applyCommuneBranding(). loadCommune() API-call vid init.
HTML+JSAPI
📄commune-subpage.html
Generisk mall för alla 8 undersidor. Läser page_slug från URL. Renderar blocks från API.
Templateblocks.php
📝artiklar/ · artikel/
Kommunartikellistning med kategorifilter. Detaljsida med breadcrumb och body HTML.
editorial/list.php
❓hjalp/ · hjalp/artikel/
Kunskapsbas med sökning, kategorigrid och artikelrendering. Feedback i localStorage.
articles.json
Backend: API-lager
🔐_helpers.php
hds_require_auth(), hds_require_entity_access(), hds_audit(), hds_db(), hds_ok/err(). Kärna för all API-logik.
Auth corePDO
🏛commune/settings.php
GET/PATCH kommunens varumärke, navigation, kontakt. Cached via APCu.
GET PATCH
📦commune/blocks.php
CRUD för page_blocks. page_slug param. 10 blocktyper validerade.
GET POST PATCH DELETE
👥commune/users.php
GET team, PATCH roll (inkl. village_admin + village_id), DELETE user. Joins village_admins.
GET PATCH DELETE
📝editorial/ (save, list, delete)
CRUD artiklar. Non-admin scoped till hds_managed_komkod. Kategorifilter i list.php.
POST GET DELETE
📷upload/ (commune-image, entity)
Magic-byte validering, GD resize 2000px, max 20 per kommun. Public GET utan auth.
POST GET DELETE
🏠village/details.php
Byprofil: GET sammanfogar villages.json + village_overrides. PATCH upserts overrides.
GET PATCHvillage_overrides
📋commune/audit-log.php
Returnerar senaste 50 loggposter för alla konton kopplade till kommunen.
GETaudit_log
Dashboard och data
🔧dashboard/index.html
SPA-liknande dashboard. ROLE_CONFIG mappar roller till flikar. Alla administrativa funktioner.
~2500 rader JS
📊ROLE_CONFIG objekt
admin, commune_coordinator, tourism_board, rural_dev, field_agent, village_admin, forening, business, member_local
9 roller
🗃data/entities.json
510+ entiteter. Statisk fil, läses direkt av frontend. Källa för entity_commune-tabell.
JSON statisk
🏠data/villages.json
Byar med namn, koordinater, taxonomy. Bas för village/details.php.
JSON statisk
🗺data/ routes (GPX, JSON)
Cykelleder, vandringsleder, semesterrutter. Visas på karta och i rutter-katalogen.
GPX + JSON
⚡APCu in-process cache
browse/catalog.php och commune/settings.php cachar i PHP-process. TTL 5 min.
In-memory
Viktiga dataflöden
Browser
→
pitea.hittadittsverige.se
→
loadCommune()
→
commune/settings.php
→
MySQL communes
Branding load (APCu cached 5min)
commune-subpage.html
→
commune/blocks.php?page_slug=X
→
commune_page_blocks
→
renderBlock(type, data)
Block rendering per page slug
Dashboard (coordinator)
→
commune/invite.php
→
accounts INSERT
→
_mailer.php → SMTP
Team invitation flow
Fältagent (app)
→
entities/update.php
→
hds_require_entity_access()
→
entity_commune lookup
Access grant: field_agent via entity_commune table
village_admin
→
hds_entity_id = village_id
→
entity.village == hds_entity_id
Village admin scoping via session entity_id field
Databastabeller: kommunvertikalen
accounts
- id (PK)
- display_name
- email
- role (ENUM)
- managed_komkod
- entity_id (village_id)
- active TINYINT
commune_settings
- commune_id (PK)
- display_name
- tagline
- accent_color
- logo_url
- banner_url
- hidden_sections JSON
commune_page_blocks
- id (PK)
- commune_id
- page_slug
- type (ENUM 10)
- sort_order INT
- data JSON
editorial_posts
- id (PK)
- slug (UNIQUE)
- commune_id (nullable)
- category
- status ENUM
- featured TINYINT
- publish_at DATETIME
entity_commune
- entity_id (PK)
- commune_id
- /* 510 rows from entities.json */
village_admins
- id (PK)
- account_id
- village_id
- created_at
- UNIQUE(account, village)
village_overrides
- id (village_id PK)
- tagline
- description TEXT
- image_url
- updated_at
audit_log
- id (PK)
- account_id
- action VARCHAR
- entity_id
- ip_hash
- created_at
entity_blocks
- id (PK)
- entity_id
- type ENUM
- sort_order INT
- data JSON
- created_at
entity_branding
- entity_id (PK)
- accent_color
- heading_color
- logo_url
- updated_at
contact_messages
- id (PK)
- entity_id
- sender_name
- sender_email
- message TEXT
- read_at DATETIME
- created_at
entity_seo_meta
- entity_id (PK)
- seo_title
- meta_description
- slug UNIQUE
- updated_at
gallery_albums
- id (PK)
- entity_id
- name
- cover_image_url
- sort_order INT
- created_at
Frontend: Public Pages
🌐hittadittsverige.se
National homepage. Municipality cards, map, exploration entry points.
Static HTML
🏛pitea.hittadittsverige.se
Municipality portal. Branding via _applyCommuneBranding(). loadCommune() API call on init.
HTML+JSAPI
📄commune-subpage.html
Generic template for all 8 sub-pages. Reads page_slug from URL. Renders blocks from API.
Templateblocks.php
📝artiklar/ · artikel/
Municipality article listing with category filter. Detail page with breadcrumb and body HTML.
editorial/list.php
❓hjalp/ · hjalp/artikel/
Knowledge base with search, category grid, and article rendering. Feedback in localStorage.
articles.json
Backend: API Layer
🔐_helpers.php
hds_require_auth(), hds_require_entity_access(), hds_audit(), hds_db(), hds_ok/err(). Core for all API logic.
Auth corePDO
🏛commune/settings.php
GET/PATCH municipality brand, navigation, contact. Cached via APCu.
GET PATCH
📦commune/blocks.php
CRUD for page_blocks. page_slug param. 10 block types validated.
GET POST PATCH DELETE
👥commune/users.php
GET team, PATCH role (incl. village_admin + village_id), DELETE user. Joins village_admins.
GET PATCH DELETE
📝editorial/ (save, list, delete)
CRUD articles. Non-admin scoped to hds_managed_komkod. Category filter in list.php.
POST GET DELETE
📷upload/ (commune-image, entity)
Magic-byte validation, GD resize 2000px, max 20 per municipality. Public GET without auth.
POST GET DELETE
🏠village/details.php
Village profile: GET merges villages.json + village_overrides. PATCH upserts overrides.
GET PATCHvillage_overrides
📋commune/audit-log.php
Returns the last 50 log entries for all accounts linked to the municipality.
GETaudit_log
Dashboard and Data
🔧dashboard/index.html
SPA-style dashboard. ROLE_CONFIG maps roles to tabs. All administrative functions.
~2500 lines JS
📊ROLE_CONFIG object
admin, commune_coordinator, tourism_board, rural_dev, field_agent, village_admin, forening, business, member_local
9 roles
🗃data/entities.json
510+ entities. Static file, read directly by frontend. Source for entity_commune table.
JSON static
🏠data/villages.json
Villages with name, coordinates, taxonomy. Base for village/details.php.
JSON static
🗺data/ routes (GPX, JSON)
Cycling trails, hiking routes, holiday routes. Shown on map and in routes catalogue.
GPX + JSON
⚡APCu in-process cache
browse/catalog.php and commune/settings.php cache in PHP process. TTL 5 min.
In-memory
Key Data Flows
Browser
→
pitea.hittadittsverige.se
→
loadCommune()
→
commune/settings.php
→
MySQL communes
Branding load (APCu cached 5min)
commune-subpage.html
→
commune/blocks.php?page_slug=X
→
commune_page_blocks
→
renderBlock(type, data)
Block rendering per page slug
Dashboard (coordinator)
→
commune/invite.php
→
accounts INSERT
→
_mailer.php → SMTP
Team invitation flow
Field Agent (app)
→
entities/update.php
→
hds_require_entity_access()
→
entity_commune lookup
Access grant: field_agent via entity_commune table
village_admin
→
hds_entity_id = village_id
→
entity.village == hds_entity_id
Village admin scoping via session entity_id field
Database Tables: the municipal vertical
accounts
- id (PK)
- display_name
- email
- role (ENUM)
- managed_komkod
- entity_id (village_id)
- active TINYINT
commune_settings
- commune_id (PK)
- display_name
- tagline
- accent_color
- logo_url
- banner_url
- hidden_sections JSON
commune_page_blocks
- id (PK)
- commune_id
- page_slug
- type (ENUM 10)
- sort_order INT
- data JSON
editorial_posts
- id (PK)
- slug (UNIQUE)
- commune_id (nullable)
- category
- status ENUM
- featured TINYINT
- publish_at DATETIME
entity_commune
- entity_id (PK)
- commune_id
- /* 510 rows from entities.json */
village_admins
- id (PK)
- account_id
- village_id
- created_at
- UNIQUE(account, village)
village_overrides
- id (village_id PK)
- tagline
- description TEXT
- image_url
- updated_at
audit_log
- id (PK)
- account_id
- action VARCHAR
- entity_id
- ip_hash
- created_at
entity_blocks
- id (PK)
- entity_id
- type ENUM
- sort_order INT
- data JSON
- created_at
entity_branding
- entity_id (PK)
- accent_color
- heading_color
- logo_url
- updated_at
contact_messages
- id (PK)
- entity_id
- sender_name
- sender_email
- message TEXT
- read_at DATETIME
- created_at
entity_seo_meta
- entity_id (PK)
- seo_title
- meta_description
- slug UNIQUE
- updated_at
gallery_albums
- id (PK)
- entity_id
- name
- cover_image_url
- sort_order INT
- created_at