Branding
Where the product name, logo, icons, colours and fonts live in each Learnio app, and what to change to make it your own brand.
For the Full Stack package
Where the brand lives
The brand is set in files, not in the admin. The student site and the admin dashboard keep their own copies, so change each app you ship.
| What | Student site (frontend/) | Admin dashboard (admin-dashboard/) |
|---|---|---|
| Name, description, links | src/config/site.ts and src/config/brand.config.ts | src/config/brand.config.ts |
| Logo files | public/assets/brand/ | public/assets/brand/ and public/assets/images/ |
| Favicon and app icons | src/app/ and public/icons/ | src/app/, which the manifest in brand.config.ts points at |
| Colours | src/styles/theme-variables.css and src/styles/dashboard-theme.css | src/styles/theme-variables.css |
| Fonts | src/app/layout.tsx and src/styles/base.css | src/app/layout.tsx and src/styles/base.css |
| Wording that names the product | messages/<namespace>/<locale>.json | src/config/brand.config.ts |
yarn dev shows a change straight away. A production build compiles the brand in, so run yarn build again, or docker compose up --build for the full stack.
The name on the student site
Paths are inside frontend/.
| Setting | Where it shows |
|---|---|
SITE.name in src/config/site.ts | The browser tab (Page | Name), sharing previews, the installed app's name and the structured data search engines read. |
SITE.description and SITE.keywords | The meta description, sharing previews and the installed app's description. |
SITE.twitterHandle | The twitter:site and twitter:creator tags on every page's sharing card. Write the handle without @; an empty string leaves both tags out. |
SITE.social | The footer and the mobile menu. Write handles, not URLs. An empty handle removes that link. |
BRAND_CONFIG in src/config/brand.config.ts | The student dashboard: shortName beside the mark in the sidebar, name, version and company in its footer. Each has an en and an ar value. |
The site's public address comes from NEXT_PUBLIC_SITE_URL, not from these files.
The name also appears in the copy: the footer's copyright line, the logo's accessible name (brand.logoLabel in messages/layouts), the home and about pages, the sign-in pages and the legal pages. Find every occurrence in both languages:
frontendgrep -rn "Learnio" messages
grep -rn "ليرنيو" messages- One string is written in code: the
LearnioLMShashtag insrc/components/ui/ShareModal.tsx. - The terms and the privacy policy in
messages/legalcarry sample contact details (legal@learnio.com,privacy@learnio.com, an address in Dubai). Replace them with your own before going live.
The name in the admin dashboard
Everything is in BRAND_CONFIG, in admin-dashboard/src/config/brand.config.ts. Text fields have an en and an ar value.
| Field | Where it shows |
|---|---|
name | Page titles (Page | Name), the sharing preview's site name and the dashboard footer. |
shortName | Beside the mark at the top of the sidebar, in capitals, and beside the mark on the sign-in card. Keep it short: a long name is cut off with an ellipsis. |
company | The dashboard footer, and the copyright line under the sign-in pages, which getCopyrightText builds from the year and this name. |
version | The dashboard footer. |
logo.icon | The mark at the top of the sidebar and on the sign-in card. |
meta | The default title, description, keywords and author, and the sharing images. |
domain.url | The base for absolute links in the metadata. It ships as https://yourdomain.com: set it to the admin's own address. |
logo.alt | The accessible name of the logo on the sign-in pages. |
theme, manifest | Browser and installed-app colours and the installed app's icons, below. |
links, contact | Only the structured data in the page head. Nothing visible reads them. |
Every place that names the product reads BRAND_CONFIG, so renaming it there renames the sidebar, the sign-in card, both footers and the page titles together. The admin's message files do not contain the product name: the copyright line's sentence is a translation (layouts.footer.copyright) with the name filled in from the config.
Logo files
The simplest change is to replace each file with your own at the same path and name. Use a PNG with a transparent background.
| App | File | Size | Where it shows |
|---|---|---|---|
| Student site | public/assets/brand/learnio-wordmark.png | 986 × 293 | The navbar, the mobile menu, the footer and the sign-in pages, in both themes. |
| Student site | public/assets/brand/learnio-mark.png | 512 × 474 | The student dashboard's sidebar. |
| Admin | public/assets/brand/learnio-mark.png | 512 × 474 | The sidebar and the sign-in card, through logo.icon. Also the default sharing image, below. |
| Admin | public/assets/images/logo-for-lightmode.png and logo-for-darkmode.png | 986 × 293 | The top bar of the sign-in pages, one file per theme. |
- The student site draws one wordmark on light and dark pages, so pick artwork that reads on both.
- In the admin, the two theme files are chosen by
--logo-bg-imageinsrc/styles/theme-variables.css. They ship as the same image. - The admin's own copy of
learnio-wordmark.pngis not used by any page.
To use a file with another name in the admin, point logo.icon in BRAND_CONFIG at it. If your artwork has a different shape, update the declared size so it is not stretched: the width and height in ASSETS in the student site's src/components/ui/BrandLogo.tsx, and width={512} and height={474} in src/layouts/dashboard/sidebar/components/SidebarBrand.tsx (both apps) and the admin's src/layouts/auth/components/FormPanel.tsx.
Favicon, app icons and sharing images
Next.js finds the files in src/app/ by name and writes the page tags for them, so replace the files and keep their names.
| App | File | Size | Used for |
|---|---|---|---|
| Both | src/app/favicon.ico | Several sizes in one file | The browser tab |
| Both | src/app/icon.png | 512 × 512 | The browser icon |
| Both | src/app/apple-icon.png | 180 × 180 | The iOS home screen |
| Student site | public/icons/icon-192.png, public/icons/icon-512.png | 192 and 512 square | The installed app. The 512 one is also the logo in the structured data. |
| Student site | public/icons/icon-maskable-512.png | 512 × 512 | Android, which may crop it to a circle. Keep the mark well inside the edges. |
| Student site | src/app/opengraph-image.png, src/app/twitter-image.png | 1200 × 630 | Link previews |
The admin has one web app manifest, served at /manifest.webmanifest from src/app/manifest.ts, which reads manifest in BRAND_CONFIG:
manifest.iconslists the installed-app icons:/icon.png(512 × 512) and/apple-icon.png(180 × 180), the two files insrc/app/. Replacing those files changes the browser icon and the installed app's icon together. If you point an entry at another file, give it that file's real size.meta.ogImageandmeta.twitterImageare the link previews,/assets/brand/learnio-mark.pngby default. The metadata declares the image as 512 × 474 and uses the smallsummarycard, so a replacement of another size needs thewidthandheightinsrc/app/layout.tsxchanged with it.- The admin tells search engines not to index it, in the page metadata and in
public/robots.txt: it is a staff tool, not a public page.
Colours on the student site
The public pages read their colours from CSS variables in src/styles/theme-variables.css: the light values under :root, the dark ones under .dark. The brand orange is #FF6A3D.
| Variable | What it colours |
|---|---|
--primaryColor, --primaryColorHover, --primaryColorLight | Buttons, links, active states, and the pale tint behind them. |
--brand-start, --brand-end | The two brand inks: orange for actions, yellow for progress and prices. Set again under .dark. |
--brand-start-ink, --brand-end-ink, --brand-figure-ink | Darker versions of the same colours for text, so it stays readable on a light page. |
--brand-action-hover, --brand-dark-pink | The filled button's hover, and an older name for the primary fill. |
--background, --surface, --text, --border | The page, cards, text and rules. |
- The signed-in student dashboard uses the admin's palette, copied into
src/styles/dashboard-theme.cssand limited to the dashboard. Its orange is#FF8A00. The copy is kept by hand: when a colour changes in the admin'stheme-variables.css, change it in this file as well. - A few illustrations write the orange directly instead of using a variable: the instructor profile and the home page's "How it works" steps. Search
src/featuresforFF6A3D. - The colour the browser paints around the page (the mobile address bar) is
SITE.browserChromeinsrc/config/site.ts, one value per theme, each matching that theme's page background. The installed app's colours areSITE.themeColorandSITE.backgroundColorin the same file.
Colours in the admin dashboard
All colours are CSS variables in src/styles/theme-variables.css, light under :root and dark under .dark. The brand orange is --primaryColor, #ff8a00 in both themes, with --primaryColorHover for its hover.
- Shades of the orange are written out as their own values: the
--accent-*family, the--chip-*family and--btn-primary-fill, which is#ff6a3din the light theme. To change the brand colour, search the file forff8a00,255, 138, 0andff6a3dand rework the shades next to them. - Apart from the browser colours below, this file is the only place the admin writes the orange. No component hardcodes it.
- Browser chrome colours are
theme.lightandtheme.darkinBRAND_CONFIG. The installed app usesmanifest.themeColorandmanifest.backgroundColor.
Fonts
Both apps load Inter for English and IBM Plex Sans Arabic for Arabic through next/font/google in src/app/layout.tsx, which serves them from your own domain. src/styles/base.css switches to the Arabic face when the page language is ar.
| App | Latin font variable | Arabic font variable |
|---|---|---|
| Student site | --font-inter | --font-ibm-plex-arabic |
| Admin | --font-sans-latin | --font-sans-arabic |
To change a font, import another one from next/font/google and keep its variable name, so the stylesheets pick it up unchanged. On the student site:
import { IBM_Plex_Sans_Arabic, Manrope } from "next/font/google";
const inter = Manrope({
subsets: ["latin"],
display: "swap",
variable: "--font-inter",
});A font that is not a variable font needs a weight list, as the Arabic one has. The student site's src/styles/base.css also names 'Inter' as a fallback; update it if you rename the variable.
Emails and the API
- Sender:
MAIL_FROMinback-end/.envis the name and address every email comes from, for exampleLearnio <noreply@example.com>. - Name: emails name the product through the
{site}placeholder insrc/i18n/translations/<locale>/mail.json, filled from thesite_namesetting. Change it in the admin's Settings, App Settings tab; it applies to the next email sent. - Replies: the
support_emailsetting is the reply-to address of every email, so a reply reaches a person rather than the no-reply sender. - Wording: subjects and bodies are in
src/i18n/translations/en/mail.jsonandsrc/i18n/translations/ar/mail.json. - Look: emails carry no logo. Their colours are written in
src/modules/mail/templates/layout.ts(INK,MUTED,PAGE,CARD), because mail clients drop stylesheets. - Links in emails open the student site at
FRONTEND_URL.
The App Settings tab does not rebrand the apps
site_name and support_email change the emails only. The student site and the admin dashboard take their name, logo and colours from the files above, so change those as well.