├── .github
└── workflows
│ └── build.yaml
├── .gitignore
├── README.md
├── fonts
└── Iosevka-regular.ttf
├── images
├── bg.jpg
└── icon.png
├── index.html
├── js
├── time.js
└── weather.js
├── manifest.json
├── package-lock.json
├── package.json
├── scrot.png
├── shell.nix
└── style.css
/.github/workflows/build.yaml:
--------------------------------------------------------------------------------
1 | ---
2 | name: Releases
3 | on:
4 | push:
5 | branches: [main]
6 | jobs:
7 | build:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - name: Checkout repository
11 | uses: actions/checkout@v4
12 | - name: Set up Node.js
13 | uses: actions/setup-node@v4
14 | with:
15 | node-version: '20'
16 | - name: Install dependencies
17 | run: npm install
18 | - name: Install web-ext
19 | run: npm install --global web-ext
20 | - name: Extract version from manifest.json
21 | id: get_version
22 | run: |
23 | version=$(jq -r '.version' manifest.json)
24 | echo "VERSION=$version" >> $GITHUB_ENV
25 | - name: Inject environment variables into weather.js
26 | run: |
27 | sed -i 's/const key = "";/const key = "${{ secrets.KEY }}";/' js/weather.js
28 | sed -i 's/const latitude = 0;/const latitude = ${{ secrets.LATITUDE }};/' js/weather.js
29 | sed -i 's/const longitude = 0;/const longitude = ${{ secrets.LONGITUDE }};/' js/weather.js
30 | - name: Build and Sign Extension
31 | id: build
32 | env:
33 | FIREFOX_JWT_ISSUER: ${{ secrets.FIREFOX_JWT_ISSUER }}
34 | FIREFOX_JWT_SECRET: ${{ secrets.FIREFOX_JWT_SECRET }}
35 | run: |
36 | web-ext sign \
37 | --channel=unlisted \
38 | --api-key=$FIREFOX_JWT_ISSUER \
39 | --api-secret=$FIREFOX_JWT_SECRET | tee >(cat) | \
40 | grep "^Generated extension ID:" | \
41 | xargs -I {} echo "EXTENSION_ID={}" >> $GITHUB_ENV
42 | - name: Prep Artifact
43 | run: |
44 | mv web-ext-artifacts/*.xpi web-ext-artifacts/startpage-${{ env.VERSION }}.xpi
45 | - name: Generate SHA-256 SRI hash for xpi file
46 | id: generate_sri
47 | run: |
48 | SHA256_HASH=$(openssl dgst -sha256 -binary web-ext-artifacts/startpage-${{ env.VERSION }}.xpi | \
49 | openssl base64 -A)
50 | echo "SRI_HASH=sha256-$SHA256_HASH" >> $GITHUB_ENV
51 | - name: Release
52 | uses: ncipollo/release-action@v1.14.0
53 | with:
54 | tag: ${{ env.VERSION }}
55 | artifacts: web-ext-artifacts/startpage-${{ env.VERSION }}.xpi
56 | allowUpdates: true
57 | replacesArtifacts: true
58 | token: ${{ secrets.GITHUB_TOKEN }}
59 | body: |-
60 | ${{ env.EXTENSION_ID }}
61 | SHA-256: `${{ env.SRI_HASH }}`
62 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | web-ext-artifacts/
3 | .web-extension-id
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Startpage
2 |
3 | Flat minimal start page made for elegant look and simple at same time.
4 | there is more than branch every one have a unique ui.
5 |
6 | 
7 |
8 | ## Pack as web-ext
9 | 1. Clone the repo
10 | ```
11 | git clone https://github.com/mahmoudk1000/startpage.git
12 | ```
13 |
14 | 2. You need to install web--ext tool by runing terminal
15 | ```
16 | sudo npm install -g web-ext
17 | ```
18 |
19 | 3. Check Firefox [ext-packing guide](https://extensionworkshop.com/)
20 |
21 | 4. Last step run in terminal in same dir where repo cloned
22 | ```
23 | web-ext sign --api-key "YOUR_USER_KEY" --api-secret "YOUR_SECRET"
24 | ```
25 |
26 | ## Weather
27 | For setting up the Weather widget you're going to need an API Key in: https://openweathermap.org/. Once you have your Key you'll need to set yourlatitude and longitude, you can use: https://www.latlong.net/ to get them. Then you just have to fill them in the weather.js in the js folder:
28 | ```js
29 | // Use your own key for the Weather, Get it here: https://openweathermap.org/
30 | const key = "XXXXXXXXXXXXXXXXXXXXXXXXXXX";
31 |
32 | setPosition();
33 |
34 | function setPosition(position) {
35 | // Here you can change your position
36 | // You can use https://www.latlong.net/ to get it! (I use San Francisco as an example)
37 | let latitude = 37.774929;
38 | let longitude = -122.419418;
39 |
40 | getWeather(latitude, longitude);
41 | }
42 | ```
43 |
44 |
45 | ## Credits
46 |
47 | [migueravila/Bento](https://github.com/migueravila/Bento) For time, date and weather script and weather guide.
48 | [MCotocel/startpage](https://github.com/MCotocel/startpage) For DuckDuckGo search script
49 |
--------------------------------------------------------------------------------
/fonts/Iosevka-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mahmoudk1000/startpage/c4d4439eb8c5bae9fc4c91f2abcf4744f4e40b6b/fonts/Iosevka-regular.ttf
--------------------------------------------------------------------------------
/images/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mahmoudk1000/startpage/c4d4439eb8c5bae9fc4c91f2abcf4744f4e40b6b/images/bg.jpg
--------------------------------------------------------------------------------
/images/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mahmoudk1000/startpage/c4d4439eb8c5bae9fc4c91f2abcf4744f4e40b6b/images/icon.png
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | H O M E
8 |
9 |
10 |
11 |
12 |
32 |
33 |
34 |
51 |
68 |
85 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/js/time.js:
--------------------------------------------------------------------------------
1 | window.onload = displayClock();
2 | function displayClock() {
3 | const monthNames = [
4 | "Jan",
5 | "Feb",
6 | "Mar",
7 | "Apr",
8 | "May",
9 | "Jun",
10 | "Jul",
11 | "Aug",
12 | "Sep",
13 | "Oct",
14 | "Nov",
15 | "Dec",
16 | ];
17 | const daysOfWeek = [
18 | 'Sun',
19 | 'Mon',
20 | 'Tues',
21 | 'Wed',
22 | 'Thurs',
23 | 'Fri',
24 | 'Sat'
25 | ];
26 |
27 | // Set to true to use a 12 hour date format
28 | var format_12hour = false;
29 |
30 | var d = new Date();
31 | var dn = daysOfWeek[d.getDay()];
32 | var mm = monthNames[d.getMonth()];
33 | var dd = d.getDate();
34 | var min = (mins = ("0" + d.getMinutes()).slice(-2));
35 | var hh = d.getHours();
36 | var ampm = "";
37 | var yy = d.getFullYear();
38 |
39 | if (format_12hour) {
40 | ampm = hh >= 12 ? " PM" : " AM";
41 | hh = hh % 12;
42 | hh = hh ? hh : 12; //show mod 0 as 12
43 | }
44 |
45 | document.getElementById("hour").innerText = hh;
46 | document.getElementById("separator").innerHTML = " : ";
47 | document.getElementById("minutes").innerText = min + ampm;
48 |
49 | document.getElementById("dow").innerText = dn;
50 | document.getElementById("day").innerText = dd;
51 | document.getElementById("month").innerText = mm;
52 | document.getElementById("year").innerText = yy;
53 |
54 | setTimeout(displayClock, 1000);
55 | }
56 |
--------------------------------------------------------------------------------
/js/weather.js:
--------------------------------------------------------------------------------
1 | const key = "";
2 | const latitude = 0;
3 | const longitude = 0;
4 |
5 | const tempElement = document.querySelector(".temperature-value span");
6 |
7 | // App data
8 | const weather = {};
9 | weather.temperature = {
10 | unit: "celsius",
11 | };
12 |
13 | // Change to 'F' for Fahrenheit
14 | var tempUnit = "C";
15 |
16 | const KELVIN = 273.15;
17 |
18 | // Set Position function
19 | setPosition();
20 |
21 | function setPosition(position) {
22 | // Here you can change your position
23 | // You can use https://www.latlong.net/ to get it! (I use San Francisco as an example)
24 | getWeather(latitude, longitude)
25 | }
26 |
27 | // Get the Weather data
28 | function getWeather(latitude, longitude) {
29 | let api = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${key}`;
30 |
31 | console.log(api);
32 |
33 | fetch(api)
34 | .then(function (response) {
35 | let data = response.json();
36 | return data;
37 | })
38 | .then(function (data) {
39 | let celsius = Math.floor(data.main.temp - KELVIN);
40 | weather.temperature.value =
41 | tempUnit == "C" ? celsius : (celsius * 9) / 5 + 32;
42 | })
43 | .then(function () {
44 | displayWeather();
45 | });
46 | }
47 |
48 | // Display Weather info
49 | function displayWeather() {
50 | tempElement.innerHTML = `${weather.temperature.value}°${tempUnit}`;
51 | }
52 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 2,
3 | "name": "start-page-colors",
4 | "short_name": "start-page-colors",
5 | "version": "3.1.1",
6 | "description": "Minimal start page made for elegant look and simple at same time.",
7 | "author": "mahmoudk1000",
8 | "icons": {
9 | "48": "images/icon.png"
10 | },
11 | "background": {
12 | "scripts": [
13 | "js/time.js",
14 | "js/weather.js"
15 | ]
16 | },
17 | "chrome_url_overrides": {
18 | "newtab": "index.html"
19 | },
20 | "permissions": [
21 | "storage",
22 | "tabs",
23 | "sessions"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "web-ext": "^7.11.0"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/scrot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/mahmoudk1000/startpage/c4d4439eb8c5bae9fc4c91f2abcf4744f4e40b6b/scrot.png
--------------------------------------------------------------------------------
/shell.nix:
--------------------------------------------------------------------------------
1 | { pkgs ? import {} }:
2 |
3 | pkgs.mkShell {
4 | name = "Startpage";
5 | buildInputs = with pkgs; [
6 | nodejs
7 | # web-ext
8 | ];
9 | }
10 |
--------------------------------------------------------------------------------
/style.css:
--------------------------------------------------------------------------------
1 | :root {
2 | /* Colors */
3 | --darkbg: #11171D;
4 | --lightbg: #161D25;
5 | --fg: #E2E8EE;
6 | }
7 |
8 | @font-face {
9 | font-family: Iosevka;
10 | src: url(../fonts/Iosevka-regular.ttf);
11 | }
12 | * {
13 | font-family: Iosevka;
14 | text-decoration: none;
15 | }
16 |
17 | @media only screen and (max-width: 768px) {
18 | .body {
19 | padding: 10px;
20 | }
21 | .header {
22 | flex-direction: column;
23 | text-align: center;
24 | padding: 20px;
25 | }
26 | .header > h1 {
27 | font-size: 18px;
28 | margin-bottom: 10px;
29 | }
30 | .info {
31 | flex-direction: column;
32 | align-items: center;
33 | margin-top: 10px;
34 | }
35 | .clock {
36 | margin-bottom: 10px;
37 | }
38 | .bookmarks {
39 | display: flex;
40 | justify-content: center;
41 | flex-wrap: wrap;
42 | margin-top: 20px;
43 | }
44 | .menu_place {
45 | width: 45%;
46 | margin: 10px;
47 | padding: 15px;
48 | text-align: center;
49 | }
50 | .list {
51 | font-size: 16px;
52 | padding-top: 10px;
53 | }
54 | .menu_name {
55 | margin-bottom: 10px;
56 | }
57 | }
58 |
59 | .body {
60 | background-color: var(--darkbg);
61 | margin: 0;
62 | position: absolute;
63 | top: 50%;
64 | left: 50%;
65 | -ms-transform: translate(-50%, -50%);
66 | transform: translate(-50%, -50%);
67 | }
68 | .header {
69 | color: var(--darkbg);
70 | height: fit-content;
71 | width: 100%;
72 | display: flex;
73 | background-image: linear-gradient(to right, #D7C1ED, #96CDFB, #B5E8E0, #F28FAD);
74 | border-radius: 8px;
75 | align-items: center;
76 | }
77 | .quote {
78 | font-size: 21px;
79 | margin: 1.5%;
80 | }
81 | .header > h1 {
82 | flex: 80%;
83 | }
84 | .header > div {
85 | flex: 20%;
86 | }
87 | .info {
88 | align-items: center;
89 | margin: 1.5%;
90 | }
91 | .clock,
92 | .temp {
93 | display: flex;
94 | justify-content: right;
95 | }
96 | .clock {
97 | font-size: 28px;
98 | align-items: end;
99 | }
100 | .temp {
101 | font-size: 14px;
102 | text-indent: 3px;
103 | align-items: center;
104 | }
105 | .bookmarks {
106 | margin-top: 40px;
107 | justify-content: center;
108 | display: flex;
109 | }
110 | .menu_place {
111 | color: var(--fg);
112 | padding: 15px;
113 | width: 260px;
114 | height: 230px;
115 | justify-content: center;
116 | border-radius: 8px;
117 | margin: 0 10px;
118 | }
119 | .menu_place:first-child {
120 | margin-left: 0;
121 | }
122 |
123 | .menu_place:last-child {
124 | margin-right: 0;
125 | }
126 | .list {
127 | text-align: center;
128 | display: block;
129 | font-size: 26px;
130 | margin-top: 20px;
131 | }
132 | .menu_name {
133 | color: var(--darkbg);
134 | text-align: center;
135 | font-size: 28px;
136 | border-radius: 8px;
137 | padding-top: 7px;
138 | padding-bottom: 7px;
139 | }
140 | .in_list_general {
141 | color: var(--fg);
142 | border-radius: 8px;
143 | height: 40px;
144 | text-align: left;
145 | padding-left: 25px;
146 | }
147 | .in_list_one:hover {
148 | color: #11171D;
149 | background-color: #D7C1ED;
150 | }
151 | .in_list_two:hover {
152 | color: #11171D;
153 | background-color: #96CDFB;
154 | }
155 | .in_list_three:hover {
156 | color: #11171D;
157 | background-color: #B5E8E0;
158 | }
159 | .in_list_four:hover {
160 | color: #11171D;
161 | background-color: #F28FAD;
162 | }
163 | .link_text {
164 | color: var(--fg);
165 | vertical-align: middle;
166 | font-variant: small-caps;
167 | }
168 |
--------------------------------------------------------------------------------