Skip to content

02 — Someli-Designer stack

Looks like someli-platform. Is much thinner. Knowing the differences saves you from copy-pasting bad assumptions.


At a glance

Concern Choice Version
Framework Nuxt 2 2.18.1 (CLI), 2.15.8 (core)
View library Vue 2 2.7.16
Mode SPA — ssr: false
State Vuex 3 (single store/index.js, no sub-modules)
HTTP @nuxtjs/axios ^5.13.6
Auth @nuxtjs/auth + local strategy ^4.9.1
Cookies cookie-universal-nuxt ^2.2.2
UI Bootstrap-Vue 2 + Bootstrap 5.3 (from CDN) ^2.23.1, ^5.3.3
Polotno editor React 18 + MobX-State-Tree + Polotno 2.13.10 (subproject)
Form upload filepond
Notifications vue-notification, vue-toastification
Tests None
Lint / format Not configured

Differences from someli-platform

Concern someli-platform Someli-Designer
Vuex modules 10+ sub-modules (post/, dashboard/, chat/, common/, plan/, reach/, …) Single store/index.js
store/api.js cache layer 5-minute TTL across ~12 endpoints None — components call $axios directly
components/ Many, grouped (Calender/, Charts/, Dashboard/, …) Only 4 (Navbar, Notification, skeletonCard, ToasterProgress)
pages/ Nested under _accid/... Flat — 73 files, no subdirectories
Router middleware chain 5 middlewares (redirect, axios, validUrl, appendUTM, appendUrl) Only axios (declared globally in nuxt.config.js → router.middleware)
Server middleware (api/) Yes (small Nuxt serverMiddleware) None
Bootstrap version Bootstrap 4 (via Bootstrap-Vue) Bootstrap-Vue (4) AND Bootstrap 5.3 from CDN — double-loaded
Polotno editor fork polotno-editor/ (221 KB, AI-rich) polotno-editor/ (50 KB, lean)
Auth header name (FE) Apptype (base64) Apptype (base64)

Junior gotcha: if you've worked on someli-platform, your muscle memory will be wrong here. There is no store/api.js cache. There are not 10 Vuex sub-modules. Components hit $axios directly.


Folder layout

Someli-Designer/
├── package.json                  ← 38 deps, 1 devDep (npm-force-resolutions)
├── package-lock.json
├── nuxt.config.js                ← 71 lines — SPA mode, auth, modules
├── README.md                     ← Polotno editor workflow
├── Dockerfile                    ← multi-stage; EFS-mounted node_modules at runtime
├── polotno-bundle.js (+ .map)    ← built artefact of polotno-editor/
├── assets/css/                   ← blueprint.css, bootstrap.css, common.css
├── components/                   ← ONLY 4 files
│   ├── Navbar.vue                ← role_type-based nav gating (commit 074b9ec)
│   ├── Notification.vue
│   ├── skeletonCard.vue
│   └── ToasterProgress.vue
├── helpers/                      ← small
├── layouts/
│   ├── default.vue               ← Navbar + <nuxt/> + notification slots
│   └── blank.vue                 ← bare layout for login
├── middleware/
│   ├── axios.js                  ← axios interceptor — adds Apptype header
│   └── guest.js                  ← redirects authenticated users away from guest-only pages
├── pages/                        ← 73 flat files (no subdirectories)
│   ├── login.vue
│   ├── dashboard.vue
│   ├── topics.vue, topicsNew.vue
│   ├── content_library.vue, master_library.vue, master_libraryNew.vue
│   ├── conditionedContent.vue, conditionedContentNew.vue
│   ├── image_Library.vue
│   ├── automationTemplate.vue, nonAutomationTemplate.vue, tempsets.vue, carousaltemplates.vue
│   ├── templateEditor.vue, templateEditor1.vue, carousaltemplateEditor.vue  ← Polotno mounts here
│   ├── postEditor.vue, postcreator.vue, postdesigner.vue
│   ├── mediaEditor.vue, MastermediaEditor.vue, PreproductionPostEditor.vue
│   ├── dynamicPost.vue, dynamicPost - Copy.vue, specialdynamicposts.vue, preProductionPost.vue
│   ├── Posts.vue, postsMismatching.vue, contentMismatching.vue
│   ├── PostColorCorrection.vue, TemplateColorCorrection.vue
│   ├── TemplateConditioning.vue, topicvalidation.vue
│   ├── News.vue, LatestNews.vue
│   ├── popularSubjects.vue, subjects.vue, subjectsDemands.vue, subjectsBasedJobs.vue
│   ├── generateSubject.vue, generatedSubjectContent.vue
│   └── ... (and many more)
├── plugins/
│   ├── customCommon.js
│   ├── common.js                 ← registers BootstrapVue + Notifications (client-only)
│   └── hotjar.js                 ← client-only Hotjar tracking
├── polotno-editor/               ← React 18 + MobX-State-Tree subproject
│   ├── index.html / index.js / App.js / app.css
│   ├── package.json              ← 15 runtime deps
│   ├── alltemplatesPanel.js, templatesPanel.js, carousaltemplatesPanel.js
│   ├── brandkitPanel.js          ← note: capital P  (customer app has brandkitpanel.js — lowercase)
│   ├── customUploads.js, mediaGrid.js, Pexels.js, PexelVideos.js
│   ├── CustomPageControls.js, CustomWorkspace.js, icons.js, helper.js
│   ├── QrSection.js, ModalPortal.js
│   └── ...
├── static/                       ← logos
└── store/
    └── index.js                  ← THE single Vuex module — no sub-modules

nuxt.config.js highlights

export default {
  ssr: false,
  head: { /* title, meta, bootstrap.bundle.min.js from jsdelivr CDN — Bootstrap 5 */ },
  css: ['@/assets/css/blueprint.css', '@/assets/css/bootstrap.css', '@/assets/css/common.css'],
  plugins: [
    '@/plugins/customCommon',
    { src: './plugins/common', ssr: false },
    { src: './plugins/hotjar', ssr: false },
  ],
  components: true,                // auto-registration
  router: { middleware: 'axios' }, // ONE global middleware
  buildModules: ['@nuxtjs/dotenv'],
  modules: ['bootstrap-vue/nuxt', '@nuxtjs/axios', '@nuxtjs/auth', 'cookie-universal-nuxt'],
  axios: { baseURL: process.env.baseURL },
  auth: {
    strategies: {
      local: {
        endpoints: {
          login:  { url: 'webauthenticate', method: 'post', propertyName: 'data' },
          user:   { url: 'me', method: 'get', propertyName: 'data' },
          logout: false              // logout is client-side only
        }
      }
    }
  },
  build: { transpile: ['swr'] },
};

Read this file end-to-end. It is short.


CDN-loaded scripts

The only CDN script of note is Bootstrap 5 JS (cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js), loaded from nuxt.config.js → head.script.

Combined with Bootstrap-Vue's Bootstrap 4 CSS, this double-loads Bootstrap. The Bootstrap 5 JS controls the navbar; the Bootstrap 4 CSS styles other Bootstrap-Vue components. If the navbar misbehaves, the 4-vs-5 conflict is the most likely cause.

SRI: the CDN scripts have no integrity attributes. Known platform-wide finding.


State — single-module Vuex

store/index.js is the entire store. There are no sub-modules. Everything (auth state, page data, UI state) lives in one module.

If you've worked on someli-platform and reach for store.dispatch('post/...') or store.dispatch('api/...') — those don't exist here.


Axios interceptor

middleware/axios.js is the only global middleware. It adds the Apptype header (base64-encoded) on outbound requests so designer-api can identify this FE.

Differences from someli-platform/middleware/axios.js:

  • Simpler — no token / accountId conditional header injection on /auth/ paths (designer-api's auth is hand-rolled, not Bearer JWT).
  • Likely just sets Apptype and trusts cookies for the rest.

Read the file directly — it's small.


Role-based nav gating

components/Navbar.vue restricts nav items by role_type (introduced in commit 074b9ec). The backend has corresponding access checks.

Role IDs taxonomy (SUPER_ADMIN, ADMIN, ACCOUNT_MANAGER, DEVELOPER, DESIGNER, …) lives in admin_console_R/src/config/env.ts and is replicated on backends. This is a source of drift risk: the FE's role IDs come from env vars; the backend's are in code. Verify alignment with the team before assuming a role number.


Build, lint, test

Build yarn build → static SPA
Lint Not configured
Format Not configured
Tests None
CI None in repo
Deploy Process owned outside the repo
Branches dev_des_app, uat_des_app, main

Next

03-architecture.md.