README.md
June 17, 2026 ยท View on GitHub
ILUMINATY
Professional Vue 3 template for editorial and commercial websites. It includes a blog, app download landing page, profile directory, event promotion, Sanity-ready content and forms ready to connect to Brevo, Mailchimp or any custom backend through webhooks.
Use cases: music platforms, creator directories, editorial websites, event promotion, app launches, creator communities, sports directories, conference sites, startup landing pages and commercial websites powered by a headless CMS.
If this project helps you, consider leaving a star on the repository.
Overview
ILUMINATY is a reusable Vue 3 template designed to ship a polished marketing site plus editorial infrastructure without coupling the frontend to one author account or one CMS instance.
This repository is intentionally delivered in two modes:
local: instant demo mode with seeded content and images so the site works immediately after clonesanity: headless CMS mode using the Sanity adapter already wired in the frontend
The current demo is music-focused, but the architecture is generic. The artist model acts as a directory entry model and can be repurposed for creators, athletes, speakers, founders, teams, products or any other profile-based catalog.
Production Scope
ILUMINATY is ready for production as an SSG template for small to medium editorial sites, landing pages and catalogs.
Operational reality:
- the Sanity integration now fetches large
postandeventcollections in build-time batches using cursor pagination, which avoids oversized single requests and reduces timeout risk during extraction - the final SSG build still assembles one complete content snapshot in Node.js memory before pages are rendered
- because of that, this template should be treated as a static-site solution for small to medium volumes, not as an infinite-scale publishing architecture
Practical guidance:
- for most template use cases, this architecture is the correct tradeoff
- once a project approaches six-figure content volumes such as roughly
100,000posts, events or equivalent route-producing records, reevaluate the architecture instead of assuming SSG will remain comfortable - the exact ceiling is not guaranteed and depends on content size, route count, build machine RAM and Node.js heap settings
- beyond that range, migrate to a server-rendered or hybrid model that can render pages on demand instead of materializing the full site during build
Delivery caveats:
- validate the Sanity integration against a real Sanity project and real content before launch
- form security and delivery guarantees depend on the real backend or webhook implementation you connect
- transitive dependency risk depends on the state of upstream packages in your install graph
Why Sanity
Sanity is the default CMS in this repository because it solves the hard parts of content operations cleanly:
- structured documents instead of freeform page blobs
- editor-friendly Studio for non-developers
- image hosting and transformations
- flexible schemas for directory entries, events, blog posts and legal pages
- an API model that maps well to a typed Vue application
If the final client is not technical, Sanity is the correct path in this repository because the adapter, document mapping and frontend integration are already implemented. Before production launch, validate the final setup against the real Sanity project and content model you will ship.
Stack
| Technology | Why it is used |
|---|---|
| Vue 3 | Component architecture and reactive UI. |
| Vite 8 | Fast dev server and lean production builds. |
| Vite SSG | Static generation for marketing pages and blog routes. |
| TypeScript | Strong contracts across views, adapters, schemas and services. |
| Tailwind CSS | Fast, consistent utility-first styling. |
| Custom CSS | Brand-specific presentation that should not be forced into utility classes. |
| Vue Router | Marketing routes plus dynamic blog routes. |
| Unhead | SEO meta tags and page head management. |
| GSAP | Motion for hero sections and visual transitions. |
| Zod | Runtime validation for content snapshots and form payloads. |
| DOMPurify | Sanitization before form payloads leave the browser. |
| Sanity | Headless CMS adapter already wired. |
Quick Start
Requirements
- Node.js 20+ recommended
- npm 10+ recommended
Install and run
npm install
npm run dev
Quality checks
npm run lint
npx vue-tsc --noEmit
npm run lint validates the codebase without mutating files. Use npm run lint:fix when you want ESLint to apply safe autofixes.
Linting is configured with the modern flat ESLint setup in eslint.config.js.
This template ships with Vitest. Run the test suite with:
npm run test # watch mode
npm run test:run # single pass
npm run test:coverage
Production build
npm run build
The build runs two steps:
scripts/generate-sitemap.mjsgeneratespublic/sitemap.xmlandpublic/robots.txtvite-ssg buildrenders the static application and blog routes
Deploy
The output of npm run build is a static directory at dist/. Any static host works.
GitHub Pages
The repository ships with a ready-to-use workflow at .github/workflows/deploy.yml. Set VITE_SITE_URL as a repository secret or variable, push to main, and the site deploys automatically. The demo at luynoxrd.github.io/ILUMINATY is deployed this way.
If the site lives under a subpath (for example https://username.github.io/repo-name/), set VITE_SITE_URL to the full URL including the subpath. The build derives the Vite base automatically from that value.
Netlify
# netlify.toml
[build]
command = "npm run build"
publish = "dist"
Set VITE_SITE_URL and any other variables in the Netlify dashboard under Site settings โ Environment variables.
Vercel
// vercel.json
{
"buildCommand": "npm run build",
"outputDirectory": "dist"
}
Set VITE_SITE_URL and other variables in the Vercel dashboard under Project settings โ Environment variables.
Cloudflare Pages
Connect the repository in the Cloudflare dashboard and set:
| Setting | Value |
|---|---|
| Build command | npm run build |
| Build output directory | dist |
Set VITE_SITE_URL and other variables under Settings โ Environment variables.
Environment Variables
Copy .env.example into .env and set the values you need.
Core variables:
| Variable | Purpose |
|---|---|
VITE_SITE_URL | Canonical site URL used by the frontend, SEO metadata and build base path. Include the subpath if the site is deployed under one, for example https://example.com/portfolio. |
VITE_CONTENT_SOURCE | local or sanity. |
VITE_SANITY_PROJECT_ID | Sanity project id. |
VITE_SANITY_DATASET | Sanity dataset name. |
VITE_SANITY_API_VERSION | Sanity API version. |
VITE_SANITY_USE_CDN | Enables or disables Sanity CDN reads. |
VITE_FORM_PROVIDER | mock, webhook or custom for contact form submissions. |
VITE_FORM_ENDPOINT | Server endpoint for the contact form. |
VITE_NEWSLETTER_PROVIDER | mock, webhook or custom for newsletter and event alerts. |
VITE_NEWSLETTER_ENDPOINT | Server endpoint for newsletter and event alerts. |
Important security rule: never expose private API keys in VITE_* variables. Secrets belong in a backend, serverless function or HttpOnly session flow, not in the browser bundle.
Deployment note: the Vite base path is derived automatically from VITE_SITE_URL. If the site lives at the domain root, use https://example.com. If it lives under a subdirectory, include that subdirectory in VITE_SITE_URL.
Theme Modes
The site includes three theme modes:
lightdarksystem
The selected mode is stored in localStorage under the iluminaty-theme key.
Behavior:
- first visit defaults to
system systemfollows the operating system preference- if the user manually selects
lightordark, that preference persists across sessions until the user selectssystemagain public/theme-init.jsis loaded byindex.htmlbefore Vue mounts and applies the right theme immediately, preventing any flash of the wrong theme
Demo Mode vs CMS Mode
Local mode
This is the default mode for first-run preview and template evaluation.
Content is read from:
src/data/pageContent.tssrc/data/artists.tssrc/data/events.tssrc/data/blogPosts.tssrc/data/about.tssrc/data/followers.tssrc/data/assets.ts
Sanity mode
When VITE_CONTENT_SOURCE=sanity, the frontend loads content through:
src/services/content/sanityAdapter.tssrc/services/content/index.tssrc/composables/useContent.tssrc/types/content.tssrc/schemas/content.ts
Implementation notes:
- the adapter validates the normalized content snapshot with Zod before the app mounts
loadContent()resolves before Vue mounts, so components do not boot against an unresolved remote snapshot- large
postandeventcollections are fetched in build-time batches using cursor pagination by_id, then sorted in memory for the final snapshot - the sitemap generator follows the same source selection and uses the same Sanity mode during build
The Sanity adapter already powers:
- home page
- about page
- contact page
- directory page
- events page
- blog page and blog posts
- terms page
- privacy page
- cookies page
- footer and site settings
- featured directory entries on the home page
Sanity Setup
1. Create or open your Sanity project
npm create sanity@latest
2. Copy the schemas from this repository
Use the schemas inside:
sanity-template/schemaTypes/documents/sanity-template/schemaTypes/index.ts
3. Configure the frontend
Set your .env:
VITE_SITE_URL=https://your-domain.com
VITE_CONTENT_SOURCE=sanity
VITE_SANITY_PROJECT_ID=your_project_id
VITE_SANITY_DATASET=production
VITE_SANITY_API_VERSION=2025-01-01
VITE_SANITY_USE_CDN=true
4. Run the frontend
npm run dev
5. Build static pages
npm run build
Blog routes are generated from the available posts during the build. In sanity mode, post discovery for the sitemap and route generation uses batched extraction instead of a fixed hard limit.
Sanity Document Map
Populate these documents to reflect content across the frontend.
Global site settings
Document: siteSettings
Fill:
brandNamefooterDescriptionfooterLinkGroupsfooterFollowLabelfooterCopyrightfooterCreditPrefixfooterCreditNamefooterCreditHreffooterCreditConnectorfooterTechnologyNamefooterTechnologyHreffooterRepositoryLinksocialProfiles
This document controls the footer, social links and attribution area, including the View Repository button and the Powered by LuynoxRD and Vue.js credit line. Replace or remove those values in your fork before publishing your version.
Home page
Document: homePage
Fill:
heroappPreviewlabelsSectionhighlightCardfeaturedArtistsSectioncommunitySectionfaqSectionfeaturedBlogSectionnewsletterSectionappCta
Home also uses:
brandLogodocuments for label or partner logos- featured directory entries from the
artistcollection - the latest blog posts from the
postcollection
About page
Document: aboutPage
Fill the hero, mission, values, team intro and manifesto content. Team members themselves are loaded from teamMember documents.
Contact page
Document: contactPage
Fill the contact hero, method blocks, FAQ section and call-to-action copy. The contact form itself is powered by the form provider layer described later in this README.
Directory page
Document: artistsPage
Even though the schema name is artistsPage, treat it as the directory page configuration for any profile-based catalog.
Fill:
heroTitleheroDescriptionfiltersgenreOptionsneighborhoodOptionsresultsSectionactionspopupemptyState
The popup labels for music and social links are also controlled from this document.
Directory entries
Collection: artist
Each document controls one directory profile. Fill:
namegenrebiolocationLabelimagehomeImageneighborhoodsbadgefeaturedlinks.spotifylinks.youtubelinks.appleMusiclinks.instagramlinks.tiktoklinks.xlinks.soundcloud
How featured entries work on the home page:
- set
featured: trueon the profiles you want to surface - the frontend reads only featured items
- the home section is capped at 10 entries
- if no featured entries exist in Sanity, the template falls back to local demo entries
Events page
Document: eventsPage
Fill:
heroTitleheroDescriptionstatsLabelsfiltersresultsSubtitleresultsTitleSuffixemptyStatepurchaseStepsTitlepurchaseStepsnotificationSectioncardLabels
Event collection
Collection: event
Each event controls:
titledescriptiondatetimedoorsOpenvenuepriceartistsisSoldOutimageticketUrl
Frontend behavior:
- if
ticketUrlexists andisSoldOutisfalse, the event is shown as available and the CTA opens the purchase page - if
isSoldOutistrue, the event is rendered as sold out even if a URL exists - if
ticketUrlis empty andisSoldOutisfalse, the event is rendered as coming soon - month and venue filters are automatic
- counters are derived from the event collection and keep available, sold out and not-yet-ticketed states separate
Blog page
Document: blogPage
Fill:
heroTitleheroDescriptionnewsletterSectionpost.backLabelpost.shareLabelpost.authorLabelpost.tocLabelpost.relatedEyebrowpost.relatedTitlepost.relatedLinkLabelpost.newsletterEyebrowpost.newsletterTitlepost.newsletterDescription
Blog posts
Collection: post
Each post controls:
titleslugexcerptmetaDescriptioncategorydateauthorauthorBioimageAltreadTimecoverImagetagscontentBlocks
Supported content blocks:
- heading
- paragraph
- bullet list
- quote
- image block
- embed
Legal pages
Documents:
termsPageprivacyPagecookiesPage
Each legal page can be edited from Sanity through:
heroTitleheroDescriptionsectionscontactCardfooterNotectaTitlectaDescriptionctaLink
How Content Updates Flow to the Site
The frontend consumes one normalized content snapshot. That means all pages read data from a single typed contract, whether the source is local seed data or Sanity.
The flow is:
- Sanity documents are queried in
src/services/content/sanityAdapter.ts - The adapter maps raw CMS data into the frontend contracts defined in
src/types/content.ts - Zod validates the final snapshot through
src/schemas/content.ts - Vue views read the content through
useContent()
For large collections, the adapter fetches post and event documents in batches using cursor pagination rather than a single unbounded query.
Why this matters:
- editors can update copy without touching Vue files
- the frontend stays strongly typed
- switching between local demo content and Sanity does not require rewriting components
Images
This template has two image pipelines.
1. Local demo images
Used in local mode and as fallback data.
Managed through:
src/assets/public/data/src/data/assets.ts
This includes:
- directory entry demo images
- event demo images
- blog demo covers
- about and team images
- follower and testimonial images
- phone mockup
- default partner logos
2. Sanity images
Used in sanity mode for editorial content.
The adapter already resolves Sanity image fields to plain URLs for:
- home app preview
- brand logos
- directory entry images
- featured home images
- event images
- blog cover images
- about and team media
If you want every visible image to come from Sanity, upload and fill the corresponding image fields in the mapped documents instead of relying on local fallback assets.
How to Move from Local Content to Full Sanity Content
If you want the site to be fully driven by Sanity instead of demo seed data:
- Keep the template in
localmode while you customize layout and branding - Create and register the Sanity Studio schemas from
sanity-template/ - Populate all singleton documents:
siteSettingshomePageaboutPagecontactPageartistsPageeventsPageblogPagetermsPageprivacyPagecookiesPage
- Populate all collections:
artisteventpostteamMembertestimonialbrandLogo
- Switch
.envtoVITE_CONTENT_SOURCE=sanity - Run
npm run devand verify each route - Run
npx vue-tsc --noEmitandnpm run build
The local seed can remain in the repository as demo fallback for future template users. You do not need to delete it unless you want a Sanity-only codebase.
Forms: Brevo, Mailchimp or Any Backend
This frontend does not send requests directly to Brevo or Mailchimp from the browser, because that would introduce avoidable security vulnerabilities and expose sensitive integration details in the client.
Instead, the project ships a provider layer that supports:
mockwebhookcustom
Relevant files:
src/config/forms.tssrc/services/forms/index.tssrc/types/forms.tssrc/schemas/forms.ts
Existing form surfaces:
- contact form
- blog newsletter
- home newsletter
- event alerts newsletter
Recommended production setup:
- Frontend submits to your backend or serverless function
- Backend stores the private API key
- Backend forwards the payload to Brevo, Mailchimp or any internal CRM
- Frontend receives a safe success or error response
Client-side sanitization in this template is a hygiene measure, not a trust boundary. The receiving backend must still validate, sanitize and safely persist or forward every payload.
Example:
VITE_FORM_PROVIDER=webhook
VITE_FORM_ENDPOINT=https://your-api.com/forms/contact
VITE_NEWSLETTER_PROVIDER=webhook
VITE_NEWSLETTER_ENDPOINT=https://your-api.com/forms/newsletter
Extending the CMS Layer
Sanity is the production-ready CMS integration included in this repository.
The content layer is adapter-based, so other CMS providers can be added later by implementing the same ContentAdapter contract used by the local and Sanity sources.
If your client needs a non-technical editing workflow today, keep Sanity. It is the only fully wired CMS integration in this template at the moment.
Security Maintenance
This repository includes a baseline security maintenance setup for a public frontend project:
SECURITY.mddocuments the reporting and maintenance posture.github/dependabot.ymlenables scheduled dependency update pull requests.github/workflows/gitleaks.ymlruns secret scanning on pull requests, pushes tomainand a weekly schedulegitleaks.tomlextends the default Gitleaks ruleset used locally and in CI- GitHub Dependabot alerts and security updates can be enabled in repository settings
- the current lint stack uses modern ESLint flat config and the build toolchain has been updated to patched dependency ranges
Recommended recurring checks:
npm auditnpm outdatednpm run lintnpx vue-tsc --noEmitnpm run buildgitleaks dir .gitleaks git .
Publishing Checklist for Your Fork
- replace demo branding, copy and media
- update
VITE_SITE_URL - populate your Sanity project if you want CMS mode
- validate the real Sanity project end to end before launch
- connect your form endpoints
- replace or remove the footer
View Repositorybutton - replace or remove the footer
Powered by LuynoxRD and Vue.jscredit line - review
siteSettings.socialProfiles - confirm featured directory entries on the home page
- run
npm run lint - run
npx vue-tsc --noEmit - run
npm run build - run
gitleaks dir .andgitleaks git .if you have Gitleaks installed locally - review Dependabot and code scanning alerts before each release
- add automated tests if your delivery process requires regression coverage
Project Structure
src/
components/ reusable UI blocks
composables/ content, forms and theme logic
config/ runtime source and provider selection
data/ local demo content
lib/ shared helpers
schemas/ Zod validators
services/ CMS and form adapters
types/ shared frontend contracts
views/ route-level pages
sanity-template/
schemaTypes/ ready-to-use Sanity schemas
License
Apache 2.0. See LICENSE and NOTICE.
This repository is open source and permits reuse, modification and commercial use under Apache License 2.0.
Practical effect:
- redistributed versions must preserve the license and applicable notices
- modified files should be marked as changed when redistributed
- attribution notices in
NOTICEmust travel with qualifying redistributions - the ILUMINATY name, logo and branding are not granted for trademark use beyond reasonable attribution of origin
Important: Apache 2.0 helps preserve authorship and notices, but it does not prohibit commercial use, resale, forks or large-scale redistribution by itself. If someone wants white-label or OEM-style commercial terms beyond the open source license, contact the author separately.