HP TV+
Getting Started
Project Setup
Prerequisites
HP TV+ uses pnpm as dependency manager, if you want to use another alternative, please go to package.json file and update the packageManager value
For more information, please visit official node section about packageManager
We use nvm to select proper node version.
Install dependencies and run app
# First, install nvm, the node version used in this project is defined in the .nvmrc file.
nvm use
corepack enable pnpm
pnpm i
# Run the development server
pnpm dev
Debug the application
Variables:
NAMESPACEPREFIXPrefix to be used as part of the deployment process for the name and url of such deploment. Please Sync with the DevOps team for the associated deployments as that will be used for the CI/CD.APP_DOMAIN: Application base domain (apps.ps.accedo.tv). Please Sync with the DevOps team for the associated deploymentsCI_APPNAME: Next Application appname to be used in the deployment process and hostDOC_APPNAME: Doc Application appname to be used in the deployment process and hostSTORYBOOK_APPNAME: Storybook Application appname to be used in the deployment process and hostAWS_CLUSTERNAME: Cluster name for the deployment. Please Sync with the DevOps to understand the value you should use here.AWS_REGION: AWS region to be used by default on the deployments. Please Sync with the DevOps to understand the value you should use here.TESTRAIL_PROJECTID: TestRail Project IDTESTRAIL_SUITEID: TestRail Suite IDTESTRAIL_TITLE: TestRail Run base titleTESTRAIL_URL: TestRail Base URL
Note: We also use DEMO1_APPNAME and DEMO1_APPNAME for out internal demo purposes, but you wont need those.
Secrets:
AWSARN: AWS Amazon Resource Name to be used in the deployments. Please Sync with the DevOps to understand the value you should use here.FIGMA_TOKEN: Figma API Token to be used to be able to fetch the Design Tokens from your the Figma files associated with the project. Please avoid using personal token and use a "corporate" one instead.NEW_RELIC_APP_NAME: New Relic Application name. Please ask your Architect/PM for a project specific value.NEW_RELIC_LICENSE_KEY: New Relic license key. Please ask your Architect/PM for a project specific value.NPM_RESOLVER: npm token to be used to fetch the@accedoand similar private dependencies from the npm registry. Please avoid using personal token and use a "corporate" one instead.SLACK_WEBHOOK: Slack Application webhook token. Please Sync with the DevOps/IT to understand the value you should use here.SONAR_TOKEN_CI: SonarCloud access token to allow the CI to report to Sonar. Please Sync with the DevOps/IT to understand the value you should use here.TESTRAIL_KEY: TestRail User apiKeyTESTRAIL_PROJECT: TestRail Project NameTESTRAIL_USER: TestRail user emailE2E_EMAIL: Application username to be used on the e2e testsE2E_PASSWORD: Application password to be used on the e2e tests
NPM Scripts
Project App Structure
HP TV+ is a Next.js based application, so some conventions are based on the conventions defined in the framework itself, we recommend you to read at least App Routing Conventions
Initialization (Services)
Use the ServiceManager.configure pattern at app boot. It’s idempotent and safe for SSR/HMR:
import { ServiceManager } from '@/services/manager';
import { serviceConfig } from '@/services/config';
// Configure once at boot
ServiceManager.configure(serviceConfig);
// Optionally touch the instance to eagerly initialize
ServiceManager.getInstance();
In tests, reset and reconfigure explicitly:
import { ServiceManager } from '@/services/manager';
import { serviceConfig } from '@/services/config';
beforeEach(() => {
ServiceManager.resetForTests();
ServiceManager.configure(serviceConfig);
ServiceManager.getInstance();
});
Component Structure
We are going to follow the a Component structure based on two concepts:
- Complexity-based: reusable components that can be used across any page/template, with a separation in two:
- simple: stateless, very reusable components
- complex: Usually composed from other simple components and can have state
- Feature-based: every complex component, that is not going to be reusable, but just part of an specific feature (EPG, Auth, Player, ...)
Besides that, we need to take into account that Pages/views and partially, any possible route-based template will be created under the app folder following the App Routing Conventions from Next.js
The reason to keep this structure and not a pure Atom-based model is to avoid having all the components under the components folder, making very hard to traverse and look for the proper component, but limit it with the feature-based list of components and then simplify the 3-4 other layers (pages/views should be always under the app folder due to Next.js) into 2 at least initially to have a clear separation for the atomic, non-composed ones (and also stateless) from the others.
General Structure
📂 docs ───────> project documentation
📂 public ───────> web static assets
📂 src ───────> source dir
├─ 📂 app ───────> next.js routes
│ └─ 📂 [[...routeSegments]] ───────> Single dynamic route page (more on the next section)
│ └─ 📄 layout ───────> default page layout
│ ...
├─ 📂 components ───────> Complexity-based Components folder
│ └─ 📂 simple ───────> Simple Components (Reels components or not composed and without state)
│ └─ 📂 base ───────> Reels Components (Component from the Component library based on PD&A Reels)
│ └─ 📂 complex ───────> Complex Components (composed from simple components or with state)
├─ 📂 config ───────> Application configuration
├─ 📂 context ───────> App global React contexts
├─ 📂 dataModels ───────> Any app data model
├─ 📂 dev-utils ───────> Utilities used for development purposes
├─ 📂 features ───────> Feature-based Components folder
│ └─ 📂 ... ───────> A per feature folder, it will include all the needed code outside of the Data Fetching related one
├─ 📂 hooks ───────> App hooks, use for common shared utilities fns and Service access
├─ 📂 providers ───────> App Providers
├─ 📂 services ───────> App Services
├─ 📂 types ───────> Typescript type utilities and global types
├─ 📂 utils ───────> Global utils
├─ 📂 views ───────> Application dynamic views (mapped from [[...routeSegments]]) and mapper
📄 .env ───────> environment variables
📄 next-env.d.ts ───────> next.js type defs
📄 next.config.js ───────> next.js config
📄 package.json ───────> project readme
📄 [other configs] ───────> Any other config file
HP TV+ Mapping
Project Documentation
General Documentation
Documentation for HP TV+ is created using Docusaurus inside the docs folder. There a separate "project" inside that folder which it's own npm project structure and so on.
The initial page uses this README.md file to create and display its content
To access documentation:
cd docs
pnpm start
To create documentation build:
cd docs
pnpm run build
pnpm run serve
If you need to add any extra Documentation, please add a new entry into docs/docs
You can use the helper command from the root of the repository to access the documentation:
pnpm run docs
Diagrams
HP TV+ uses mermaid for the diagrams which integrates directly with Github and with an integration with Docusaurus
Components
Code rules
General
Code and CSS Style Guidelines
We are using eslint, prettier and stylelint to define the project code style and ensure that everyone follows the same rules.
We enforce the usage of typescript as default language to ensure better type check and remove possible situations/issues.
Please refer to the .eslintrc.json and .stylelintrc.json to see the specific configuration we use for each tool.
You can also read the Next.js Docs about the default eslint config.
App Styling
HP TV+ uses CSS Modules together with Design tokens to create the styles for the applications and components.
Style entry point file is globals.css and there is includes all the Design System tokens from _variables.css.
Custom pages/layout styles, component styles or features styles should be included in it's own folder and use Design System tokens when possible.
NOTE
Font Family is not used based on the Design tokens variables but using next/font/google instead as it's the standard way of working on Next.js
Testing
We use jest, testing-library, storybook and playwright for the Automatic testing of the application.
jestis used as test runner and assertion librarytesting-libraryis used for the component and component interaction library on the simple cases.storybookis used for the component interaction test for more detailed casesplaywrightis used for end to end testing.
GitFlow and Related Rules
Branching and Code Reviews
We have a main branch staging and usually we work toward that branch every time, which is then sync into the main branch. Our philosophy is to Ship as fast as possible into the main branch and use the Setup validations to ensure everything works as expected.
We follow a Ship/Show/Ask approach where:
- We Ship directly into
stagingbranch anything that doesn't require any validation or it's totally straightforward. - We Show creating a PR into
stagingwith the tag[SHOW]to create a PR that doesn't require manual validation, but that can benefit for it or has something that can be interesting to show to peers. Automatic validations will help to avoid merging an invalid PR. - We Ask creating a PR that requires manual validation for any peer/contributor to ensure a patter is properly implemented or there's no mistake into the implementation (apart from the automatic validations)
For all the cases, there's a PR template for Github located in .github/pull_request_template.md
Branch Naming conventions
We use short-live feature branches to handle features work, and bugfix branches for aby fix needed.
The prefixes for those are: feat and fix and the general naming convention for the branches will be:
{type}/BUILDELEVATE-XXXX_description-name: for ticket related branches{type}/description-name: for non-ticket related branches
Github Actions
Validations
We have separate Github actions created to do all the actions related to a change for every PR (creation, change) and main push that will execute (pr.yml and main.yml):
Then we have splitted the workflows into validations (validations.yml) and deployments.
The validations will:
- All the code validations (linters and tsc)
- Unit and component test validation with code coverage report
- Component Accessibility Validation using Storybook
- Danger Pull request analysis
- Sonar Analysis with report to SonarCloud, including the test coverage from the test report and the automatic generation of sonar properties from template
After all the static validations the main workflows, will trigger the CI/CD workflows if the conditions for the trigger checks are met (ie: we wouldn't trigger from pr.yml the deployment if the trigger was an edited event.action as it will not include code changes)
CI/CD
We have three separate Github actions created for each of the deploy types as workflow_call:
- Nextjs Application deployment on
Build-&-Deploy_webci-elevate.yml - Documentation deployment on
Build-&-Deploy_doc-elevate-web.yml - Component Documentation deployment on
Build-&-Deploy_storybook-elevate-web.yml
This process will deploy it corresponding application/static site following the rules:
https://hpchannels-prod.apps.ps.accedo.tvfor the Nextjs App onmainbranchhttps://hpchannels-staging.apps.ps.accedo.tvfor the Nextjs App onstagingbranchhttps://hpchannels-prod-pr-{N}.apps.ps.accedo.tvfor the Nextjs App on a PR with numberNon Githubhttps://hpchannels-doc.apps.ps.accedo.tv/for the General Documentation onstagingbranchhttps://hpchannels-doc-pr-{N}.apps.ps.accedo.tv/for the General Documentation on a PR with numberNon Githubhttps://hpchannels-storybook.apps.ps.accedo.tvfor the Component Documentation onstagingbranchhttps://hpchannels-storybook-pr-{N}.apps.ps.accedo.tvfor the Component Documentation on a PR with numberNon Github
Note: PR related deployments will only be triggered if the following tags are included in the PR:
Elevatefor App deploymentstorybookfor omponent Documentation deploymentdocusaurusfor Documentation deployment
Danger PR Analysis
We use Danger to do some aumatic validations of de "quality" of the Pull request and also to report back into the Pull Request based on the base branch and the Status of the Pull Request.
You can find the specific code into the Dangerfile file.
Commit messages guide
We enforce the usage of convential commits to create explicit commit messages
We use commitlint with @commitlint/config-conventional and husky to ensure that the commits follow the proper messages. Please don't skip hooks
Versioning and Releases
Together with the Commit rules, we do automatic versioning based on the rules applied on convential commits following Semantic Versioning
For the releases, we use Semantic Release with it's own Github Action to define a Workflow to ensure every merge into main creates it's own separate HP TV+ version.
You can see how is configured in:
- Workflow:
.github/workflows/release.yml - Semantic Release Config:
.releaserc.json
It is in charge of the following:
- Determine the version to create based on the commits since the previous tag based on the commitlint conventions
- Execute the version change using
@semantic-release/execand set-version - Generate Changelog for both Github Release and CHANGELOG.md file
- Create and push tag with the proper name/version
- Create Github Release with the proper name/version
Initially we create prereleases with the dev tags. This will be changed once we release the first final version of HP TV+.