Min Side Expert Context
Use this skill when working on
/min-side/routes, user authentication, access control, or member portal features in BIM Verdi.
1. Architecture Overview
Router System
Min Side uses a single router template that maps URL paths to part files:
template-minside-router.php
↓
inc/minside-helpers.php (route definitions)
↓
parts/minside/{part-file}.php
Key files:
template-minside-router.php- Main router templateinc/minside-helpers.php- Route definitions + helper functionsheader-minside.php- Authenticated headerparts/minside/*.php- Individual view templates
Adding a New Route
- Add route to
bimverdi_get_minside_routes()ininc/minside-helpers.php:
'my-route' => 'my-route', // Simple route
'parent/child' => 'parent-child', // Nested route
-
Create template file:
parts/minside/{part-file}.php -
Optionally add to navigation in
bimverdi_get_minside_nav()
2. Complete Route Map
Active Routes (17+)
| URL Path | Part File | Description |
|---|---|---|
/min-side/ | dashboard.php | Main dashboard |
/min-side/profil/ | profil.php | View profile |
/min-side/profil/rediger/ | profil-rediger.php | Edit profile |
/min-side/profil/passord/ | profil-passord.php | Change password |
/min-side/foretak/ | foretak-detail.php | View company |
/min-side/foretak/rediger/ | foretak-rediger.php | Edit company (hovedkontakt only) |
/min-side/verktoy/ | verktoy-list.php | List tools |
/min-side/verktoy/registrer/ | verktoy-registrer.php | Register new tool |
/min-side/verktoy/rediger/ | verktoy-rediger.php | Edit tool (?id=X) |
/min-side/kunnskapskilder/ | kunnskapskilder-list.php | List knowledge sources |
/min-side/kunnskapskilder/registrer/ | kunnskapskilder-registrer.php | Register knowledge source |
/min-side/kunnskapskilder/rediger/ | kunnskapskilder-rediger.php | Edit knowledge source |
/min-side/artikler/ | artikler-list.php | List articles |
/min-side/artikler/skriv/ | artikler-skriv.php | Write new article |
/min-side/arrangementer/ | arrangementer-list.php | Events list |
/min-side/prosjektideer/ | prosjektideer-list.php | Project ideas list |
/min-side/invitasjoner/ | invitasjoner-list.php | Invite colleagues (hovedkontakt only) |
Legacy Route Aliases
These redirect to new routes for backward compatibility:
/min-side/mine-verktoy/→ verktoy-list/min-side/registrer-verktoy/→ verktoy-registrer/min-side/rediger-verktoy/→ verktoy-rediger/min-side/rediger-foretak/→ foretak-rediger/min-side/rediger-profil/→ profil-rediger/min-side/endre-passord/→ profil-passord/min-side/skriv-artikkel/→ artikler-skriv
3. User Roles & Access Control
Account Types
| Type | Definition | Access Level |
|---|---|---|
profil | User without company | Limited - can browse, attend events |
foretak | User linked to company | Full - can create content |
guest | Not logged in | No Min Side access |
WordPress Roles
| Role | Description | Has Company |
|---|---|---|
medlem | Free member | Optional |
tilleggskontakt | Invited by hovedkontakt | Yes (required) |
deltaker | Paying member (standard) | Yes (required) |
prosjektdeltaker | Paying member (mid-tier) | Yes (required) |
partner | Paying member (top tier) | Yes (required) |
Important: deltaker, prosjektdeltaker, and partner have IDENTICAL capabilities. The difference is business/pricing only.
Hovedkontakt vs Tilleggskontakt
| Capability | Tilleggskontakt | Hovedkontakt |
|---|---|---|
| Create tools | Yes | Yes |
| Write articles | Yes | Yes |
| Register knowledge sources | Yes | Yes |
| Submit project ideas | Yes | Yes |
| Edit own content | Yes | Yes |
| Delete content | No (admin) | No (admin) |
| Edit company profile | No | Yes |
| View team members | Yes | Yes |
| Remove team members | No | Yes |
| Transfer hovedkontakt | No | Yes |
| Invite colleagues | No | Yes |
Feature Access Control
Requires Company (foretak account type):
const COMPANY_REQUIRED_FEATURES = [
'register_tool', // Registrere verktøy
'edit_tool', // Redigere verktøy
'write_article', // Skrive artikler
'submit_case', // Sende inn prosjektidéer
'join_temagruppe', // Velge temagrupper
'company_profile', // Redigere foretaksprofil
'view_members_full', // Se fullt medlemsinnhold
];
Open to All Logged-In Users:
const OPEN_FEATURES = [
'view_dashboard', // Se Min Side dashboard
'edit_profile', // Redigere egen profil
'view_catalog', // Se medlemskatalog
'view_tools', // Se verktøykatalog
'register_event', // Melde seg på arrangementer
'view_events', // Se arrangementer
'connect_company', // Koble til foretak
];
4. Helper Functions
URL Helpers
// Get Min Side base URL
bimverdi_minside_base_url(); // Returns: https://site.com/min-side
// Generate Min Side URL
bimverdi_minside_url('verktoy'); // /min-side/verktoy/
bimverdi_minside_url('verktoy/rediger', ['id' => 123]); // /min-side/verktoy/rediger/?id=123
// Get current route
bimverdi_get_current_route(); // Returns: 'verktoy/rediger'
// Check if on specific route
bimverdi_is_minside_route('verktoy'); // true for /verktoy/ and /verktoy/rediger/
bimverdi_is_minside_route(['profil', 'foretak']); // Multiple routes
// Get primary route segment
bimverdi_get_primary_route(); // 'verktoy' from 'verktoy/rediger'
Company & User Helpers
// Check if user has company
bimverdi_user_has_company($user_id); // Returns: bool
// Get user's company ID
bimverdi_get_user_company($user_id); // Returns: int|false
// Check if user is hovedkontakt
bimverdi_is_hovedkontakt($user_id, $company_id); // Returns: bool
// Check if company is active/approved
bimverdi_is_company_active($company_id); // Returns: bool
// Get account type
bimverdi_get_account_type($user_id); // Returns: 'profil', 'foretak', or 'guest'
Access Control Helpers
// Check feature access
bimverdi_can_access('register_tool'); // Returns: bool
// Render locked feature UI
BIMVerdi_Access_Control::render_locked_ui('register_tool', 'Custom message');
// Render locked card component
bimverdi_locked_card('Title', 'Description', 'icon-name', 'feature');
// Render "connect to company" CTA
bimverdi_connect_company_cta();
Navigation Helper
// Get navigation structure
$nav = bimverdi_get_minside_nav();
// Returns array with: label, url, icon, badge, routes
5. Company ID Storage (Legacy Migration)
User's company is stored in user_meta. Check these keys in order:
bimverdi_company_id(new standard)bim_verdi_company_id(legacy)- ACF field
tilknyttet_foretak(fallback)
Always use the helper function bimverdi_get_user_company() which handles all three.
6. ACF Field Reference
Foretak (Company) - CPT: foretak
get_field('hovedkontaktperson', $company_id); // User ID of primary contact
get_field('er_aktiv_deltaker', $company_id); // bool - is active member
get_field('organisasjonsnummer', $company_id); // Norwegian org number
get_field('bedriftsnavn', $company_id); // Company name (or post_title)
get_field('beskrivelse', $company_id); // Company description
get_field('logo', $company_id); // Attachment ID
get_field('adresse', $company_id); // Street address
get_field('postnummer', $company_id); // Postal code
get_field('poststed', $company_id); // City
get_field('land', $company_id); // Country
get_field('telefon', $company_id); // Phone
get_field('epost', $company_id); // Email
get_field('nettside', $company_id); // Website URL
Verktøy (Tool) - CPT: verktoy
get_field('tilknyttet_foretak', $tool_id); // Company ID that owns the tool
get_field('eier_leverandor', $tool_id); // Owner/vendor company
get_field('logo', $tool_id); // Tool logo
get_field('vendor', $tool_id); // Vendor name
get_field('type_verktoey', $tool_id); // Tool type
get_field('plattform', $tool_id); // Platform(s)
Kunnskapskilde (Knowledge Source) - CPT: kunnskapskilde
get_field('registrert_av', $kilde_id); // User ID who registered
get_field('tilknyttet_bedrift', $kilde_id); // Company ID
get_field('kunnskapskilde_navn', $kilde_id); // Name
get_field('kildetype', $kilde_id); // Type (standard, veileder, etc.)
get_field('utgiver', $kilde_id); // Publisher
get_field('ekstern_lenke', $kilde_id); // External URL
get_field('kort_beskrivelse', $kilde_id); // Short description
Arrangement (Event) - CPT: arrangement
get_field('arrangement_dato', $event_id); // Date
get_field('tidspunkt_start', $event_id); // Start time
get_field('tidspunkt_slutt', $event_id); // End time
get_field('arrangement_type', $event_id); // Type (digitalt, fysisk, hybrid)
get_field('sted_by', $event_id); // City
get_field('sted_adresse', $event_id); // Address
get_field('pamelding_url', $event_id); // Registration URL
get_field('maks_deltakere', $event_id); // Max participants
Prosjektidé (Project Idea) - CPT: case
get_field('temagruppe', $idea_id); // Related theme group
User Fields
get_field('tilknyttet_foretak', 'user_' . $user_id); // Company ID
7. CPT Constants
Defined in bim-verdi-core/includes/class-content-types.php:
BV_CPT_COMPANY = 'foretak' // Member companies
BV_CPT_TOOL = 'verktoy' // Software tools
BV_CPT_EVENT = 'arrangement' // Events/meetings
BV_CPT_REGISTRATION = 'pamelding' // Event registrations
BV_CPT_IDEA = 'case' // Project ideas (private)
BV_CPT_PROJECT = 'prosjekt' // Pilot projects
BV_CPT_THEME_GROUP = 'theme_group' // Temagrupper
BV_CPT_ARTICLE = 'artikkel' // Member articles
8. Gravity Forms
Form IDs
- Form 10: Email signup (Step 1) - Email verification flow
- Form 11: Account activation (Step 2) - Name + password
Form Handlers
Located in mu-plugins/bimverdi-email-verification.php and bimverdi-gforms-setup.php.
Usage in Templates
Forms are embedded via PHP or shortcode in registration flows, not typically in Min Side views.
9. Design System Rules
Always follow claude/UI-CONTRACT.md when building Min Side templates.
Key Principles
- P1: Whitespace + dividers as primary structure (no "boxes everywhere")
- P2: Clickability must be explicit (only buttons/links are interactive)
- P3: Information ≠ handling (info in borderless sections, actions in buttons)
- P4: Show only what exists (hide empty fields)
- P5: Rolig, consistent enterprise style (minimal visual noise)
Layout Widths
- Standard content:
max-width: 1200-1280px - Form pages:
max-width: 960px - Spacing scale: 8px increments
Color Palette
Text Primary: #1A1A1A text-[#1A1A1A]
Text Secondary: #5A5A5A text-[#5A5A5A]
Dividers: #D6D1C6 border-[#D6D1C6]
Background: #F7F5EF bg-[#F7F5EF]
CTA/Orange: #FF8B5E bg-[#FF8B5E]
Button Component
Use bimverdi_button() from parts/components/button.php:
bimverdi_button([
'text' => 'Lagre',
'variant' => 'primary', // primary, secondary, tertiary, danger
'size' => 'medium', // small, medium, large
'icon' => 'save', // Lucide icon name
'href' => '/url', // Makes it a link
]);
Icons
Use Lucide icons (https://lucide.dev):
layout-dashboard- Dashboardwrench- Toolsfile-text- Articleslightbulb- Ideascalendar- Eventsbuilding-2- Companyuser-plus- Invitationschevron-right- Navigate
10. Temagrupper (Theme Groups)
Important: Temagrupper are linked to foretak (companies), NOT individual users.
- All users linked to a foretak can view the company's temagrupper
- Only hovedkontakt can change temagruppe memberships
- Temagruppe selection is a company-level setting
11. Common Patterns
Access Check in Template
<?php
// At top of template part
$user_id = get_current_user_id();
$company_id = bimverdi_get_user_company($user_id);
// Require company
if (!$company_id) {
bimverdi_connect_company_cta();
return;
}
// Require hovedkontakt
if (!bimverdi_is_hovedkontakt($user_id, $company_id)) {
wp_redirect(bimverdi_minside_url('foretak'));
exit;
}
?>
Page Header Component
get_template_part('parts/components/page-header', null, [
'title' => 'Page Title',
'description' => 'Optional subtitle text',
'icon' => 'wrench', // Lucide icon
'actions' => [
[
'text' => 'Primary Action',
'href' => '/url',
'variant' => 'primary',
'icon' => 'plus',
],
],
]);
Breadcrumb Navigation
<nav class="text-sm mb-6" aria-label="Brødsmulesti">
<ol class="flex items-center gap-2 text-[#5A5A5A]">
<li><a href="<?php echo bimverdi_minside_url(); ?>" class="hover:text-[#1A1A1A]">Min side</a></li>
<li><span class="text-[#D6D1C6]">/</span></li>
<li><a href="<?php echo bimverdi_minside_url('parent'); ?>" class="hover:text-[#1A1A1A]">Parent</a></li>
<li><span class="text-[#D6D1C6]">/</span></li>
<li class="text-[#1A1A1A] font-medium">Current Page</li>
</ol>
</nav>
Data Table Pattern
<div class="overflow-x-auto">
<table class="w-full">
<thead>
<tr class="border-b border-[#D6D1C6]">
<th class="text-left py-3 px-4 text-xs font-medium text-[#5A5A5A] uppercase tracking-wide">Column</th>
</tr>
</thead>
<tbody class="divide-y divide-[#E5E2DB]">
<tr class="hover:bg-[#F7F5EF]/50">
<td class="py-4 px-4">Content</td>
</tr>
</tbody>
</table>
</div>
12. Debug Mode
Add ?debug_router=1 to any Min Side URL (admin only) to see:
- Request URI
- Current Route
- Part File
- Query Var
13. Files Quick Reference
| Purpose | File Path |
|---|---|
| Router template | template-minside-router.php |
| Route definitions | inc/minside-helpers.php |
| Access control | mu-plugins/bimverdi-access-control.php |
| Role definitions | mu-plugins/bimverdi-custom-roles.php |
| Authenticated header | header-minside.php |
| View templates | parts/minside/*.php |
| Button component | parts/components/button.php |
| Page header | parts/components/page-header.php |
| Design rules | claude/UI-CONTRACT.md |