added astro

This commit is contained in:
Sebastian Wendel 2023-04-07 16:32:36 +02:00
parent ac596a15a5
commit a2c92466b9
No known key found for this signature in database
GPG key ID: 14ED8B1EC3371ECE
62 changed files with 6706 additions and 0 deletions

7
.envrc Normal file
View file

@ -0,0 +1,7 @@
watch_file flake.nix flake.lock package.json yarn.lock nix/*.nix
use flake
yarn install
yarn sync

20
.eslintignore Normal file
View file

@ -0,0 +1,20 @@
# build output
dist/
result
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store

32
.eslintrc.js Normal file
View file

@ -0,0 +1,32 @@
module.exports = {
env: {
browser: true,
es2021: true,
},
extends: ['plugin:astro/all'],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
},
plugins: ['@typescript-eslint'],
rules: {},
overrides: [
{
// Define the configuration for `.astro` file.
files: ['*.astro'],
// Allows Astro components to be parsed.
parser: 'astro-eslint-parser',
// Parse the script in `.astro` as TypeScript by adding the following configuration.
// It's the setting you need when using TypeScript.
parserOptions: {
parser: '@typescript-eslint/parser',
extraFileExtensions: ['.astro'],
},
rules: {
// override/add rules settings here, such as:
'astro/no-set-html-directive': 'off',
},
},
],
};

View file

@ -0,0 +1,20 @@
name: node-build
on:
push:
branches: [main]
jobs:
node:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0
- run: git fetch --force --tags
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm ci
- run: npm test
- run: npm run build

26
.gitignore vendored Normal file
View file

@ -0,0 +1,26 @@
# nix env
.direnv/
result
# build output
dist/
# generated type files
.astro/
# dependencies
node_modules/
# logs
npm-debug.log*
pnpm-debug.log*
yarn-debug.log*
yarn-error.log*
# environment variables
.env
.env.production
src/env.d.ts
# pre-commit
/.pre-commit-config.yaml

2
.npmrc Normal file
View file

@ -0,0 +1,2 @@
# Expose Astro dependencies for `pnpm` users
shamefully-hoist=true

4
.prettierignore Normal file
View file

@ -0,0 +1,4 @@
/.vscode
/dist
/result
/.direnv

5
.prettierrc Normal file
View file

@ -0,0 +1,5 @@
{
"tabWidth": 2,
"useTabs": false,
"bracketSameLine": true
}

30
.prettierrc.cjs Normal file
View file

@ -0,0 +1,30 @@
/** @type {import("@types/prettier").Options} */
module.exports = {
printWidth: 100,
semi: true,
singleQuote: true,
tabWidth: 4,
trailingComma: 'es5',
useTabs: true,
plugins: ['./node_modules/prettier-plugin-astro'],
overrides: [
{
files: '*.astro',
options: {
parser: 'astro',
},
},
{
files: ['.*', '*.md', '*.toml'],
options: {
useTabs: false,
},
},
{
files: ['*.yaml', '*.yml', '*.json'],
options: {
tabWidth: 2,
},
},
],
};

7
.vscode/extensions.json vendored Normal file
View file

@ -0,0 +1,7 @@
{
"recommendations": [
"astro-build.astro-vscode",
"kamadorueda.alejandra",
],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

12
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,12 @@
{
"alejandra.program": "alejandra",
"[nix]": {
"editor.defaultFormatter": "kamadorueda.alejandra",
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"editor.insertSpaces": true,
"editor.tabSize": 2,
"editor.codeLens": true
},
}

18
.vscode/tasks.json vendored Normal file
View file

@ -0,0 +1,18 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "watch tests",
"type": "shell",
"command": "watch --color 'nix-build test --no-out-link | xargs cat'",
"presentation": {
"echo": false,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": false
},
"problemMatcher": []
}
]
}

17
astro.config.mjs Normal file
View file

@ -0,0 +1,17 @@
import { defineConfig } from "astro/config";
import tailwind from "@astrojs/tailwind";
import image from "@astrojs/image";
import mdx from "@astrojs/mdx";
import sitemap from "@astrojs/sitemap";
export default defineConfig({
site: "https://astroship.web3templates.com",
integrations: [
tailwind(),
image({
serviceEntryPoint: "@astrojs/image/sharp",
}),
mdx(),
sitemap(),
],
});

505
flake.lock Normal file
View file

@ -0,0 +1,505 @@
{
"nodes": {
"alejandra": {
"inputs": {
"fenix": "fenix",
"flakeCompat": "flakeCompat",
"nixpkgs": [
"d2n",
"nixpkgs"
]
},
"locked": {
"lastModified": 1658427149,
"narHash": "sha256-ToD/1z/q5VHsLMrS2h96vjJoLho59eNRtknOUd19ey8=",
"owner": "kamadorueda",
"repo": "alejandra",
"rev": "f5a22afd2adfb249b4e68e0b33aa1f0fb73fb1be",
"type": "github"
},
"original": {
"owner": "kamadorueda",
"repo": "alejandra",
"type": "github"
}
},
"crane": {
"flake": false,
"locked": {
"lastModified": 1670900067,
"narHash": "sha256-VXVa+KBfukhmWizaiGiHRVX/fuk66P8dgSFfkVN4/MY=",
"owner": "ipetkov",
"repo": "crane",
"rev": "59b31b41a589c0a65e4a1f86b0e5eac68081468b",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"d2n": {
"inputs": {
"alejandra": "alejandra",
"all-cabal-json": [
"nixpkgs"
],
"crane": "crane",
"devshell": "devshell",
"flake-parts": "flake-parts",
"flake-utils-pre-commit": "flake-utils-pre-commit",
"ghc-utils": "ghc-utils",
"gomod2nix": "gomod2nix",
"mach-nix": "mach-nix",
"nix-pypi-fetcher": "nix-pypi-fetcher",
"nixpkgs": "nixpkgs",
"poetry2nix": "poetry2nix",
"pre-commit-hooks": "pre-commit-hooks",
"pruned-racket-catalog": "pruned-racket-catalog"
},
"locked": {
"lastModified": 1676992344,
"narHash": "sha256-TEn5kEi/jL9Dt6O+ZZ7kQwnlAgEv0r4VgQZnav/cfV4=",
"owner": "nix-community",
"repo": "dream2nix",
"rev": "db72710500a80bdf4589b6807d2491a4a0dae3ad",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "dream2nix",
"type": "github"
}
},
"devshell": {
"flake": false,
"locked": {
"lastModified": 1663445644,
"narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=",
"owner": "numtide",
"repo": "devshell",
"rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"fenix": {
"inputs": {
"nixpkgs": [
"d2n",
"alejandra",
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1657607339,
"narHash": "sha256-HaqoAwlbVVZH2n4P3jN2FFPMpVuhxDy1poNOR7kzODc=",
"owner": "nix-community",
"repo": "fenix",
"rev": "b814c83d9e6aa5a28d0cf356ecfdafb2505ad37d",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"d2n",
"nixpkgs"
]
},
"locked": {
"lastModified": 1675933616,
"narHash": "sha256-/rczJkJHtx16IFxMmAWu5nNYcSXNg1YYXTHoGjLrLUA=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "47478a4a003e745402acf63be7f9a092d51b83d7",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1679737941,
"narHash": "sha256-srSD9CwsVPnUMsIZ7Kt/UegkKUEBcTyU1Rev7mO45S0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "3502ee99d6dade045bdeaf7b0cd8ec703484c25c",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils-pre-commit": {
"locked": {
"lastModified": 1644229661,
"narHash": "sha256-1YdnJAsNy69bpcjuoKdOYQX0YxZBiCYZo4Twxerqv7k=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3cecb5b042f7f209c56ffd8371b2711a290ec797",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flakeCompat": {
"flake": false,
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"ghc-utils": {
"flake": false,
"locked": {
"lastModified": 1662774800,
"narHash": "sha256-1Rd2eohGUw/s1tfvkepeYpg8kCEXiIot0RijapUjAkE=",
"ref": "refs/heads/master",
"rev": "bb3a2d3dc52ff0253fb9c2812bd7aa2da03e0fea",
"revCount": 1072,
"type": "git",
"url": "https://gitlab.haskell.org/bgamari/ghc-utils"
},
"original": {
"type": "git",
"url": "https://gitlab.haskell.org/bgamari/ghc-utils"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"pre-commit",
"nixpkgs"
]
},
"locked": {
"lastModified": 1660459072,
"narHash": "sha256-8DFJjXG8zqoONA1vXtgeKXy68KdJL5UaXR8NtVMUbx8=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "a20de23b925fd8264fd7fad6454652e142fd7f73",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"gomod2nix": {
"flake": false,
"locked": {
"lastModified": 1627572165,
"narHash": "sha256-MFpwnkvQpauj799b4QTBJQFEddbD02+Ln5k92QyHOSk=",
"owner": "tweag",
"repo": "gomod2nix",
"rev": "67f22dd738d092c6ba88e420350ada0ed4992ae8",
"type": "github"
},
"original": {
"owner": "tweag",
"repo": "gomod2nix",
"type": "github"
}
},
"mach-nix": {
"flake": false,
"locked": {
"lastModified": 1634711045,
"narHash": "sha256-m5A2Ty88NChLyFhXucECj6+AuiMZPHXNbw+9Kcs7F6Y=",
"owner": "DavHau",
"repo": "mach-nix",
"rev": "4433f74a97b94b596fa6cd9b9c0402104aceef5d",
"type": "github"
},
"original": {
"id": "mach-nix",
"type": "indirect"
}
},
"nix-filter": {
"locked": {
"lastModified": 1678109515,
"narHash": "sha256-C2X+qC80K2C1TOYZT8nabgo05Dw2HST/pSn6s+n6BO8=",
"owner": "numtide",
"repo": "nix-filter",
"rev": "aa9ff6ce4a7f19af6415fb3721eaa513ea6c763c",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "nix-filter",
"type": "github"
}
},
"nix-pypi-fetcher": {
"flake": false,
"locked": {
"lastModified": 1669065297,
"narHash": "sha256-UStjXjNIuIm7SzMOWvuYWIHBkPUKQ8Id63BMJjnIDoA=",
"owner": "DavHau",
"repo": "nix-pypi-fetcher",
"rev": "a9885ac6a091576b5195d547ac743d45a2a615ac",
"type": "github"
},
"original": {
"owner": "DavHau",
"repo": "nix-pypi-fetcher",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1665580254,
"narHash": "sha256-hO61XPkp1Hphl4HGNzj1VvDH5URt7LI6LaY/385Eul4=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f634d427b0224a5f531ea5aa10c3960ba6ec5f0f",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixos-unstable",
"type": "indirect"
}
},
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1675183161,
"narHash": "sha256-Zq8sNgAxDckpn7tJo7V1afRSk2eoVbu3OjI1QklGLNg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e1e1b192c1a5aab2960bf0a0bd53a2e8124fa18e",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-stable": {
"locked": {
"lastModified": 1673800717,
"narHash": "sha256-SFHraUqLSu5cC6IxTprex/nTsI81ZQAtDvlBvGDWfnA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2f9fd351ec37f5d479556cd48be4ca340da59b8f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1677050843,
"narHash": "sha256-3fcFxn58eCtrXrVPeW/nAg6NR5wUERVEf8zOtjPDzuM=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "9e0eed654c705c7cafe192a8eba1610217f70544",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1671271357,
"narHash": "sha256-xRJdLbWK4v2SewmSStYrcLa0YGJpleufl44A19XSW8k=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "40f79f003b6377bd2f4ed4027dde1f8f922995dd",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"poetry2nix": {
"flake": false,
"locked": {
"lastModified": 1666918719,
"narHash": "sha256-BkK42fjAku+2WgCOv2/1NrPa754eQPV7gPBmoKQBWlc=",
"owner": "nix-community",
"repo": "poetry2nix",
"rev": "289efb187123656a116b915206e66852f038720e",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "1.36.0",
"repo": "poetry2nix",
"type": "github"
}
},
"pre-commit": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"gitignore": "gitignore",
"nixpkgs": "nixpkgs_3",
"nixpkgs-stable": "nixpkgs-stable"
},
"locked": {
"lastModified": 1676879534,
"narHash": "sha256-HU4RXcwsAX1u7AUbGOBDxkYQkeODcn+HZjXqKa1y/hk=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "c9495f017f67a11e9c9909b032dc7762dfc853cf",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"pre-commit-hooks": {
"inputs": {
"flake-utils": [
"d2n",
"flake-utils-pre-commit"
],
"nixpkgs": [
"d2n",
"nixpkgs"
]
},
"locked": {
"lastModified": 1646153636,
"narHash": "sha256-AlWHMzK+xJ1mG267FdT8dCq/HvLCA6jwmx2ZUy5O8tY=",
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"rev": "b6bc0b21e1617e2b07d8205e7fae7224036dfa4b",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "pre-commit-hooks.nix",
"type": "github"
}
},
"pruned-racket-catalog": {
"flake": false,
"locked": {
"lastModified": 1672537287,
"narHash": "sha256-SuOvXVcLfakw18oJB/PuRMyvGyGG1+CQD3R+TGHIv44=",
"owner": "nix-community",
"repo": "pruned-racket-catalog",
"rev": "c8b89557fb53b36efa2ee48a769c7364df0f6262",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "catalog",
"repo": "pruned-racket-catalog",
"type": "github"
}
},
"root": {
"inputs": {
"d2n": "d2n",
"flake-parts": "flake-parts_2",
"nix-filter": "nix-filter",
"nixpkgs": "nixpkgs_2",
"pre-commit": "pre-commit"
}
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1657557289,
"narHash": "sha256-PRW+nUwuqNTRAEa83SfX+7g+g8nQ+2MMbasQ9nt6+UM=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "caf23f29144b371035b864a1017dbc32573ad56d",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

51
flake.nix Normal file
View file

@ -0,0 +1,51 @@
{
description = "nixos_hamburg - Website";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixpkgs-unstable";
d2n.url = "github:nix-community/dream2nix";
d2n.inputs.all-cabal-json.follows = "nixpkgs";
nix-filter.url = "github:numtide/nix-filter";
flake-parts.url = "github:hercules-ci/flake-parts";
pre-commit.url = "github:cachix/pre-commit-hooks.nix";
};
outputs = {
d2n,
nix-filter,
flake-parts,
pre-commit,
...
} @ inputs: let
systems = ["x86_64-linux" "aarch64-linux"];
in
flake-parts.lib.mkFlake {inherit inputs;} {
inherit systems;
imports = [d2n.flakeModuleBeta pre-commit.flakeModule ./nix/site.nix ./nix/hooks.nix];
dream2nix.config.projectRoot = ./.;
perSystem = {
self',
config,
pkgs,
system,
...
}: {
apps.serve.program = "${pkgs.writeShellScript "serve" ''
${pkgs.miniserve}/bin/miniserve -p 3001 --index index.html ${self'.packages.default}
''}";
packages.default = self'.packages.nixos_hamburg;
devShells.default = pkgs.mkShell {
packages = builtins.attrValues {
inherit (pkgs) yarn;
inherit (pkgs) alejandra nil;
};
shellHook = config.pre-commit.installationScript;
};
};
};
}

3
garnix.yaml Normal file
View file

@ -0,0 +1,3 @@
builds:
exclude:
- 'checks.*.pre-commit'

13
nix/hooks.nix Normal file
View file

@ -0,0 +1,13 @@
{self, ...}: {
perSystem = {pkgs, ...}: {
pre-commit.check.enable = true;
pre-commit.settings.hooks.nixpkgs-fmt.enable = false;
pre-commit.settings.hooks.alejandra.enable = true;
pre-commit.settings.hooks.prettier.enable = true;
pre-commit.settings.hooks.eslint.enable = true;
pre-commit.settings.hooks.eslint.pass_filenames = false;
pre-commit.settings.settings.eslint.binPath = "${pkgs.nodePackages.eslint}/bin/eslint src";
pre-commit.settings.settings.eslint.extensions = "\\.(js|ts|jsx|tsx|astro|md|mdx|cjs|ts)$";
};
}

35
nix/site.nix Normal file
View file

@ -0,0 +1,35 @@
{inputs, ...}: let
inherit (inputs.nix-filter.lib) filter inDirectory matchExt;
in {
perSystem = {config, ...}: {
dream2nix.inputs.self = {
source = filter {
root = ./..;
include = [
(inDirectory "src")
(inDirectory "public")
(matchExt "js")
(matchExt "cjs")
(matchExt "mjs")
../package.json
../yarn.lock
];
};
projects.nixos_hamburg = {
name = "nixos_hamburg";
subsystem = "nodejs";
translator = "yarn-lock";
subsystemInfo.nodejs = 18;
};
packageOverrides.nixos_hamburg.copyNixos_hamburg = {
installPhase = ''
mkdir -p $out
cp -rv ./dist/* $out
'';
};
};
packages.nixos_hamburg = config.dream2nix.outputs.self.packages.nixos_hamburg;
};
}

31
package.json Normal file
View file

@ -0,0 +1,31 @@
{
"name": "nixos.hamburg",
"type": "module",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"sync": "astro sync",
"astro": "astro"
},
"dependencies": {
"@astrojs/image": "^0.14.1",
"@astrojs/mdx": "^0.16.0",
"@astrojs/sitemap": "^1.0.1",
"@astrojs/tailwind": "^3.0.1",
"@fontsource/inter": "^4.5.15",
"astro": "^2.0.11",
"astro-feather-icons": "^1.0.2",
"astro-icon": "^0.8.0",
"astro-navbar": "^1.1.5",
"astro-seo": "^0.7.0",
"tailwindcss": "^3.2.4"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.9",
"sharp": "^0.31.3"
}
}

13
public/favicon.svg Normal file
View file

@ -0,0 +1,13 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 36 36">
<path fill="#000" d="M22.25 4h-8.5a1 1 0 0 0-.96.73l-5.54 19.4a.5.5 0 0 0 .62.62l5.05-1.44a2 2 0 0 0 1.38-1.4l3.22-11.66a.5.5 0 0 1 .96 0l3.22 11.67a2 2 0 0 0 1.38 1.39l5.05 1.44a.5.5 0 0 0 .62-.62l-5.54-19.4a1 1 0 0 0-.96-.73Z"/>
<path fill="url(#gradient)" d="M18 28a7.63 7.63 0 0 1-5-2c-1.4 2.1-.35 4.35.6 5.55.14.17.41.07.47-.15.44-1.8 2.93-1.22 2.93.6 0 2.28.87 3.4 1.72 3.81.34.16.59-.2.49-.56-.31-1.05-.29-2.46 1.29-3.25 3-1.5 3.17-4.83 2.5-6-.67.67-2.6 2-5 2Z"/>
<defs>
<linearGradient id="gradient" x1="16" x2="16" y1="32" y2="24" gradientUnits="userSpaceOnUse">
<stop stop-color="#000"/>
<stop offset="1" stop-color="#000" stop-opacity="0"/>
</linearGradient>
</defs>
<style>
@media (prefers-color-scheme:dark){:root{filter:invert(100%)}}
</style>
</svg>

After

Width:  |  Height:  |  Size: 873 B

BIN
public/opengraph.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

4
public/robots.txt Normal file
View file

@ -0,0 +1,4 @@
User-agent: *
Allow: /
Sitemap: http://astroship.web3templates.com/sitemap-index.xml

8
renovate.json Normal file
View file

@ -0,0 +1,8 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
"assignees": ["Nobbz"],
"rangeStrategy": "update-lockfile",
"schedule": ["* 0-5 * * *"],
"nix": { "enabled": true }
}

BIN
src/assets/hero-alt.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 33 KiB

BIN
src/assets/hero.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

View file

@ -0,0 +1,127 @@
---
import Button from "./ui/button.astro";
---
<!-- To make this contact form work, create your free access key from https://web3forms.com/
Then you will get all form submissions in your email inbox. -->
<form
action="https://api.web3forms.com/submit"
method="POST"
id="form"
class="needs-validation"
novalidate>
<input type="hidden" name="access_key" value="YOUR_ACCESS_KEY_HERE" />
<!-- Create your free access key from https://web3forms.com/ -->
<input type="checkbox" class="hidden" style="display:none" name="botcheck" />
<div class="mb-5">
<input
type="text"
placeholder="Full Name"
required
class="w-full px-4 py-3 border-2 placeholder:text-gray-800 rounded-md outline-none focus:ring-4 border-gray-300 focus:border-gray-600 ring-gray-100"
name="name"
/>
<div class="empty-feedback invalid-feedback text-red-400 text-sm mt-1">
Please provide your full name.
</div>
</div>
<div class="mb-5">
<label for="email_address" class="sr-only">Email Address</label><input
id="email_address"
type="email"
placeholder="Email Address"
name="email"
required
class="w-full px-4 py-3 border-2 placeholder:text-gray-800 rounded-md outline-none focus:ring-4 border-gray-300 focus:border-gray-600 ring-gray-100"
/>
<div class="empty-feedback text-red-400 text-sm mt-1">
Please provide your email address.
</div>
<div class="invalid-feedback text-red-400 text-sm mt-1">
Please provide a valid email address.
</div>
</div>
<div class="mb-3">
<textarea
name="message"
required
placeholder="Your Message"
class="w-full px-4 py-3 border-2 placeholder:text-gray-800 rounded-md outline-none h-36 focus:ring-4 border-gray-300 focus:border-gray-600 ring-gray-100"
></textarea>
<div class="empty-feedback invalid-feedback text-red-400 text-sm mt-1">
Please enter your message.
</div>
</div>
<Button type="submit" size="lg" block>Send Message</Button>
<div id="result" class="mt-3 text-center"></div>
</form>
<style>
.invalid-feedback,
.empty-feedback {
display: none;
}
.was-validated :placeholder-shown:invalid ~ .empty-feedback {
display: block;
}
.was-validated :not(:placeholder-shown):invalid ~ .invalid-feedback {
display: block;
}
.is-invalid,
.was-validated :invalid {
border-color: #dc3545;
}
</style>
<script is:inline>
const form = document.getElementById("form");
const result = document.getElementById("result");
form.addEventListener("submit", function (e) {
e.preventDefault();
form.classList.add("was-validated");
if (!form.checkValidity()) {
form.querySelectorAll(":invalid")[0].focus();
return;
}
const formData = new FormData(form);
const object = Object.fromEntries(formData);
const json = JSON.stringify(object);
result.innerHTML = "Sending...";
fetch("https://api.web3forms.com/submit", {
method: "POST",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
body: json,
})
.then(async (response) => {
let json = await response.json();
if (response.status == 200) {
result.classList.add("text-green-500");
result.innerHTML = json.message;
} else {
console.log(response);
result.classList.add("text-red-500");
result.innerHTML = json.message;
}
})
.catch((error) => {
console.log(error);
result.innerHTML = "Something went wrong!";
})
.then(function () {
form.reset();
form.classList.remove("was-validated");
setTimeout(() => {
result.style.display = "none";
}, 5000);
});
});
</script>

View file

@ -0,0 +1,7 @@
---
const { class: className } = Astro.props;
---
<div class:list={["max-w-screen-xl mx-auto px-5", className]}>
<slot />
</div>

17
src/components/cta.astro Normal file
View file

@ -0,0 +1,17 @@
---
import Link from "./ui/link.astro";
---
<div
class="bg-black p-8 md:px-20 md:py-20 mt-20 mx-auto max-w-5xl rounded-lg flex flex-col items-center text-center">
<h2 class="text-white text-4xl md:text-6xl tracking-tight">
Build faster websites.
</h2>
<p class="text-slate-400 mt-4 text-lg md:text-xl">
Pull content from anywhere and serve it fast with Astro's next-gen island
architecture.
</p>
<div class="flex mt-5">
<Link href="#" style="inverted">Get Started</Link>
</div>
</div>

View file

@ -0,0 +1,69 @@
---
// @ts-ignore
import { Icon } from "astro-icon";
const features = [
{
title: "Bring Your Own Framework",
description:
"Build your site using React, Svelte, Vue, Preact, web components, or just plain ol' HTML + JavaScript.",
icon: "bx:bxs-briefcase",
},
{
title: "100% Static HTML, No JS",
description:
"Astro renders your entire page to static HTML, removing all JavaScript from your final build by default.",
icon: "bx:bxs-window-alt",
},
{
title: "On-Demand Components",
description:
"Need some JS? Astro can automatically hydrate interactive components when they become visible on the page. ",
icon: "bx:bxs-data",
},
{
title: "Broad Integration",
description:
"Astro supports TypeScript, Scoped CSS, CSS Modules, Sass, Tailwind, Markdown, MDX, and any other npm packages.",
icon: "bx:bxs-bot",
},
{
title: "SEO Enabled",
description:
"Automatic sitemaps, RSS feeds, pagination and collections take the pain out of SEO and syndication. It just works!",
icon: "bx:bxs-file-find",
},
{
title: "Community",
description:
"Astro is an open source project powered by hundreds of contributors making thousands of individual contributions.",
icon: "bx:bxs-user",
},
];
---
<div class="mt-16 md:mt-0">
<h2 class="text-4xl lg:text-5xl font-bold lg:tracking-tight">
Everything you need to start a website
</h2>
<p class="text-lg mt-4 text-slate-600">
Astro comes batteries included. It takes the best parts of state-of-the-art
tools and adds its own innovations.
</p>
</div>
<div class="grid sm:grid-cols-2 md:grid-cols-3 mt-16 gap-16">
{
features.map((item) => (
<div class="flex gap-4 items-start">
<div class="mt-1 bg-black rounded-full p-2 w-8 h-8 shrink-0">
<Icon class="text-white" name={item.icon} />
</div>
<div>
<h3 class="font-semibold text-lg">{item.title}</h3>{" "}
<p class="text-slate-500 mt-2 leading-relaxed">{item.description}</p>
</div>
</div>
))
}
</div>

View file

@ -0,0 +1,19 @@
<footer class="my-20">
<p class="text-center text-sm text-slate-500">
Copyright © {new Date().getFullYear()} Astroship. All rights reserved.
</p>
<!--
Can we ask you a favor 🙏
Please keep this backlink on your website if possible.
or Purchase a commercial license from https://web3templates.com
-->
<p class="text-center text-xs text-slate-500 mt-1">
Made by <a
href="https://web3templates.com"
target="_blank"
rel="noopener"
class="hover:underline">
Web3Templates
</a>
</p>
</footer>

54
src/components/hero.astro Normal file
View file

@ -0,0 +1,54 @@
---
import { Picture } from "@astrojs/image/components";
import heroImage from "assets/hero.png";
import Link from "@components/ui/link.astro";
import { Icon } from "astro-icon";
---
<main
class="grid lg:grid-cols-2 place-items-center pt-16 pb-8 md:pt-12 md:pb-24">
<div class="py-6 md:order-1 hidden md:block">
<Picture
src={heroImage}
alt="Astronaut in the air"
widths={[200, 400, 600]}
aspectRatio="4:3"
sizes="(max-width: 800px) 100vw, 620px"
loading="eager"
format="avif"
/>
</div>
<div>
<h1
class="text-5xl lg:text-6xl xl:text-7xl font-bold lg:tracking-tight xl:tracking-tighter">
Marketing website done with Astro
</h1>
<p class="text-lg mt-4 text-slate-600 max-w-xl">
Astroship is a starter template for startups, marketing websites & landing
pages.<wbr /> Built with Astro.build and TailwindCSS. You can quickly create
any website with this starter.
</p>
<div class="mt-6 flex flex-col sm:flex-row gap-3">
<Link
href="#"
href="https://web3templates.com/templates/astroship-starter-website-template-for-astro"
target="_blank"
class="flex gap-1 items-center justify-center"
rel="noopener">
<Icon class="text-white w-5 h-5" name="bx:bxs-cloud-download" />
Download for Free
</Link>
<Link
size="lg"
style="outline"
rel="noopener"
href="https://github.com/surjithctly/astroship"
class="flex gap-1 items-center justify-center"
target="_blank">
<Icon class="text-black w-4 h-4" name="bx:bxl-github" />
GitHub Repo
</Link>
</div>
</div>
</main>

View file

@ -0,0 +1,16 @@
---
// @ts-ignore
import { Icon } from "astro-icon";
---
<div class="mt-24">
<h2 class="text-center text-slate-500">Works with your technologies</h2>
<div class="flex gap-8 md:gap-20 items-center justify-center mt-10 flex-wrap">
<Icon class="h-8 md:h-12" name="simple-icons:react" />
<Icon class="h-8 md:h-12" name="simple-icons:svelte" />
<Icon class="h-8 md:h-14" name="simple-icons:tailwindcss" />
<Icon class="h-8 md:h-16" name="simple-icons:alpinedotjs" />
<Icon class="h-8 md:h-12" name="simple-icons:vercel" />
<Icon class="h-8 md:h-12" name="simple-icons:astro" />
</div>
</div>

View file

@ -0,0 +1,47 @@
---
import { Dropdown, DropdownItems } from "astro-navbar";
const { title, lastItem, children } = Astro.props;
---
<li class="relative">
<Dropdown class="group">
<button
class="flex items-center gap-1 w-full lg:w-auto lg:px-3 py-2 text-gray-600 hover:text-gray-900">
<span>{title}</span>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width="3"
stroke="currentColor"
class="w-3 h-3 mt-0.5 group-open:rotate-180">
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M19.5 8.25l-7.5 7.5-7.5-7.5"></path>
</svg>
</button>
<DropdownItems>
<div
class:list={[
"lg:absolute w-full lg:w-48 z-10",
lastItem
? "lg:right-0 origin-top-right"
: "lg:left-0 origin-top-left",
]}>
<div
class="px-3 lg:py-2 lg:bg-white lg:rounded-md lg:shadow lg:border flex flex-col">
{
children.map((item) => (
<a
href={item.path}
class="py-1 text-gray-600 hover:text-gray-900">
{item.title}
</a>
))
}
</div>
</div>
</DropdownItems>
</Dropdown>
</li>

View file

@ -0,0 +1,88 @@
---
import Container from "@components/container.astro";
import Link from "@components/ui/link.astro";
import Dropdown from "./dropdown.astro";
import { Astronav, MenuItems, MenuIcon } from "astro-navbar";
const menuitems = [
{
title: "Features",
path: "#",
children: [
{ title: "Action", path: "#" },
{ title: "Another action", path: "#" },
{ title: "Dropdown Submenu", path: "#" },
],
},
{
title: "Pricing",
path: "/pricing",
},
{
title: "About",
path: "/about",
},
{
title: "Blog",
path: "/blog",
},
{
title: "Contact",
path: "/contact",
},
];
---
<Container>
<header class="flex flex-col lg:flex-row justify-between items-center my-5">
<Astronav>
<div class="flex w-full lg:w-auto items-center justify-between">
<a href="/" class="text-lg"
><span class="font-bold text-slate-800">Astro</span><span
class="text-slate-500">ship</span
>
</a>
<div class="block lg:hidden">
<MenuIcon class="w-4 h-4 text-gray-800" />
</div>
</div>
<MenuItems class="hidden w-full lg:w-auto mt-2 lg:flex lg:mt-0">
<ul class="flex flex-col lg:flex-row lg:gap-3">
{
menuitems.map((item, index) => (
<>
{item.children && (
<Dropdown
title={item.title}
children={item.children}
lastItem={index === menuitems.length - 1}
/>
)}
{!item.children && (
<li>
<a
href={item.path}
class="flex lg:px-3 py-2 text-gray-600 hover:text-gray-900">
{item.title}
</a>
</li>
)}
</>
))
}
</ul>
<div class="lg:hidden flex items-center mt-3 gap-4">
<Link href="#" style="muted" block size="md">Log in</Link>
<Link href="#" size="md" block>Sign up</Link>
</div>
</MenuItems>
</Astronav>
<div>
<div class="hidden lg:flex items-center gap-4">
<a href="#">Log in</a>
<Link href="#" size="md">Sign up</Link>
</div>
</div>
</header>
</Container>

View file

@ -0,0 +1,45 @@
---
import { Tick } from "@components/ui/icons";
import Link from "@components/ui/link.astro";
const { plan } = Astro.props;
---
<div>
<div
class="flex flex-col w-full order-first lg:order-none border-2 border-[#D8DEE9] border-opacity-50 py-5 px-6 rounded-md">
<div class="text-center">
<h4 class="text-lg font-medium text-gray-400">{plan.name}</h4><p
class="mt-3 text-4xl font-bold text-black md:text-4xl">
{
plan.price && typeof plan.price === "object"
? plan.price.monthly
: plan.price
}
</p>
<!-- {
plan.price.original && (
<p class="mt-1 text-xl font-medium text-gray-400 line-through md:text-2xl">
{plan.price.original}
</p>
)
} -->
</div><ul class="grid mt-8 text-left gap-y-4">
{
plan.features.map((item) => (
<li class="flex items-start gap-3 text-gray-800">
<Tick class="w-6 h-6" />
<span>{item}</span>
</li>
))
}
</ul><div class="flex mt-8">
<Link
href={plan.button.link || "#"}
block
style={plan.popular ? "primary" : "outline"}>
{plan.button.text || "Get Started"}
</Link>
</div>
</div>
</div>

View file

@ -0,0 +1,12 @@
---
const { align = "center" } = Astro.props;
---
<div class:list={["mt-16", align === "center" && "text-center"]}>
<h1 class="text-4xl lg:text-5xl font-bold lg:tracking-tight">
<slot name="title">Title</slot>
</h1>
<p class="text-lg mt-4 text-slate-600">
<slot name="desc">Some description goes here</slot>
</p>
</div>

View file

@ -0,0 +1,40 @@
---
interface Props {
size?: "md" | "lg";
block?: boolean;
style?: "outline" | "primary" | "inverted";
class?: string;
[x: string]: any;
}
const {
size = "md",
style = "primary",
block,
class: className,
...rest
} = Astro.props;
const sizes = {
md: "px-5 py-2.5",
lg: "px-6 py-3",
};
const styles = {
outline: "border-2 border-black hover:bg-black text-black hover:text-white",
primary:
"bg-black text-white hover:bg-slate-900 border-2 border-transparent",
};
---
<button
{...rest}
class:list={[
"rounded text-center transition focus-visible:ring-2 ring-offset-2 ring-gray-200",
block && "w-full",
sizes[size],
styles[style],
className,
]}
><slot />
</button>

View file

@ -0,0 +1 @@
export { default as Tick } from "./tick.astro";

View file

@ -0,0 +1,16 @@
---
const { class: className } = Astro.props;
---
<svg
class={className}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
><circle cx="12" cy="12" r="9" fill="currentColor" fill-opacity=".16"
></circle><path
fill-rule="evenodd"
clip-rule="evenodd"
d="M3.75 12a8.25 8.25 0 0 1 11.916-7.393.75.75 0 1 0 .668-1.343A9.713 9.713 0 0 0 12 2.25c-5.385 0-9.75 4.365-9.75 9.75s4.365 9.75 9.75 9.75 9.75-4.365 9.75-9.75c0-.366-.02-.727-.06-1.082a.75.75 0 1 0-1.49.164A8.25 8.25 0 1 1 3.75 12Zm17.78-6.47a.75.75 0 0 0-1.06-1.06L12 12.94l-2.47-2.47a.75.75 0 0 0-1.06 1.06l3 3a.75.75 0 0 0 1.06 0l9-9Z"
fill="currentColor"></path>
</svg>

View file

@ -0,0 +1,44 @@
---
interface Props {
href: string;
size?: "md" | "lg";
block?: boolean;
style?: "outline" | "primary" | "inverted" | "muted";
class?: string;
[x: string]: any;
}
const {
href,
block,
size = "lg",
style = "primary",
class: className,
...rest
} = Astro.props;
const sizes = {
lg: "px-5 py-2.5",
md: "px-4 py-2",
};
const styles = {
outline: "bg-white border-2 border-black hover:bg-gray-100 text-black ",
primary: "bg-black text-white hover:bg-gray-800 border-2 border-transparent",
inverted: "bg-white text-black border-2 border-transparent",
muted: "bg-gray-100 hover:bg-gray-200 border-2 border-transparent",
};
---
<a
href={href}
{...rest}
class:list={[
"rounded text-center transition focus-visible:ring-2 ring-offset-2 ring-gray-200",
block && "w-full",
sizes[size],
styles[style],
className,
]}
><slot />
</a>

View file

@ -0,0 +1,37 @@
---
draft: false
title: "The Complete Guide to Full Stack Web Development"
snippet: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti."
image: {
src: "https://images.unsplash.com/photo-1593720213428-28a5b9e94613?&fit=crop&w=430&h=240",
alt: "full stack web development"
}
publishDate: "2022-11-08 11:39"
category: "Tutorials"
author: "Janette Lynch"
tags: [webdev, tailwindcss, frontend]
---
Lorem ipsum dolor sit amet consectetur adipiscing elit euismod rutrum, consequat fringilla ultricies nullam curae mollis semper conubia viverra, orci aenean dapibus pharetra nec tortor tellus cubilia. Ullamcorper mi lectus eu malesuada tempor massa praesent magna mattis posuere, lobortis vulputate ut duis magnis parturient habitant nibh id tristique, quis suspendisse donec nisl penatibus sem non feugiat taciti. Mollis per ridiculus integer cursus semper vestibulum fermentum penatibus cubilia blandit scelerisque, tempus platea leo posuere ac pharetra volutpat aliquet euismod id ullamcorper lobortis, urna est magna mus rhoncus massa curae libero praesent eget. Mattis malesuada vestibulum quis ac nam phasellus suscipit facilisis libero diam posuere, cursus massa vehicula neque imperdiet tincidunt dui egestas lacinia mollis aliquet orci, nisl curabitur dapibus litora dis cum nostra montes ligula praesent. Facilisi aliquam convallis molestie tempor blandit ultricies bibendum parturient cubilia quam, porttitor morbi torquent tempus taciti nec faucibus elementum phasellus, quis inceptos vestibulum gravida augue potenti eget nunc maecenas. Tempor facilisis ligula volutpat habitant consequat inceptos orci per potenti blandit platea, mus sapien eget vel libero vestibulum augue cubilia ut ultrices fringilla lectus, imperdiet pellentesque cum ridiculus convallis sollicitudin nisl interdum semper felis.
Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti augue nulla vivamus senectus odio, quisque curabitur enim consequat class sociis feugiat ullamcorper, felis dis imperdiet cubilia commodo sed massa phasellus. Viverra purus mus nisi condimentum dui vehicula facilisis turpis, habitant nascetur lectus tempor quisque habitasse urna scelerisque, nibh nullam vestibulum luctus aenean mollis metus. Suscipit gravida duis nec aliquet natoque molestie a ridiculus scelerisque cum, justo cursus sapien sodales purus dignissim vel facilisi magnis, inceptos rutrum ut integer auctor commodo sollicitudin fames et. Faucibus ligula nibh sagittis mauris auctor posuere habitant, scelerisque phasellus accumsan egestas gravida viverra nam, sed etiam eleifend proin massa dictumst. Porttitor risus luctus per aenean tellus primis fringilla vitae fames lacinia mauris metus, nec pulvinar quisque commodo sodales ac nibh natoque phasellus semper placerat. Lectus aenean potenti leo sollicitudin tristique eros quam ligula, vestibulum diam consequat enim torquent nec tempus, blandit viverra dapibus eleifend dis nunc nascetur.
## Sodales hendrerit malesuada et vestibulum
- Luctus euismod pretium nisi et, est dui enim.
- Curae eget inceptos malesuada, fermentum class.
- Porttitor vestibulum aliquam porta feugiat velit, potenti eu placerat.
- Ligula lacus tempus ac porta, vel litora.
Torquent non nisi lacinia faucibus nibh tortor taciti commodo porttitor, mus hendrerit id leo scelerisque mollis habitasse orci tristique aptent, lacus at molestie cubilia facilisis porta accumsan condimentum. Metus lacus suscipit porttitor integer facilisi torquent, nostra nulla platea at natoque varius venenatis, id quam pharetra aliquam leo. Dictum orci himenaeos quam mi fusce lacinia maecenas ac magna eleifend laoreet, vivamus enim curabitur ullamcorper est ultrices convallis suscipit nascetur. Ornare fames pretium ante ac eget nisi tellus vivamus, convallis mauris sapien imperdiet sollicitudin aliquet taciti quam, lacinia tempor primis magna iaculis at eu. Est facilisi proin risus eleifend orci torquent ultricies platea, quisque nullam vel porttitor euismod sociis non, maecenas sociosqu interdum arcu sed pharetra potenti. Aliquet risus tempus hendrerit sapien tellus eget cursus enim etiam dui, lobortis nostra pellentesque odio posuere morbi ad neque senectus arcu eu, turpis proin ac felis purus fames magnis dis dignissim.
Orci volutpat augue viverra scelerisque dictumst ut condimentum vivamus, accumsan cum sem sollicitudin aliquet vehicula porta pretium placerat, malesuada euismod primis cubilia rutrum tempus parturient. Urna mauris in nibh morbi hendrerit vulputate condimentum, iaculis consequat porttitor dui dis euismod eros, arcu elementum venenatis varius lectus nisi. Nibh arcu ultrices semper morbi quam aptent quisque porta posuere iaculis, vestibulum cum vitae primis varius natoque conubia eu. Placerat sociis sagittis sociosqu morbi purus lobortis convallis, bibendum tortor ridiculus orci habitasse viverra dictum, quis rutrum fusce potenti volutpat vehicula. Curae porta inceptos lectus mus urna litora semper aliquam libero rutrum sem dui maecenas ligula quis, eget risus non imperdiet cum morbi magnis suspendisse etiam augue porttitor placerat facilisi hendrerit. Et eleifend eget augue duis fringilla sagittis erat est habitasse commodo tristique quisque pretium, suspendisse imperdiet inceptos mollis blandit magna mus elementum molestie sed vestibulum. Euismod morbi hendrerit suscipit felis ornare libero ligula, mus tortor urna interdum blandit nisi netus posuere, purus fermentum magnis nam primis nulla.
## Elementum nisi urna cursus nisl quam ante tristique blandit ultricies eget
Netus at rutrum taciti vestibulum molestie conubia semper class potenti lobortis, hendrerit donec vitae ad libero natoque parturient litora congue. Torquent rhoncus odio cursus iaculis molestie arcu leo condimentum accumsan, laoreet congue duis libero justo tortor commodo fusce, massa eros hac euismod netus sodales mi magnis. Aenean nullam sollicitudin ad velit nulla venenatis suspendisse iaculis, aliquet senectus mollis aptent fringilla volutpat nascetur, nec urna vehicula lacinia neque augue orci. Suspendisse et eleifend convallis sollicitudin posuere diam turpis gravida congue ultrices, laoreet ultricies dapibus proin facilisis magna class praesent fusce. Mus morbi magnis ultricies sed turpis ultrices tempus tortor bibendum, netus nulla viverra torquent malesuada ridiculus tempor. Parturient sociosqu erat ullamcorper gravida natoque varius, etiam habitant augue praesent per curabitur iaculis, donec pellentesque cursus suscipit aliquet. Congue curae cursus scelerisque pellentesque quis fusce arcu eros dictumst luctus ridiculus nisl viverra, turpis class faucibus phasellus feugiat eleifend fringilla orci tristique habitasse conubia quam. Habitasse montes congue sodales rutrum cras torquent cursus auctor condimentum imperdiet egestas nascetur, platea tincidunt ut sollicitudin purus libero lobortis ad nisi diam quam.
Suspendisse et eleifend convallis sollicitudin posuere diam turpis gravida congue ultrices, laoreet ultricies dapibus proin facilisis magna class praesent fusce. Mus morbi magnis ultricies sed turpis ultrices tempus tortor bibendum, netus nulla viverra torquent malesuada ridiculus tempor. Parturient sociosqu erat ullamcorper gravida natoque varius, etiam habitant augue praesent per curabitur iaculis, donec pellentesque cursus suscipit aliquet. Congue curae cursus scelerisque pellentesque quis fusce arcu eros dictumst luctus ridiculus nisl viverra, turpis class faucibus phasellus feugiat eleifend fringilla orci tristique habitasse conubia quam. Habitasse montes congue sodales rutrum cras torquent cursus auctor condimentum imperdiet egestas nascetur.

View file

@ -0,0 +1,37 @@
---
draft: false
title: " Introduction to the Essential Data Structures & Algorithms"
snippet: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti."
image: {
src: "https://images.unsplash.com/photo-1627163439134-7a8c47e08208?&fit=crop&w=430&h=240",
alt: "data structures & algorithms"
}
publishDate: "2022-11-09 16:39"
category: "Courses"
author: "Marcell Ziemann"
tags: [webdev, tailwindcss, frontend]
---
Lorem ipsum dolor sit amet consectetur adipiscing elit euismod rutrum, consequat fringilla ultricies nullam curae mollis semper conubia viverra, orci aenean dapibus pharetra nec tortor tellus cubilia. Ullamcorper mi lectus eu malesuada tempor massa praesent magna mattis posuere, lobortis vulputate ut duis magnis parturient habitant nibh id tristique, quis suspendisse donec nisl penatibus sem non feugiat taciti. Mollis per ridiculus integer cursus semper vestibulum fermentum penatibus cubilia blandit scelerisque, tempus platea leo posuere ac pharetra volutpat aliquet euismod id ullamcorper lobortis, urna est magna mus rhoncus massa curae libero praesent eget. Mattis malesuada vestibulum quis ac nam phasellus suscipit facilisis libero diam posuere, cursus massa vehicula neque imperdiet tincidunt dui egestas lacinia mollis aliquet orci, nisl curabitur dapibus litora dis cum nostra montes ligula praesent. Facilisi aliquam convallis molestie tempor blandit ultricies bibendum parturient cubilia quam, porttitor morbi torquent tempus taciti nec faucibus elementum phasellus, quis inceptos vestibulum gravida augue potenti eget nunc maecenas. Tempor facilisis ligula volutpat habitant consequat inceptos orci per potenti blandit platea, mus sapien eget vel libero vestibulum augue cubilia ut ultrices fringilla lectus, imperdiet pellentesque cum ridiculus convallis sollicitudin nisl interdum semper felis.
Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti augue nulla vivamus senectus odio, quisque curabitur enim consequat class sociis feugiat ullamcorper, felis dis imperdiet cubilia commodo sed massa phasellus. Viverra purus mus nisi condimentum dui vehicula facilisis turpis, habitant nascetur lectus tempor quisque habitasse urna scelerisque, nibh nullam vestibulum luctus aenean mollis metus. Suscipit gravida duis nec aliquet natoque molestie a ridiculus scelerisque cum, justo cursus sapien sodales purus dignissim vel facilisi magnis, inceptos rutrum ut integer auctor commodo sollicitudin fames et. Faucibus ligula nibh sagittis mauris auctor posuere habitant, scelerisque phasellus accumsan egestas gravida viverra nam, sed etiam eleifend proin massa dictumst. Porttitor risus luctus per aenean tellus primis fringilla vitae fames lacinia mauris metus, nec pulvinar quisque commodo sodales ac nibh natoque phasellus semper placerat. Lectus aenean potenti leo sollicitudin tristique eros quam ligula, vestibulum diam consequat enim torquent nec tempus, blandit viverra dapibus eleifend dis nunc nascetur.
## Sodales hendrerit malesuada et vestibulum
- Luctus euismod pretium nisi et, est dui enim.
- Curae eget inceptos malesuada, fermentum class.
- Porttitor vestibulum aliquam porta feugiat velit, potenti eu placerat.
- Ligula lacus tempus ac porta, vel litora.
Torquent non nisi lacinia faucibus nibh tortor taciti commodo porttitor, mus hendrerit id leo scelerisque mollis habitasse orci tristique aptent, lacus at molestie cubilia facilisis porta accumsan condimentum. Metus lacus suscipit porttitor integer facilisi torquent, nostra nulla platea at natoque varius venenatis, id quam pharetra aliquam leo. Dictum orci himenaeos quam mi fusce lacinia maecenas ac magna eleifend laoreet, vivamus enim curabitur ullamcorper est ultrices convallis suscipit nascetur. Ornare fames pretium ante ac eget nisi tellus vivamus, convallis mauris sapien imperdiet sollicitudin aliquet taciti quam, lacinia tempor primis magna iaculis at eu. Est facilisi proin risus eleifend orci torquent ultricies platea, quisque nullam vel porttitor euismod sociis non, maecenas sociosqu interdum arcu sed pharetra potenti. Aliquet risus tempus hendrerit sapien tellus eget cursus enim etiam dui, lobortis nostra pellentesque odio posuere morbi ad neque senectus arcu eu, turpis proin ac felis purus fames magnis dis dignissim.
Orci volutpat augue viverra scelerisque dictumst ut condimentum vivamus, accumsan cum sem sollicitudin aliquet vehicula porta pretium placerat, malesuada euismod primis cubilia rutrum tempus parturient. Urna mauris in nibh morbi hendrerit vulputate condimentum, iaculis consequat porttitor dui dis euismod eros, arcu elementum venenatis varius lectus nisi. Nibh arcu ultrices semper morbi quam aptent quisque porta posuere iaculis, vestibulum cum vitae primis varius natoque conubia eu. Placerat sociis sagittis sociosqu morbi purus lobortis convallis, bibendum tortor ridiculus orci habitasse viverra dictum, quis rutrum fusce potenti volutpat vehicula. Curae porta inceptos lectus mus urna litora semper aliquam libero rutrum sem dui maecenas ligula quis, eget risus non imperdiet cum morbi magnis suspendisse etiam augue porttitor placerat facilisi hendrerit. Et eleifend eget augue duis fringilla sagittis erat est habitasse commodo tristique quisque pretium, suspendisse imperdiet inceptos mollis blandit magna mus elementum molestie sed vestibulum. Euismod morbi hendrerit suscipit felis ornare libero ligula, mus tortor urna interdum blandit nisi netus posuere, purus fermentum magnis nam primis nulla.
## Elementum nisi urna cursus nisl quam ante tristique blandit ultricies eget
Netus at rutrum taciti vestibulum molestie conubia semper class potenti lobortis, hendrerit donec vitae ad libero natoque parturient litora congue. Torquent rhoncus odio cursus iaculis molestie arcu leo condimentum accumsan, laoreet congue duis libero justo tortor commodo fusce, massa eros hac euismod netus sodales mi magnis. Aenean nullam sollicitudin ad velit nulla venenatis suspendisse iaculis, aliquet senectus mollis aptent fringilla volutpat nascetur, nec urna vehicula lacinia neque augue orci. Suspendisse et eleifend convallis sollicitudin posuere diam turpis gravida congue ultrices, laoreet ultricies dapibus proin facilisis magna class praesent fusce. Mus morbi magnis ultricies sed turpis ultrices tempus tortor bibendum, netus nulla viverra torquent malesuada ridiculus tempor. Parturient sociosqu erat ullamcorper gravida natoque varius, etiam habitant augue praesent per curabitur iaculis, donec pellentesque cursus suscipit aliquet. Congue curae cursus scelerisque pellentesque quis fusce arcu eros dictumst luctus ridiculus nisl viverra, turpis class faucibus phasellus feugiat eleifend fringilla orci tristique habitasse conubia quam. Habitasse montes congue sodales rutrum cras torquent cursus auctor condimentum imperdiet egestas nascetur, platea tincidunt ut sollicitudin purus libero lobortis ad nisi diam quam.
Suspendisse et eleifend convallis sollicitudin posuere diam turpis gravida congue ultrices, laoreet ultricies dapibus proin facilisis magna class praesent fusce. Mus morbi magnis ultricies sed turpis ultrices tempus tortor bibendum, netus nulla viverra torquent malesuada ridiculus tempor. Parturient sociosqu erat ullamcorper gravida natoque varius, etiam habitant augue praesent per curabitur iaculis, donec pellentesque cursus suscipit aliquet. Congue curae cursus scelerisque pellentesque quis fusce arcu eros dictumst luctus ridiculus nisl viverra, turpis class faucibus phasellus feugiat eleifend fringilla orci tristique habitasse conubia quam. Habitasse montes congue sodales rutrum cras torquent cursus auctor condimentum imperdiet egestas nascetur.

View file

@ -0,0 +1,44 @@
---
draft: false
title: "How to become a Frontend Master"
snippet: "Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti."
image: {
src: "https://images.unsplash.com/photo-1667372393119-3d4c48d07fc9?&fit=crop&w=430&h=240",
alt: "frontend master"
}
publishDate: "2022-11-07 15:39"
category: "Tutorials"
author: "Connor Lopez"
tags: [astro, tailwindcss, frontend]
---
Whatever you do, it's always beneficial to have the right tools at your disposal. I love working remotely and am a big advocate of doing remote software development. Therefore, I always strive to have the best equipment available to be as productive as possible. Writing posts like this constantly takes a lot of time. Luckily iVanky helped me out and sponsored this post so that I can concentrate on writing. I recently had the chance to test out one of their hottest products, a dual USB-C Docking Station that allows me to connect both my wide-screen monitors to my MacBook with Dual 4K@60Hz display connectivity. It also supports up to 96W laptop charging, which is awesome. If you are in a situation like me and want to upgrade your equipment, check out this and their other products! And now comes the article:
Whether you are new to programming or already an experienced developer. In this industry, learning new concepts and languages/frameworks is
mandatory to keep up with the rapid changes. Take for example React - open-sourced by Facebook just a shy 4 years ago it already became the number one choice for JavaScript devs around the globe. But also Vue and Angular, of course, have their legitimate follower-base. And then there is Svelte, and universal frameworks like Next.js or Nuxt.js, and Gatsby, and Gridsome, and Quasar, and and and. If you want to shine as an expert JavaScript developer you should at least have some experience in different frameworks and libraries - besides doing your homework with good, old JS.
To help you become Frontend Masters, I have collected 9 different projects, each with a distinct topic and a different JavaScript framework or library as a tech stack that you can build and add to your portfolio. Remember, nothing helps you more than actually building stuff so go ahead, sharpen your mind and make this happen!
## Dictum integer fusce ac ridiculus
Lorem ipsum dolor sit amet consectetur adipiscing elit euismod rutrum, consequat fringilla ultricies nullam curae mollis semper conubia viverra, orci aenean dapibus pharetra nec tortor tellus cubilia. Ullamcorper mi lectus eu malesuada tempor massa praesent magna mattis posuere, lobortis vulputate ut duis magnis parturient habitant nibh id tristique, quis suspendisse donec nisl penatibus sem non feugiat taciti. Mollis per ridiculus integer cursus semper vestibulum fermentum penatibus cubilia blandit scelerisque, tempus platea leo posuere ac pharetra volutpat aliquet euismod id ullamcorper lobortis, urna est magna mus rhoncus massa curae libero praesent eget. Mattis malesuada vestibulum quis ac nam phasellus suscipit facilisis libero diam posuere, cursus massa vehicula neque imperdiet tincidunt dui egestas lacinia mollis aliquet orci, nisl curabitur dapibus litora dis cum nostra montes ligula praesent. Facilisi aliquam convallis molestie tempor blandit ultricies bibendum parturient cubilia quam, porttitor morbi torquent tempus taciti nec faucibus elementum phasellus, quis inceptos vestibulum gravida augue potenti eget nunc maecenas. Tempor facilisis ligula volutpat habitant consequat inceptos orci per potenti blandit platea, mus sapien eget vel libero vestibulum augue cubilia ut ultrices fringilla lectus, imperdiet pellentesque cum ridiculus convallis sollicitudin nisl interdum semper felis.
Ornare cum cursus laoreet sagittis nunc fusce posuere per euismod dis vehicula a, semper fames lacus maecenas dictumst pulvinar neque enim non potenti. Torquent hac sociosqu eleifend potenti augue nulla vivamus senectus odio, quisque curabitur enim consequat class sociis feugiat ullamcorper, felis dis imperdiet cubilia commodo sed massa phasellus. Viverra purus mus nisi condimentum dui vehicula facilisis turpis, habitant nascetur lectus tempor quisque habitasse urna scelerisque, nibh nullam vestibulum luctus aenean mollis metus. Suscipit gravida duis nec aliquet natoque molestie a ridiculus scelerisque cum, justo cursus sapien sodales purus dignissim vel facilisi magnis, inceptos rutrum ut integer auctor commodo sollicitudin fames et. Faucibus ligula nibh sagittis mauris auctor posuere habitant, scelerisque phasellus accumsan egestas gravida viverra nam, sed etiam eleifend proin massa dictumst. Porttitor risus luctus per aenean tellus primis fringilla vitae fames lacinia mauris metus, nec pulvinar quisque commodo sodales ac nibh natoque phasellus semper placerat. Lectus aenean potenti leo sollicitudin tristique eros quam ligula, vestibulum diam consequat enim torquent nec tempus, blandit viverra dapibus eleifend dis nunc nascetur.
## Sodales hendrerit malesuada et vestibulum
- Luctus euismod pretium nisi et, est dui enim.
- Curae eget inceptos malesuada, fermentum class.
- Porttitor vestibulum aliquam porta feugiat velit, potenti eu placerat.
- Ligula lacus tempus ac porta, vel litora.
Torquent non nisi lacinia faucibus nibh tortor taciti commodo porttitor, mus hendrerit id leo scelerisque mollis habitasse orci tristique aptent, lacus at molestie cubilia facilisis porta accumsan condimentum. Metus lacus suscipit porttitor integer facilisi torquent, nostra nulla platea at natoque varius venenatis, id quam pharetra aliquam leo. Dictum orci himenaeos quam mi fusce lacinia maecenas ac magna eleifend laoreet, vivamus enim curabitur ullamcorper est ultrices convallis suscipit nascetur. Ornare fames pretium ante ac eget nisi tellus vivamus, convallis mauris sapien imperdiet sollicitudin aliquet taciti quam, lacinia tempor primis magna iaculis at eu. Est facilisi proin risus eleifend orci torquent ultricies platea, quisque nullam vel porttitor euismod sociis non, maecenas sociosqu interdum arcu sed pharetra potenti. Aliquet risus tempus hendrerit sapien tellus eget cursus enim etiam dui, lobortis nostra pellentesque odio posuere morbi ad neque senectus arcu eu, turpis proin ac felis purus fames magnis dis dignissim.
Orci volutpat augue viverra scelerisque dictumst ut condimentum vivamus, accumsan cum sem sollicitudin aliquet vehicula porta pretium placerat, malesuada euismod primis cubilia rutrum tempus parturient. Urna mauris in nibh morbi hendrerit vulputate condimentum, iaculis consequat porttitor dui dis euismod eros, arcu elementum venenatis varius lectus nisi. Nibh arcu ultrices semper morbi quam aptent quisque porta posuere iaculis, vestibulum cum vitae primis varius natoque conubia eu. Placerat sociis sagittis sociosqu morbi purus lobortis convallis, bibendum tortor ridiculus orci habitasse viverra dictum, quis rutrum fusce potenti volutpat vehicula. Curae porta inceptos lectus mus urna litora semper aliquam libero rutrum sem dui maecenas ligula quis, eget risus non imperdiet cum morbi magnis suspendisse etiam augue porttitor placerat facilisi hendrerit. Et eleifend eget augue duis fringilla sagittis erat est habitasse commodo tristique quisque pretium, suspendisse imperdiet inceptos mollis blandit magna mus elementum molestie sed vestibulum. Euismod morbi hendrerit suscipit felis ornare libero ligula, mus tortor urna interdum blandit nisi netus posuere, purus fermentum magnis nam primis nulla.
## Elementum nisi urna cursus nisl quam ante tristique blandit ultricies eget
Netus at rutrum taciti vestibulum molestie conubia semper class potenti lobortis, hendrerit donec vitae ad libero natoque parturient litora congue. Torquent rhoncus odio cursus iaculis molestie arcu leo condimentum accumsan, laoreet congue duis libero justo tortor commodo fusce, massa eros hac euismod netus sodales mi magnis. Aenean nullam sollicitudin ad velit nulla venenatis suspendisse iaculis, aliquet senectus mollis aptent fringilla volutpat nascetur, nec urna vehicula lacinia neque augue orci. Suspendisse et eleifend convallis sollicitudin posuere diam turpis gravida congue ultrices, laoreet ultricies dapibus proin facilisis magna class praesent fusce. Mus morbi magnis ultricies sed turpis ultrices tempus tortor bibendum, netus nulla viverra torquent malesuada ridiculus tempor. Parturient sociosqu erat ullamcorper gravida natoque varius, etiam habitant augue praesent per curabitur iaculis, donec pellentesque cursus suscipit aliquet. Congue curae cursus scelerisque pellentesque quis fusce arcu eros dictumst luctus ridiculus nisl viverra, turpis class faucibus phasellus feugiat eleifend fringilla orci tristique habitasse conubia quam. Habitasse montes congue sodales rutrum cras torquent cursus auctor condimentum imperdiet egestas nascetur, platea tincidunt ut sollicitudin purus libero lobortis ad nisi diam quam.

View file

@ -0,0 +1,193 @@
---
draft: false
title: "Typography Example Post"
snippet: "Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat"
publishDate: "2022-11-05 15:36"
image: {
src: "https://images.unsplash.com/photo-1542393545-10f5cde2c810?&fit=crop&w=430&h=240",
alt: "typography"
}
category: "Technology"
author: "Charles North"
tags: [mdx, astro, blog]
---
import Button from "@components/ui/button.astro";
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
## <a name="Headings"></a>Headings
Sint sit cillum pariatur eiusmod nulla pariatur ipsum. Sit laborum anim qui mollit tempor pariatur nisi minim dolor. Aliquip et adipisicing sit sit fugiat commodo id sunt. Nostrud enim ad commodo incididunt cupidatat in ullamco ullamco Lorem cupidatat velit enim et Lorem. Ut laborum cillum laboris fugiat culpa sint irure do reprehenderit culpa occaecat. Exercitation esse mollit tempor magna aliqua in occaecat aliquip veniam reprehenderit nisi dolor in laboris dolore velit.
## Heading two
Aute officia nulla deserunt do deserunt cillum velit magna. Officia veniam culpa anim minim dolore labore pariatur voluptate id ad est duis quis velit dolor pariatur enim. Incididunt enim excepteur do veniam consequat culpa do voluptate dolor fugiat ad adipisicing sit. Labore officia est adipisicing dolore proident eiusmod exercitation deserunt ullamco anim do occaecat velit. Elit dolor consectetur proident sunt aliquip est do tempor quis aliqua culpa aute. Duis in tempor exercitation pariatur et adipisicing mollit irure tempor ut enim esse commodo laboris proident. Do excepteur laborum anim esse aliquip eu sit id Lorem incididunt elit irure ea nulla dolor et. Nulla amet fugiat qui minim deserunt enim eu cupidatat aute officia do velit ea reprehenderit.
### Heading three
Voluptate cupidatat cillum elit quis ipsum eu voluptate fugiat consectetur enim. Quis ut voluptate culpa ex anim aute consectetur dolore proident voluptate exercitation eiusmod. Esse in do anim magna minim culpa sint. Adipisicing ipsum consectetur proident ullamco magna sit amet aliqua aute fugiat laborum exercitation duis et.
#### Heading four
Commodo fugiat aliqua minim quis pariatur mollit id tempor. Non occaecat minim esse enim aliqua adipisicing nostrud duis consequat eu adipisicing qui. Minim aliquip sit excepteur ipsum consequat laborum pariatur excepteur. Veniam fugiat et amet ad elit anim laborum duis mollit occaecat et et ipsum et reprehenderit. Occaecat aliquip dolore adipisicing sint labore occaecat officia fugiat. Quis adipisicing exercitation exercitation eu amet est laboris sunt nostrud ipsum reprehenderit ullamco. Enim sint ut consectetur id anim aute voluptate exercitation mollit dolore magna magna est Lorem. Ut adipisicing adipisicing aliqua ullamco voluptate labore nisi tempor esse magna incididunt.
##### Heading five
Veniam enim esse amet veniam deserunt laboris amet enim consequat. Minim nostrud deserunt cillum consectetur commodo eu enim nostrud ullamco occaecat excepteur. Aliquip et ut est commodo enim dolor amet sint excepteur. Amet ad laboris laborum deserunt sint sunt aliqua commodo ex duis deserunt enim est ex labore ut. Duis incididunt velit adipisicing non incididunt adipisicing adipisicing. Ad irure duis nisi tempor eu dolor fugiat magna et consequat tempor eu ex dolore. Mollit esse nisi qui culpa ut nisi ex proident culpa cupidatat cillum culpa occaecat anim. Ut officia sit ea nisi ea excepteur nostrud ipsum et nulla.
###### Heading six
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
[[Top]](#top)
## <a name="Paragraphs"></a>Paragraphs
Incididunt ex adipisicing ea ullamco consectetur in voluptate proident fugiat tempor deserunt reprehenderit ullamco id dolore laborum. Do laboris laboris minim incididunt qui consectetur exercitation adipisicing dolore et magna consequat magna anim sunt. Officia fugiat Lorem sunt pariatur incididunt Lorem reprehenderit proident irure. Dolore ipsum aliqua mollit ad officia fugiat sit eu aliquip cupidatat ipsum duis laborum laborum fugiat esse. Voluptate anim ex dolore deserunt ea ex eiusmod irure. Occaecat excepteur aliqua exercitation aliquip dolor esse eu eu.
Officia dolore laborum aute incididunt commodo nisi velit est est elit et dolore elit exercitation. Enim aliquip magna id ipsum aliquip consectetur ad nulla quis. Incididunt pariatur dolor consectetur cillum enim velit cupidatat laborum quis ex.
Officia irure in non voluptate adipisicing sit amet tempor duis dolore deserunt enim ut. Reprehenderit incididunt in ad anim et deserunt deserunt Lorem laborum quis. Enim aute anim labore proident laboris voluptate elit excepteur in. Ex labore nulla velit officia ullamco Lorem Lorem id do. Dolore ullamco ipsum magna dolor pariatur voluptate ipsum id occaecat ipsum. Dolore tempor quis duis commodo quis quis enim.
[[Top]](#top)
## <a name="Blockquotes"></a>Blockquotes
Ad nisi laborum aute cupidatat magna deserunt eu id laboris id. Aliquip nulla cupidatat sint ex Lorem mollit laborum dolor amet est ut esse aute. Nostrud ex consequat id incididunt proident ipsum minim duis aliqua ut ex et ad quis. Laborum sint esse cillum anim nulla cillum consectetur aliqua sit. Nisi excepteur cillum labore amet excepteur commodo enim occaecat consequat ipsum proident exercitation duis id in.
> Ipsum et cupidatat mollit exercitation enim duis sunt irure aliqua reprehenderit mollit. Pariatur Lorem pariatur laboris do culpa do elit irure. Eiusmod amet nulla voluptate velit culpa et aliqua ad reprehenderit sit ut.
Labore ea magna Lorem consequat aliquip consectetur cillum duis dolore. Et veniam dolor qui incididunt minim amet laboris sit. Dolore ad esse commodo et dolore amet est velit ut nisi ea. Excepteur ea nulla commodo dolore anim dolore adipisicing eiusmod labore id enim esse quis mollit deserunt est. Minim ea culpa voluptate nostrud commodo proident in duis aliquip minim.
> Qui est sit et reprehenderit aute est esse enim aliqua id aliquip ea anim. Pariatur sint reprehenderit mollit velit voluptate enim consectetur sint enim. Quis exercitation proident elit non id qui culpa dolore esse aliquip consequat.
Ipsum excepteur cupidatat sunt minim ad eiusmod tempor sit.
> Deserunt excepteur adipisicing culpa pariatur cillum laboris ullamco nisi fugiat cillum officia. In cupidatat nulla aliquip tempor ad Lorem Lorem quis voluptate officia consectetur pariatur ex in est duis. Mollit id esse est elit exercitation voluptate nostrud nisi laborum magna dolore dolore tempor in est consectetur.
Adipisicing voluptate ipsum culpa voluptate id aute laboris labore esse fugiat veniam ullamco occaecat do ut. Tempor et esse reprehenderit veniam proident ipsum irure sit ullamco et labore ea excepteur nulla labore ut. Ex aute minim quis tempor in eu id id irure ea nostrud dolor esse.
[[Top]](#top)
## <a name="Lists"></a>Lists
### Ordered List
1. Longan
2. Lychee
3. Excepteur ad cupidatat do elit laborum amet cillum reprehenderit consequat quis.
Deserunt officia esse aliquip consectetur duis ut labore laborum commodo aliquip aliquip velit pariatur dolore.
4. Marionberry
5. Melon
- Cantaloupe
- Honeydew
- Watermelon
6. Miracle fruit
7. Mulberry
### Unordered List
- Olive
- Orange
- Blood orange
- Clementine
- Papaya
- Ut aute ipsum occaecat nisi culpa Lorem id occaecat cupidatat id id magna laboris ad duis. Fugiat cillum dolore veniam nostrud proident sint consectetur eiusmod irure adipisicing.
- Passionfruit
[[Top]](#top)
## <a name="Horizontal"></a>Horizontal rule
In dolore velit aliquip labore mollit minim tempor veniam eu veniam ad in sint aliquip mollit mollit. Ex occaecat non deserunt elit laborum sunt tempor sint consequat culpa culpa qui sit. Irure ad commodo eu voluptate mollit cillum cupidatat veniam proident amet minim reprehenderit.
---
In laboris eiusmod reprehenderit aliquip sit proident occaecat. Non sit labore anim elit veniam Lorem minim commodo eiusmod irure do minim nisi. Dolor amet cillum excepteur consequat sint non sint.
[[Top]](#top)
## <a name="Table"></a>Table
Duis sunt ut pariatur reprehenderit mollit mollit magna dolore in pariatur nulla commodo sit dolor ad fugiat. Laboris amet ea occaecat duis eu enim exercitation deserunt ea laborum occaecat reprehenderit. Et incididunt dolor commodo consequat mollit nisi proident non pariatur in et incididunt id. Eu ut et Lorem ea ex magna minim ipsum ipsum do.
| Table Heading 1 | Table Heading 2 | Center align | Right align | Table Heading 5 |
| :-------------- | :-------------- | :----------: | ----------: | :-------------- |
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
| Item 1 | Item 2 | Item 3 | Item 4 | Item 5 |
Minim id consequat adipisicing cupidatat laborum culpa veniam non consectetur et duis pariatur reprehenderit eu ex consectetur. Sunt nisi qui eiusmod ut cillum laborum Lorem officia aliquip laboris ullamco nostrud laboris non irure laboris. Cillum dolore labore Lorem deserunt mollit voluptate esse incididunt ex dolor.
[[Top]](#top)
## <a name="Code"></a>Code
### Inline code
Ad amet irure est magna id mollit Lorem in do duis enim. Excepteur velit nisi magna ea pariatur pariatur ullamco fugiat deserunt sint non sint. Duis duis est `code in text` velit velit aute culpa ex quis pariatur pariatur laborum aute pariatur duis tempor sunt ad. Irure magna voluptate dolore consectetur consectetur irure esse. Anim magna `<strong>in culpa qui officia</strong>` dolor eiusmod esse amet aute cupidatat aliqua do id voluptate cupidatat reprehenderit amet labore deserunt.
### Highlighted
Et fugiat ad nisi amet magna labore do cillum fugiat occaecat cillum Lorem proident. In sint dolor ullamco ad do adipisicing amet id excepteur Lorem aliquip sit irure veniam laborum duis cillum. Aliqua occaecat minim cillum deserunt magna sunt laboris do do irure ea nostrud consequat ut voluptate ex.
```go
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
```
Ex amet id ex aliquip id do laborum excepteur exercitation elit sint commodo occaecat nostrud est. Nostrud pariatur esse veniam laborum non sint magna sit laboris minim in id. Aliqua pariatur pariatur excepteur adipisicing irure culpa consequat commodo et ex id ad.
[[Top]](#top)
## <a name="Inline"></a>Inline elements
Sint ea anim ipsum ad commodo cupidatat do **exercitation** incididunt et minim ad labore sunt. Minim deserunt labore laboris velit nulla incididunt ipsum nulla. Ullamco ad laborum ea qui et anim in laboris exercitation tempor sit officia laborum reprehenderit culpa velit quis. **Consequat commodo** reprehenderit duis [irure](#!) esse esse exercitation minim enim Lorem dolore duis irure. Nisi Lorem reprehenderit ea amet excepteur dolor excepteur magna labore proident voluptate ipsum. Reprehenderit ex esse deserunt aliqua ea officia mollit Lorem nulla magna enim. Et ad ipsum labore enim ipsum **cupidatat consequat**. Commodo non ea cupidatat magna deserunt dolore ipsum velit nulla elit veniam nulla eiusmod proident officia.
![Super wide](https://images.unsplash.com/photo-1471128466710-c26ff0d26143?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY2MDc4MTk3Mw&ixlib=rb-1.2.1&q=80&utm_campaign=api-credit&utm_medium=referral&utm_source=unsplash_source&w=1080)
_Proident sit veniam in est proident officia adipisicing_ ea tempor cillum non cillum velit deserunt. Voluptate laborum incididunt sit consectetur Lorem irure incididunt voluptate nostrud. Commodo ut eiusmod tempor cupidatat esse enim minim ex anim consequat. Mollit sint culpa qui laboris quis consectetur ad sint esse. Amet anim anim minim ullamco et duis non irure. Sit tempor adipisicing ea laboris `culpa ex duis sint` anim aute reprehenderit id eu ea. Aute [excepteur proident](#!) Lorem minim adipisicing nostrud mollit ad ut voluptate do nulla esse occaecat aliqua sint anim.
![Not so big](https://placekitten.com/480/400)
Incididunt in culpa cupidatat mollit cillum qui proident sit. In cillum aliquip incididunt voluptate magna amet cupidatat cillum pariatur sint aliqua est _enim **anim** voluptate_. Magna aliquip proident incididunt id duis pariatur eiusmod incididunt commodo culpa dolore sit. Culpa do nostrud elit ad exercitation anim pariatur non minim nisi **adipisicing sunt _officia_**. Do deserunt magna mollit Lorem commodo ipsum do cupidatat mollit enim ut elit veniam ea voluptate.
Reprehenderit non eu quis in ad elit esse qui aute id [incididunt](#!) dolore cillum. Esse laboris consequat dolor anim exercitation tempor aliqua deserunt velit magna laboris. Culpa culpa minim duis amet mollit do quis amet commodo nulla irure.
[[Top]](#top)
## MDX
```js
---
publishDate: 'Aug 02 2022'
title: 'Markdown elements demo post'
---
import Logo from "@components/ui/button.astro";
## MDX
<Button>Click</Button>
```
<div>
<Button>Click Me</Button>
</div>
[[Top]](#top)

39
src/content/config.ts Normal file
View file

@ -0,0 +1,39 @@
// 1. Import utilities from `astro:content`
import { z, defineCollection } from 'astro:content';
// 2. Define your collection(s)
const blogCollection = defineCollection({
schema: z.object({
draft: z.boolean(),
title: z.string(),
snippet: z.string(),
image: z.object({
src: z.string(),
alt: z.string(),
}),
publishDate: z.string().transform(str => new Date(str)),
author: z.string().default('Astroship'),
category: z.string(),
tags: z.array(z.string()),
}),
});
const teamCollection = defineCollection({
schema: z.object({
draft: z.boolean(),
name: z.string(),
title: z.string(),
avatar: z.object({
src: z.string(),
alt: z.string(),
}),
publishDate: z.string().transform(str => new Date(str)),
}),
});
// 3. Export a single `collections` object to register your collection(s)
// This key should match your collection directory name in "src/content"
export const collections = {
'blog': blogCollection,
'team': teamCollection,
};

View file

@ -0,0 +1,10 @@
---
draft: false
name: "Janette Lynch"
title: "Senior Director"
avatar: {
src: "https://images.unsplash.com/photo-1580489944761-15a19d654956?&fit=crop&w=280",
alt: "Janette Lynch"
}
publishDate: "2022-11-07 15:39"
---

View file

@ -0,0 +1,10 @@
---
draft: false
name: "Marcell Ziemann"
title: "Principal Strategist"
avatar: {
src: "https://images.unsplash.com/photo-1633332755192-727a05c4013d?&fit=crop&w=280",
alt: "Marcell Ziemann"
}
publishDate: "2022-11-08 15:39"
---

View file

@ -0,0 +1,10 @@
---
draft: false
name: "Robert Palmer"
title: "Marketing Engineer"
avatar: {
src: "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?&fit=crop&w=280",
alt: "Robert Palmer"
}
publishDate: "2022-11-09 15:39"
---

View file

@ -0,0 +1,50 @@
---
import Container from "@components/container.astro";
import { getFormattedDate } from "@utils/all";
import { log } from "astro/dist/core/logger/core";
import Layout from "./Layout.astro";
const { frontmatter } = Astro.props;
---
<Layout title={frontmatter.title}>
<Container>
<div class="mx-auto max-w-[735px] mt-14">
<span class="text-blue-400 uppercase tracking-wider text-sm font-medium">
{frontmatter.category}
</span>
<h1
class="text-4xl lg:text-5xl font-bold lg:tracking-tight mt-1 lg:leading-tight">
{frontmatter.title}
</h1>
<div class="flex gap-2 mt-3 items-center flex-wrap md:flex-nowrap">
<span class="text-gray-400">
{frontmatter.author}
</span>
<span class="text-gray-400">•</span>
<time class="text-gray-400" datetime={frontmatter.publishDate}>
{getFormattedDate(frontmatter.publishDate)}
</time>
<span class="text-gray-400 hidden md:block">•</span>
<div class="w-full md:w-auto flex flex-wrap gap-3">
{
frontmatter.tags.map((tag) => (
<span class="text-sm text-gray-500">#{tag}</span>
))
}
</div>
</div>
</div>
<div class="mx-auto prose prose-lg mt-6">
<slot />
</div>
<div class="text-center mt-8">
<a
href="/blog"
class="bg-gray-100 px-5 py-3 rounded-md hover:bg-gray-200 transition"
>← Back to Blog</a
>
</div>
</Container>
</Layout>

68
src/layouts/Layout.astro Normal file
View file

@ -0,0 +1,68 @@
---
import { SEO } from "astro-seo";
import Footer from "@components/footer.astro";
import Navbar from "@components/navbar/navbar.astro";
import "@fontsource/inter/variable.css";
export interface Props {
title: string;
}
const canonicalURL = new URL(Astro.url.pathname, Astro.site).toString();
const resolvedImageWithDomain = new URL(
"/opengraph.jpg",
Astro.site
).toString();
const { title } = Astro.props;
const makeTitle = title
? title + " | " + "Astroship"
: "Astroship - Starter Template for Astro with Tailwind CSS";
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="generator" content={Astro.generator} />
<!-- <link rel="preload" as="image" href={src} alt="Hero" /> -->
<SEO
title={makeTitle}
description="Astroship is a starter website template for Astro built with TailwindCSS."
canonical={canonicalURL}
twitter={{
creator: "@surjithctly",
site: "@web3templates",
card: "summary_large_image",
}}
openGraph={{
basic: {
url: canonicalURL,
type: "website",
title: `Astroship - Starter Template for Astro`,
image: resolvedImageWithDomain,
},
image: {
alt: "Astroship Homepage Screenshot",
},
}}
/>
</head>
<body>
<Navbar />
<slot />
<Footer />
<style is:global>
/* Improve Page speed */
/* https://css-tricks.com/almanac/properties/c/content-visibility/ */
img {
content-visibility: auto;
}
</style>
</body>
</html>

62
src/pages/about.astro Normal file
View file

@ -0,0 +1,62 @@
---
import { getCollection } from "astro:content";
import { Picture } from "@astrojs/image/components";
import Layout from "@layouts/Layout.astro";
import Container from "@components/container.astro";
import Sectionhead from "@components/sectionhead.astro";
// Filter team entries with 'draft: false' & date before current date
const publishedTeamMembers = await getCollection("team", ({ data }) => {
return !data.draft && data.publishDate < new Date();
});
---
<Layout title="About">
<Container>
<Sectionhead>
<Fragment slot="title">About</Fragment>
<Fragment slot="desc">We are a small passionate team.</Fragment>
</Sectionhead>
<div class="flex flex-col gap-3 mx-auto max-w-4xl mt-16">
<h2 class="font-bold text-3xl text-gray-800">
Empowering the world with Astro.
</h2>
<p class="text-lg leading-relaxed text-slate-500">
We're a multi-cultural team from around the world! We come from diverse
backgrounds, bringing different personalities, experiences and skills to
the job. This is what makes our team so special.
</p>
</div>
<div class="grid md:grid-cols-3 gap-10 mx-auto max-w-4xl mt-12">
{
publishedTeamMembers.map((teamMemberEntry) => (
<div class="group">
<div class="w-full aspect-square">
<Picture
src={teamMemberEntry.data.avatar.src}
alt={teamMemberEntry.data.avatar.alt}
sizes="(max-width: 800px) 100vw, 400px"
widths={[200, 400]}
aspectRatio="1:1"
background="#ffffff"
fit="cover"
position="center"
class="w-full rounded-md rounded transition group-hover:-translate-y-1 group-hover:shadow-xl"
/>
</div>
<div class="mt-4 text-center">
<h2 class="text-lg text-gray-800">
{teamMemberEntry.data.name}
</h2>
<h3 class="text-sm text-slate-500">
{teamMemberEntry.data.title}
</h3>
</div>
</div>
))
}
</div>
</Container>
</Layout>

76
src/pages/blog.astro Normal file
View file

@ -0,0 +1,76 @@
---
import { getCollection } from "astro:content";
import { Picture } from "@astrojs/image/components";
import Layout from "@layouts/Layout.astro";
import Container from "@components/container.astro";
import Sectionhead from "@components/sectionhead.astro";
// Filter blog entries with 'draft: false' & date before current date
const publishedBlogEntries = await getCollection("blog", ({ data }) => {
return !data.draft && data.publishDate < new Date();
});
// Sort content entries by publication date
publishedBlogEntries.sort(function (a, b) {
return b.data.publishDate.valueOf() - a.data.publishDate.valueOf();
});
---
<Layout title="Blog">
<Container>
<Sectionhead>
<Fragment slot="title">Our Blog</Fragment>
<Fragment slot="desc">
We write about building startups and thoughts going on our mind.
</Fragment>
</Sectionhead>
<main class="mt-16">
<ul class="grid gap-16 max-w-4xl mx-auto">
{
publishedBlogEntries.map((blogPostEntry, index) => (
<li>
<a href={`/blog/${blogPostEntry.slug}`}>
<div class="grid md:grid-cols-2 gap-5 md:gap-10 items-center">
<Picture
src={blogPostEntry.data.image.src}
alt={blogPostEntry.data.image.alt}
sizes="(max-width: 800px) 100vw, 800px"
widths={[200, 400, 800]}
aspectRatio="16:9"
background="#ffffff"
fit="cover"
position="center"
loading={index <= 2 ? "eager" : "lazy"}
decoding={index <= 2 ? "sync" : "async"}
class="w-full rounded-md"
/>
<div>
<span class="text-blue-400 uppercase tracking-wider text-sm font-medium">
{blogPostEntry.data.category}
</span>
<h2 class="text-3xl font-semibold leading-snug tracking-tight mt-1 ">
{blogPostEntry.data.title}
</h2>
<div class="flex gap-2 mt-3">
<span class="text-gray-400">
{blogPostEntry.data.author}
</span>
<span class="text-gray-400">• </span>
<time
class="text-gray-400"
datetime={blogPostEntry.data.publishDate.toISOString()}>
{blogPostEntry.data.publishDate.toDateString()}
</time>
</div>
</div>
</div>
</a>
</li>
))
}
</ul>
</main>
</Container>
</Layout>

View file

@ -0,0 +1,62 @@
---
import { getCollection } from "astro:content";
import Layout from "@layouts/Layout.astro";
import Container from "@components/container.astro";
// Generate a new path for every collection entry
export async function getStaticPaths() {
const blogEntries = await getCollection("blog");
return blogEntries.map((entry) => ({
params: { slug: entry.slug },
props: { entry },
}));
}
// Get the entry directly from the prop on render
const { entry } = Astro.props;
const { Content } = await entry.render();
---
<Layout title={entry.data.title}>
<Container>
<div class="mx-auto max-w-[735px] mt-14">
<span class="text-blue-400 uppercase tracking-wider text-sm font-medium">
{entry.data.category}
</span>
<h1
class="text-4xl lg:text-5xl font-bold lg:tracking-tight mt-1 lg:leading-tight">
{entry.data.title}
</h1>
<div class="flex gap-2 mt-3 items-center flex-wrap md:flex-nowrap">
<span class="text-gray-400">
{entry.data.author}
</span>
<span class="text-gray-400">•</span>
<time
class="text-gray-400"
datetime={entry.data.publishDate.toISOString()}>
{entry.data.publishDate.toDateString()}
</time>
<span class="text-gray-400 hidden md:block">•</span>
<div class="w-full md:w-auto flex flex-wrap gap-3">
{
entry.data.tags.map((tag) => (
<span class="text-sm text-gray-500">#{tag}</span>
))
}
</div>
</div>
</div>
<div class="mx-auto prose prose-lg mt-6">
<Content />
</div>
<div class="text-center mt-8">
<a
href="/blog"
class="bg-gray-100 px-5 py-3 rounded-md hover:bg-gray-200 transition"
>← Back to Blog</a
>
</div>
</Container>
</Layout>

45
src/pages/contact.astro Normal file
View file

@ -0,0 +1,45 @@
---
import { Icon } from "astro-icon";
import Layout from "@layouts/Layout.astro";
import Container from "@components/container.astro";
import Sectionhead from "@components/sectionhead.astro";
import Button from "@components/ui/button.astro";
import Contactform from "@components/contactform.astro";
---
<Layout title="Contact">
<Container>
<Sectionhead>
<Fragment slot="title">Contact</Fragment>
<Fragment slot="desc">We are a here to help.</Fragment>
</Sectionhead>
<div class="grid md:grid-cols-2 gap-10 mx-auto max-w-4xl mt-16">
<div>
<h2 class="font-medium text-2xl text-gray-800">Contact Astroship</h2>
<p class="text-lg leading-relaxed text-slate-500 mt-3">
Have something to say? We are here to help. Fill up the form or send
email or call phone.
</p>
<div class="mt-5">
<div class="flex items-center mt-2 space-x-2 text-gray-600">
<Icon class="text-gray-400 w-4 h-4" name="uil:map-marker" />
<span>1734 Sanfransico, CA 93063</span>
</div><div class="flex items-center mt-2 space-x-2 text-gray-600">
<Icon class="text-gray-400 w-4 h-4" name="uil:envelope" /><a
href="mailto:hello@astroshipstarter.com"
>hello@astroshipstarter.com</a
>
</div><div class="flex items-center mt-2 space-x-2 text-gray-600">
<Icon class="text-gray-400 w-4 h-4" name="uil:phone" /><a
href="tel:+1 (987) 4587 899">+1 (987) 4587 899</a
>
</div>
</div>
</div>
<div>
<Contactform />
</div>
</div>
</Container>
</Layout>

18
src/pages/index.astro Normal file
View file

@ -0,0 +1,18 @@
---
import Container from "@components/container.astro";
import Cta from "@components/cta.astro";
import Features from "@components/features.astro";
import Footer from "@components/footer.astro";
import Hero from "@components/hero.astro";
import Logos from "@components/logos.astro";
import Layout from "@layouts/Layout.astro";
---
<Layout title="">
<Container>
<Hero />
<Features />
<Logos />
<Cta />
</Container>
</Layout>

80
src/pages/pricing.astro Normal file
View file

@ -0,0 +1,80 @@
---
import Layout from "@layouts/Layout.astro";
import Container from "@components/container.astro";
import Sectionhead from "@components/sectionhead.astro";
import Pricing from "@components/pricing.astro";
const pricing = [
{
name: "Personal",
price: "Free",
popular: false,
features: [
"Lifetime free",
"Up to 3 users",
"Unlimited Pages",
"Astro Sub domain",
"Basic Integrations",
"Community Support",
],
button: {
text: "Get Started",
link: "/",
},
},
{
name: "Startup",
price: {
monthly: "$19",
annual: "$16",
discount: "10%",
original: "$24",
},
popular: true,
features: [
"All Free Features",
"Up to 20 users",
"20 Custom domains",
"Unlimited Collaborators",
"Advanced Integrations",
"Priority Support",
],
button: {
text: "Get Started",
link: "#",
},
},
{
name: "Enterprise",
price: "Custom",
popular: false,
features: [
"All Pro Features",
"Unlimited Custom domains",
"99.99% Uptime SLA",
"SAML & SSO Integration",
"Dedicated Account Manager",
"24/7 Phone Support",
],
button: {
text: "Contact us",
link: "/contact",
},
},
];
---
<Layout title="Pricing">
<Container>
<Sectionhead>
<Fragment slot="title">Pricing</Fragment>
<Fragment slot="desc"
>Simple & Predictable pricing. No Surprises.</Fragment
>
</Sectionhead>
<div class="grid md:grid-cols-3 gap-10 mx-auto max-w-screen-lg mt-12">
{pricing.map((item) => <Pricing plan={item} />)}
</div>
</Container>
</Layout>

9
src/utils/all.js Normal file
View file

@ -0,0 +1,9 @@
/** */
export const getFormattedDate = (date) =>
date
? new Date(date).toLocaleDateString("en-us", {
year: "numeric",
month: "short",
day: "numeric",
})
: "";

13
tailwind.config.cjs Normal file
View file

@ -0,0 +1,13 @@
/** @type {import('tailwindcss').Config} */
const defaultTheme = require("tailwindcss/defaultTheme");
module.exports = {
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
theme: {
extend: {
fontFamily: {
sans: ["InterVariable", "Inter", ...defaultTheme.fontFamily.sans],
},
},
},
plugins: [require("@tailwindcss/typography")],
};

27
tsconfig.json Normal file
View file

@ -0,0 +1,27 @@
{
"extends": "astro/tsconfigs/base",
"compilerOptions": {
"strictNullChecks": true,
"baseUrl": "src",
"paths": {
"@lib/*": [
"lib/*"
],
"@utils/*": [
"utils/*"
],
"@components/*": [
"components/*"
],
"@layouts/*": [
"layouts/*"
],
"@assets/*": [
"assets/*"
],
"@pages/*": [
"pages/*"
],
}
}
}

4308
yarn.lock Normal file

File diff suppressed because it is too large Load diff